Add tool parameter validation to MCP binding#1877
Draft
jfallows wants to merge 13 commits into
Draft
Conversation
…ptions.tools Make InlineCatalogHandler mutable at runtime (content-addressed CRC32C, refcounted) so the mcp server can register tool inputSchemas captured from tools/list responses. Add McpOptionsConfig.tools ModelConfig surfaced through OptionsConfig.models for catalog id resolution. Refs #1876 https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
Add 'tool' to the model-json validator strategy enum, add the options.tools validator ref to the mcp binding schema, and add server.validation.yaml IT config wiring an inline catalog with strategy: tool (#1876). https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
Resolve the inline tools catalog on McpBindingConfig and add registerToolSchema/unregisterToolSchema/resolveToolValidator with a worker-level Int2ObjectHashMap<ValidatorHandler> cache keyed by content-addressed schema id. Add model-json dependency (#1876). https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
…call args McpServerFactory now captures each advertised inputSchema from the tools/list reply (per session, content-addressed into the inline catalog) and validates tools/call arguments against the tool's schema. On invalid arguments the server returns JSON-RPC -32602 and never forwards the payload upstream (app begin is deferred until validation passes); unknown tools pass through. Schemas are evicted on notifications/tools/list_changed (#1876). https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
…alog Add network/application .rpt scenarios and McpServerIT methods for tools/call argument validation (valid pass-through, invalid -> -32602). Fix InlineCatalogHandler to accept a null/absent options block so an inline catalog can be populated purely at runtime (was NPEing on config.subjects); add regression unit test. Make doEncodeResponseError emit well-formed JSON. Add catalog-inline test dependency for the IT. ITs not yet executed to green: the container's k3po control backend fails to start after a restart (reproduced on unrelated binding-http ITs), so engine+k3po integration tests cannot run in this environment; engine config load and unit tests verified. https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
…t request end Validate tools/call arguments when the request body completes (onNetEnd), not mid-decode, so the rejected request stream is already registered and cleanly removed, and the error reply is encoded at the half-duplex reply point. Fix doEncodeResponseError to mark the reply closing and defer the END until any buffered body flushes (previously doNetEnd discarded the buffered JSON-RPC error before the client could read it). Guard flushAppWindow against a deferred request stream whose app side was never begun. McpServerIT shouldAcceptToolsCallWithValidInput and shouldRejectToolsCallWithInvalidInput both pass via failsafe verify. https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
…alidation Add the network server and application client peer scripts and the paired NetworkIT/ApplicationIT methods for tools.call.valid.input and tools.call.invalid.input, per specs/AGENTS.md (every scenario needs both a binding IT and a peer-to-peer NetworkIT/ApplicationIT method). All four peer tests pass. https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
A tools/call for a tool with no captured schema (here, called before any tools/list) is forwarded unvalidated under server.validation.yaml, exercising the best-effort path. Adds network + application peer scripts and McpServerIT/NetworkIT/ApplicationIT methods. All pass. https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
Re-listing with a changed inputSchema recaptures the tool schema; a subsequent tools/call is validated against the new schema (args valid under v2 but not v1 are accepted). Adds network + application peer scripts and McpServerIT/NetworkIT/ApplicationIT methods. All pass. https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
…n end Schema catalog references were only released on tools/list_changed, so tools dropped from a subsequent tools/list and schemas held by a session that ended without a list_changed were never unregistered (refcount leak, bounded only by distinct schema content). Treat each tools/list as the authoritative full set: evict the session's prior schemas before recapturing, and evict on both session teardown paths (inactivity and app close). Add tools.list.drop scenario (network+application peers + McpServerIT/NetworkIT/ApplicationIT) asserting a tool dropped from a re-list is no longer validated (call passes through instead of -32602). https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR adds JSON schema validation for tool call parameters in the MCP binding. When tools are configured with a model and catalog, their input parameters are now validated against the schema before being forwarded to the application.
Changes
Core Validation Logic:
McpServerFactoryto pass binding configuration toMcpServerinstancesMcpRequestStreamvia newbufferArgs()andvalidateArgs()methodsConfiguration & Integration:
McpBindingConfigto support optionaltoolsmodel configuration with catalog referencesvalidatesTools(),registerToolSchema(),resolveToolValidator(), andunregisterToolSchema()methods to manage tool validationMcpOptionsConfigand related adapters to support the newtoolsmodel configurationmodel-jsonruntime moduleCatalog Improvements:
InlineCatalogHandlerwith runtime registration/unregistration viaregister()andunregister()methodsTest Coverage:
server.validation.yamldemonstrates tools validation setupTest Plan
Existing and new integration tests verify:
https://claude.ai/code/session_015SCFtykHvSyqMSqe5VCBYo