Skip to content

fix: validate collection name consistently across all MCP tool methods - #108

Open
adityamparikh wants to merge 3 commits into
apache:mainfrom
adityamparikh:fix/unified-collection-validation
Open

adityamparikh wants to merge 3 commits into
apache:mainfrom
adityamparikh:fix/unified-collection-validation

Conversation

@adityamparikh

@adityamparikh adityamparikh commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Summary

Only createCollection and the two schema-modification tools validated the collection name. checkHealth, getCollectionStats, search, the four index*Documents tools, getSchema and getSchemaResource accepted null or blank and failed downstream, and a null collection reaching SolrJ silently targets the client's default collection rather than reporting a bad argument. The message was also duplicated: a constant in CollectionService and a copied literal in SchemaService.

Changes

  • One shared ToolArguments.requireCollection(String) in the util package, called by all twelve entry points, so the four services cannot drift apart. SchemaService's private duplicate is removed.
  • Single message: "Collection name cannot be null or empty".
Service Methods validated
CollectionService createCollection*, getCollectionStats, checkHealth
IndexingService indexJsonDocuments, indexCsvDocuments, indexXmlDocuments, indexMarkdownDocuments
SchemaService getSchema, getSchemaResource, addFields, addFieldTypes
SearchService search

* already validated on main; switched to the shared helper.

Why a runtime null check in @NullMarked code

NullAway is a compile-time analysis and only binds callers the compiler can see. MCP tool methods are invoked reflectively by the Spring AI annotation runtime, which looks each parameter up in the request's argument map and passes null through for a missing value. @McpToolParam(required = true) only marks the parameter required in the advertised JSON schema; the MCP SDK on main (0.18) does not validate incoming arguments against it. The rationale is recorded on ToolArguments.

Verification

Touches the same SchemaService.getSchema lines as #98; whichever merges second needs a one-line rebase.

🤖 Generated with Claude Code

https://claude.ai/code/session_01CiUHyyXLTo9ATdgg8eRFZJ

@adityamparikh
adityamparikh force-pushed the fix/unified-collection-validation branch from 14c39e5 to d8ddc16 Compare May 2, 2026 17:04
@adityamparikh
adityamparikh force-pushed the fix/unified-collection-validation branch from d8ddc16 to 2c77c92 Compare June 14, 2026 03:39
@adityamparikh
adityamparikh force-pushed the fix/unified-collection-validation branch from 2c77c92 to d918d29 Compare August 18, 2026 21:25
@adityamparikh adityamparikh changed the title fix: add consistent collection name validation to all MCP tool methods fix: validate collection name consistently across all MCP tool methods Aug 18, 2026
@adityamparikh
adityamparikh force-pushed the fix/unified-collection-validation branch from d918d29 to 5f0eb18 Compare August 18, 2026 21:31
Only createCollection and the two schema-modification tools validated the
collection name. checkHealth, getCollectionStats, search, the three
index*Documents tools, getSchema and getSchemaResource accepted null or blank
and failed downstream — a null collection reaches SolrJ and silently targets
the client's default collection rather than reporting a bad argument.

The message was already duplicated on main: a BLANK_COLLECTION_NAME_ERROR
constant in CollectionService and a copied string literal in SchemaService's
private requireCollection. Extract one shared
ToolArguments.requireCollection(String) in the util package and route all
eleven call sites through it, so the four services cannot drift apart.

Message wording is aligned with the document-creator family
("<Subject> cannot be null or empty"), which also covers SchemaService's
sibling requireNonEmpty helper.

The null half of the check is deliberate rather than redundant defensive
coding: the package is @NullMarked with NullAway as a build error, but that
analysis only binds callers the compiler can see. MCP tool methods are invoked
reflectively by the Spring AI annotation runtime, which resolves each parameter
with a plain lookup against the request's argument map and passes the result
straight through — a missing or null JSON value therefore arrives as null no
matter what the annotations declare. @McpToolParam(required = true) only marks
the parameter required in the advertised JSON schema; the server does not
validate incoming arguments against it.

CollectionNameValidationTest asserts all nine entry points against the shared
constant rather than a copied literal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
adityamparikh and others added 2 commits September 12, 2026 23:20
main gained indexMarkdownDocuments after this branch's merge base; it is now
guarded like the other tools and covered by CollectionNameValidationTest.
Reverts an unrelated rewording of SchemaService.requireNonEmpty.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CiUHyyXLTo9ATdgg8eRFZJ
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant