Skip to content

fix: advertise Data API clause JSON in MCP schemas - #2619

Merged
erichare merged 39 commits into
mainfrom
fix/mcp-clause-wire-schemas
Oct 23, 2026
Merged

erichare merged 39 commits into
mainfrom
fix/mcp-clause-wire-schemas

Conversation

@erichare

@erichare erichare commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does:

Uses OpenAPI annotations on the owning models to describe clause JSON accepted by Data API parsers. The existing generator remains the fallback. Nested authentication and parameters maps in rerank overrides accept empty and null values, including authentication maps for shared-secret providers. Contract tests compare schema acceptance with runtime behavior.

This builds on #2644. Merge #2618 first so the parser and schema reject the same conflicting vector sort keys.

Which issue(s) this PR fixes:

Addresses the schema portion of #2604.

Verification

All 89 focused tests passed with no failures, errors, or skips on this branch with the cleanup.

JAVA_HOME=/Library/Java/JavaVirtualMachines/graalvm-21.jdk/Contents/Home ./mvnw -B -ntp test -Dtest=McpProtocolTest,McpClauseSchemaContractTest,McpOpenApiSchemaAdapterTest,McpSchemaCustomizerTest -DskipITs -Dxml-format.skip=true

Packaged integration tests and manual client checks were not rerun in this sweep.

Checklist

  • Changes manually tested
  • Automated Tests added/updated
  • Documentation added/updated
  • CLA Signed: DataStax CLA

RED: schema contract tests compile and execute on Java 21, with seven schema failures and one malformed OpenAPI example error.
GREEN: 124 MCP schema, parser, builder, and ObjectMapper tests pass on Java 21. Schema examples validate and deserialize, and rerank override fields remain scoped to the request.
Align the HTTP and MCP hybrid descriptions. All 124 targeted tests, formatting, and the packaged build pass on Java 21.
@erichare
erichare requested a review from a team as a code owner October 6, 2026 22:10
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

📈 Unit Test Coverage Delta vs Main Branch

Metric Value
Main Branch 54.71%
This PR 55.07%
Delta 🟢 +0.36%
✅ Coverage improved!

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Unit Test Coverage Report

Overall Project 55.07% -0.04% 🍏
Files changed 93.35% 🍏

File Coverage
McpSchemaCustomizer.java 100% 🍏
FilterDefinition.java 100% 🍏
JsonDefinition.java 100% 🍏
McpOpenApiSchemaAdapter.java 94.05% -5.95% 🍏
FindAndRerankSort.java 91.96% -8.04% ❌
FindAndRerankCommand.java 86.36% -2.73% ❌
SortDefinition.java 56.52% 🍏
CollectionCommandTools.java 0% 🍏

@erichare erichare linked an issue Oct 6, 2026 that may be closed by this pull request
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

📈 Integration Test Coverage Delta vs Main Branch (dse69-it)

Metric Value
Main Branch 72.95%
This PR 73.04%
Delta 🟢 +0.09%
✅ Coverage improved!

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Integration Test Coverage Report (dse69-it)

Overall Project 73.04% -0.09% 🍏
Files changed 83.7% 🍏

File Coverage
CollectionCommandTools.java 100% 🍏
FilterDefinition.java 100% 🍏
JsonDefinition.java 100% 🍏
McpSchemaCustomizer.java 96.93% -3.07% 🍏
FindAndRerankCommand.java 81.82% -2.73% ❌
McpOpenApiSchemaAdapter.java 81.72% -18.28% 🍏
SortDefinition.java 56.52% 🍏
FindAndRerankSort.java 21.43% -8.04% ❌

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

📈 Integration Test Coverage Delta vs Main Branch (hcd-it)

Metric Value
Main Branch 74.27%
This PR 74.35%
Delta 🟢 +0.08%
✅ Coverage improved!

@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Integration Test Coverage Report (hcd-it)

Overall Project 74.35% -0.09% 🍏
Files changed 83.7% 🍏

File Coverage
CollectionCommandTools.java 100% 🍏
FilterDefinition.java 100% 🍏
JsonDefinition.java 100% 🍏
McpSchemaCustomizer.java 96.93% -3.07% 🍏
FindAndRerankCommand.java 82.73% -2.73% ❌
McpOpenApiSchemaAdapter.java 81.72% -18.28% 🍏
SortDefinition.java 56.52% 🍏
FindAndRerankSort.java 21.43% -8.04% ❌

RED: McpProtocolTest executes against MCP 1.13.0 and fails because the first tools/list POST returns HTTP 400 instead of 200.
GREEN: the same raw HTTP McpProtocolTest passes with MCP BOM 2.0.3 on Quarkus 3.38.1 and JDK 21. Both independent tools/list requests return complete results without Mcp-Session-Id.
Both DSE and HCD CI exposed four obsolete empty-metadata assertions after the framework upgrade. Require only serverInfo and validate its name and version. The two affected DSE integration classes pass locally: 17 tests, zero failures.

@amorton amorton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see where this is going, it's a bit dangerour having multi line strings that must be valid JSON, and we only find out if it is not at request time.

Also, can we collapse into the McpSchemaDescriptionCustomizer ?

Comment thread src/main/java/io/stargate/sgv2/jsonapi/api/v1/mcp/CollectionCommandTools.java Outdated
Comment thread src/main/java/io/stargate/sgv2/jsonapi/api/v1/mcp/CollectionCommandTools.java Outdated
Comment thread src/main/java/io/stargate/sgv2/jsonapi/api/v1/mcp/McpClauseSchemaCustomizer.java Outdated
Comment thread src/main/java/io/stargate/sgv2/jsonapi/api/v1/mcp/McpClauseSchemaCustomizer.java Outdated
Comment thread src/main/java/io/stargate/sgv2/jsonapi/api/v1/mcp/McpClauseSchemaCustomizer.java Outdated
@erichare

erichare commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

I see where this is going, it's a bit dangerour having multi line strings that must be valid JSON, and we only find out if it is not at request time.

Also, can we collapse into the McpSchemaDescriptionCustomizer ?

The handwritten schema JSON has been replaced with shared @Schema definitions, and the clause and description customizers are combined into McpSchemaCustomizer.

@erichare
erichare changed the base branch from main to fix/mcp-protocol-foundation October 22, 2026 18:19

@amorton amorton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the way it is working looks better, but the code quality is still needs work.

I dont want to being in code if we dont know how it works.

Comment thread src/main/java/io/stargate/sgv2/jsonapi/api/model/schema/ApiSchemaProvider.java Outdated
private record AdaptedInputSchema(JsonObject value) implements InputSchema {
@Override
public String asJson() {
return value.encode();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHY using .encode and not toString() like other code in this PR

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6e2cf87. It now uses toString(), matching the library's own InputSchema implementation. The output is the same either way.

* preserves validation constraints without expanding or merging schemas.
*/
@Decorator
@Priority(1)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EXPLAIN

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 6e2cf87 with a comment. @Decorator wraps the MCP library's generator instead of replacing it, and CDI enables a decorator for the whole app only when it has @Priority. The value only orders decorators on the same bean, and this is the only one.

* shapes that differ from the Java fields, so those types need overrides. Ordinary records still
* use field-based generation.
*
* <p>Named {@code @Schema} definitions refer to the schemas Quarkus already generates for Swagger.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: polite to say this includes the code that was in McpSchemaDescriptionCustomizer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a line to the class doc saying it now includes the description resolver from McpSchemaDescriptionCustomizer.

@Singleton
public class McpSchemaCustomizer implements SchemaGeneratorConfigCustomizer {
@Override
public void customize(SchemaGeneratorConfigBuilder builder) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pls explain what why any of this happens, it generally looks like default behaviour

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to the class doc, plus a short comment on each block. The MCP server builds its generator with the victools PLAIN_JSON preset and no modules, so by default it reads no annotations, and each block adds one back.

return null;
}
var reference = annotation.ref();
if (reference.isEmpty()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use isBlank() to test strings

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched the ref, name, and description checks to isBlank(). The @JsonProperty check stays isEmpty() for the Jackson reason on the earlier thread.

Use the reviewer's filter and sort descriptions, drop trailing sentences from schema descriptions, align example text blocks, restore the JsonDefinition field comment, rename SCHEMA_MAPS to SCHEMA_OBJECTS, use isBlank for annotation strings, and note that McpSchemaCustomizer absorbed McpSchemaDescriptionCustomizer.
Replace @Schema(hidden) with @JsonIgnore on clause wrapper state, restore Map.class on FindAndRerankSort, explain why HybridLimits sets implementation = Void.class, document the schema-only classes, nest the hybrid limit values schema inside HybridLimits, and explain each McpSchemaCustomizer block. The generated OpenAPI document is unchanged.
Address review feedback on McpOpenApiSchemaAdapter.

- Inject the delegate through the constructor and read the generated
  OpenAPI document there. A missing document now stops startup instead
  of failing tools/list requests, and the synchronized lazy loader is
  gone.
- Replace adapt() with static bundleOpenApiSchemas(), which changes the
  given schema in place. This drops the input deepCopy, and
  copyReferencedSchemas() returns its copies instead of filling a
  parameter.
- Convert the bundled tree straight to the Vert.x object the MCP library
  sends, removing the second JSON text round trip.
- Add OpenApiConstants.Components for the components/schemas pointer and
  ref prefix, plus componentRef() and named JSON Pointer escape helpers
  shared with McpSchemaCustomizer.
- Document the class, @priority, the $defs prefix, the schema keyword
  sets, and the argument pointer fix.
Bring the findAndRerank tool arguments to one standard, following
review feedback.

- filter now takes its description from FilterDefinition, as sort
  already does from FindAndRerankSort. A @ToolArg description replaces
  the class description, so it was showing only "filter".
- projection and options get real descriptions in place of "projection"
  and "Reranking options".
- collection says "Name of the collection", since findAndRerank has no
  table support.

Add contract tests that the filter description comes from its class and
that no argument is described only by its own name.
Apply the findAndRerank argument standard to all MCP tools, following
review feedback.

- filter and sort arguments take their descriptions from FilterDefinition
  and SortDefinition, which Swagger also uses. A @ToolArg description
  replaced them, so clients saw only "filter" or "sort".
- Collection arguments name what the command supports: the collection,
  the table, or a collection or table, based on CommandName targets.
- Projection, update, replacement, document, definition, and options
  arguments get real descriptions in place of their bare names or
  generic text.
- Descriptions drop "Optional" and "Required" prefixes, since the schema
  already lists required arguments, and use consistent capitalization.

Generalize the contract tests to every tool: filter and sort use their
class descriptions, and no argument is described only by its name or
starts with "Optional" or "Required".
name = "HybridSort",
type = SchemaType.OBJECT,
implementation = Object.class,
additionalProperties = Schema.False.class,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how does it look when we call with some {"foo": 1} with and without this additionalProperties?

@amorton amorton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 discussed with Eric, some tidy up, and some comments to help with later refactor if needed

@amorton amorton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 discussed with Eric, some tidy up, and some comments to help with later refactor if needed

Base automatically changed from fix/mcp-protocol-foundation to main October 23, 2026 20:42
…chemas

# Conflicts:
#	src/test/java/io/stargate/sgv2/jsonapi/api/v1/mcp/McpHttpTestSupport.java
#	src/test/java/io/stargate/sgv2/jsonapi/api/v1/mcp/McpIntegrationTestBase.java
#	src/test/java/io/stargate/sgv2/jsonapi/api/v1/mcp/McpProtocolTest.java
@erichare
erichare merged commit 7056432 into main Oct 23, 2026
3 checks passed
@erichare
erichare deleted the fix/mcp-clause-wire-schemas branch October 23, 2026 21:19
@erichare
erichare restored the fix/mcp-clause-wire-schemas branch October 25, 2026 02:25
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.

2 participants