Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

abloomston
Copy link

@abloomston abloomston commented Aug 5, 2025

Add optional strict parameter to registerTool() config that enables Zod's strict validation to reject unknown parameters instead of silently ignoring them.

Motivation and Context

The MCP TypeScript SDK currently silently ignores unknown parameters in tool calls, which causes issues where parameter name typos are silently dropped, leading to confusing behavior where tools execute with missing data.

How Has This Been Tested?

  • Added comprehensive test case demonstrating the issue and fix

Breaking Changes

None. The strict parameter defaults to false for backward compatibility. Existing code will continue to work unchanged.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

You should consider this PR in concert with #792 which makes changes that may be related.

Implementation Details:

  • Added strict?: boolean to registerTool config interface
  • When strict=true, applies z.object(inputSchema).strict() to reject unknown parameters
  • When strict=false (default), maintains current lenient behavior
  • Only available in registerTool() method - legacy tool() method uses lenient validation for compatibility

Use Cases:

  • Development: Catch parameter name typos early
  • Production APIs: Ensure clients send only expected parameters
  • Security-sensitive tools: Prevent injection of unexpected data

The feature follows existing patterns in the codebase and maintains full backward compatibility while solving a real pain point for developers.

LLM Disclosure

This PR was created with the assistance of Claude Code, Claude Haiku 3.5, Claude Sonnet 4.0, and Chat-GPT 4.1 nano.

Adam Bloomston added 3 commits August 5, 2025 11:00
  This test demonstrates the current issue where tools accept unknown
  parameters (e.g. incorrect capitalization) without validation errors.
  The test uses 'username' and 'itemcount' instead of the expected
  'userName' and 'itemCount' parameters, which should be rejected
  but currently aren't.

  This test is expected to fail until strict validation is implemented.
  Add strict parameter to registerTool config that defaults to false for
  backward compatibility. When strict=true, applies .strict() to Zod
  schema creation for tool input validation to throw errors on unknown
  parameters instead of silently ignoring them.

  - Add strict?: boolean to registerTool config interface
  - Modify _createRegisteredTool to accept and use strict parameter
  - Apply z.object(inputSchema).strict() when strict=true
  - Update legacy tool() method to pass strict=false (backward compatibility)
  - Update test to verify strict validation rejects unknown parameters
  - All existing tests continue to pass (no breaking changes)

  This fixes the issue where parameter name typos are silently dropped,
  leading to confusing behavior where tools execute with missing data.
  Add Advanced Usage section explaining the strict parameter for registerTool:
  - Show examples of strict vs lenient validation
  - Explain when to use each mode (development vs production)
  - Document that strict parameter is only available in registerTool()
  - Note that legacy tool() method uses lenient validation for compatibility

  This helps developers understand when and how to use strict validation
  to catch parameter name typos and unexpected data.
@abloomston abloomston requested a review from a team as a code owner August 5, 2025 17:45
@abloomston abloomston requested a review from domdomegg August 5, 2025 17:45
@domdomegg domdomegg requested review from ochafik and removed request for domdomegg August 25, 2025 16:38
Copy link
Contributor

@ochafik ochafik left a comment

Choose a reason for hiding this comment

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

Thanks @abloomston !

strict: true // Reject { username: "test", itemcount: 42 }
}, handler);

// Lenient validation for production - handles client variations gracefully
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure about advising leniency in prod tbh, or maybe explain why (e.g. to allow some kind of forward compatibility maybe, although I'm struggling to imagine a valid use case)

Copy link
Author

Choose a reason for hiding this comment

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

@ochafik I did this to maintain backwards compatibility for users of this sdk. Let me know which (or another) you'd like me to do:

  1. Revise this comment, maintaining backwards compatibility
  2. Do not maintain backwards compatibility, making strict the default

@@ -774,14 +774,19 @@ export class McpServer {
inputSchema: ZodRawShape | undefined,
outputSchema: ZodRawShape | undefined,
annotations: ToolAnnotations | undefined,
strict: boolean | undefined,
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd name this more explicitly, e.g. rejectUnexpectedInputs, given this isn't turning registerTool as fully strict (e.g. I'd expect structuredContent to be checked against outputSchema, and potentially content text to be checked against structuredContent)

Copy link
Author

Choose a reason for hiding this comment

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

@ochafik would the variable name strictInputSchemaValidation work for you?

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