adityamparikh opened a new issue, #209:
URL: https://github.com/apache/solr-mcp/issues/209
## Motivation
The `search` tool
(`src/main/java/org/apache/solr/mcp/server/search/SearchService.java`)
currently exposes seven parameters:
| Parameter | Solr equivalent |
|---|---|
| `collection` | path |
| `query` | `q` |
| `filterQueries` | `fq` |
| `facetFields` | `facet.field` (with `facet.mincount=1`, `facet.sort=count`
hard-coded) |
| `sortClauses` | `sort` |
| `start` | `start` |
| `rows` | `rows` |
That covers the basic "find documents" loop, but an LLM client hits walls
quickly:
- **Every document comes back whole.** There is no `fl`, so a 20-row result
over a wide schema burns thousands of tokens on fields the model never asked
for. Field selection is the single biggest lever on cost and context window for
MCP clients.
- **No relevance signal per document.** `maxScore` is on the response, but
the per-document `score` pseudo-field can only be requested via `fl`.
- **No snippets.** Without highlighting the model has to read full bodies to
find *why* a document matched.
- **Faceting is field-only.** No range facets (dates, prices), no facet
queries, and `mincount`/`limit` cannot be tuned. PR #162 declares "field facets
only" in the server instructions precisely because this is the current surface.
- **Deep pagination is `start`-only.** Solr recommends `cursorMark` for
anything past the first few pages; large `start` offsets are expensive on the
server.
## Proposal
Add optional parameters to the existing `search` tool. All are `required =
false`, so this is backward compatible. Nothing here adds a new tool.
### Tier 1: high value, low risk
| Parameter | Type | Solr | Notes |
|---|---|---|---|
| `fields` | `List<String>` | `fl` | Field list to return. Allow `score` so
clients can request per-doc relevance. Cuts response token cost dramatically. |
| `highlightFields` | `List<String>` | `hl=true`, `hl.fl` | Adds a
`highlighting` map (`docId -> field -> [snippets]`) to `SearchResponse`.
Optionally `highlightSnippets` / `highlightFragsize`. |
| `facetMinCount` | `Integer` | `facet.mincount` | Currently hard-coded to
1. |
| `facetLimit` | `Integer` | `facet.limit` | Solr default is 100; models
often want top 5–10. |
| `defaultOperator` | `AND`/`OR` enum | `q.op` | Lets the client tighten
recall without rewriting the query. |
### Tier 2: worthwhile, needs a small design
| Parameter | Type | Solr | Notes |
|---|---|---|---|
| `facetQueries` | `List<String>` | `facet.query` | Arbitrary bucket counts
(`price:[* TO 10]`). Response gains a `facetQueries` map. |
| `rangeFacets` | `List<RangeFacet>` | `facet.range` + `start`/`end`/`gap` |
Typed record `(field, start, end, gap)` following the `SortClause` pattern from
PR #164. Needs a `SolrNativeHints` entry. |
| `cursorMark` | `String` | `cursorMark` | Response returns
`nextCursorMark`. Requires a sort that ends on the unique key; the tool should
validate that and give a remediation hint (see PR #166 style). |
| `timeAllowed` | `Integer` | `timeAllowed` | Bounded query time for agent
loops; response should surface `partialResults`. |
### Deliberately out of scope for this issue
- **Separate `defType` / `qf` / `mm` / `pf` / `bq` parameters.** PR #161
chose to document local params in `q` (`{!edismax qf='name author' mm=2}`)
instead of adding parameters. Revisiting that is a separate discussion:
explicit parameters would let the server escape values (cf. closed #122 on
local-param injection) but widen the surface. Not proposed here.
- **`debugQuery`, KNN / vector search, grouping, MoreLikeThis, spellcheck.**
#162 explicitly declares debugQuery and KNN out of the tool surface; #64 tracks
semantic/hybrid search separately.
- **JSON Facet API (`json.facet`).** Powerful but effectively an untyped
DSL; better as its own follow-up once Tier 1/2 lands.
## Implementation notes
- `SearchResponse` will gain `highlighting` (and later `facetQueries`,
`rangeFacets`, `nextCursorMark`). It is registered in `SolrNativeHints`, so any
new nested record needs a hint too or the native image will fail at runtime.
- Update the `search` tool description and the
`spring.ai.mcp.server.instructions` text from #162 ("field facets only") in the
same PR as the facet changes, so the declared boundaries stay truthful.
- Tests: unit test per parameter in `SearchServiceTest`, plus Testcontainers
coverage for highlighting, range facets and `cursorMark` since those depend on
real Solr behaviour (mocks would be tautological).
- Suggest landing Tier 1 as one PR and each Tier 2 parameter as its own
small PR.
## Acceptance criteria
- [ ] `fields` limits returned document fields and `score` works as a
pseudo-field
- [ ] `highlightFields` returns snippets in the response
- [ ] `facetMinCount` / `facetLimit` / `defaultOperator` are honoured
- [ ] Existing calls with only the current seven parameters behave exactly
as before
- [ ] Tool description and server instructions updated to match the new
surface
- [ ] `./gradlew build` and `./gradlew nativeTest -Pnative` pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]