Skip to content

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

Open
adityamparikh wants to merge 1 commit into
apache:mainfrom
adityamparikh:fix/unified-collection-validation
Open

fix: validate collection name consistently across all MCP tool methods#108
adityamparikh wants to merge 1 commit 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 three 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 already duplicated on main: a BLANK_COLLECTION_NAME_ERROR constant in CollectionService and a copied string literal in SchemaService's private requireCollection.

Changes

  • Extract one shared ToolArguments.requireCollection(String) into the util package and route all eleven call sites through it, so the four services cannot drift apart. SchemaService's private duplicate is removed.
  • Single message: "Collection name cannot be null or empty", aligned with the document-creator family in fix(indexing): reject blank document input consistently across formats #105. SchemaService's sibling requireNonEmpty helper is aligned to the same wording.

Coverage after this change:

Service Methods now validated
CollectionService createCollection*, getCollectionStats, checkHealth
IndexingService indexJsonDocuments, indexCsvDocuments, indexXmlDocuments
SchemaService getSchema, getSchemaResource, addFields, addFieldTypes
SearchService search

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

Why a runtime null check in @NullMarked code

The package is @NullMarked with NullAway wired as a build error, so this may look redundant. It isn't — NullAway is a closed-world compile-time analysis and only binds callers the compiler can see.

MCP tool methods are invoked reflectively by the Spring AI annotation runtime: AbstractMcpToolMethodCallback resolves each parameter with a plain lookup against the request's argument map and passes the result straight to buildTypedArgument, which returns null for a null input. 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.

The rationale is recorded on ToolArguments so it doesn't get "cleaned up" later.

Test plan

  • ./gradlew build passes
  • New CollectionNameValidationTest (9 tests, all green) asserts every entry point against the shared constant rather than a copied literal — that is what keeps the services from drifting
  • No regressions

Companion to #105, which applies the same treatment to document-input validation and uses the same message wording.

🤖 Generated with Claude Code

@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>
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