-
Notifications
You must be signed in to change notification settings - Fork 8.3k
fix(sequential-thinking): Add input sanitization for numeric parameters #2812
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
fix(sequential-thinking): Add input sanitization for numeric parameters #2812
Conversation
WHY: Some MCP clients may pass numeric parameters as strings Strict type checking causes validation errors with 'Invalid thoughtNumber' EXPECTED: Sanitize valid numeric strings to numbers before validation Maintains type safety while improving client compatibility CHANGES: - Added sanitizeNumericParam() private helper method - Sanitizes thoughtNumber, totalThoughts, revisesThought, branchFromThought - Coerces valid numeric strings (e.g., '1') to numbers (e.g., 1) - Preserves original validation logic after sanitization - Returns invalid values as-is for clear error messages TESTING: - Handles number inputs: 1 → 1 (pass through) - Handles string inputs: '1' → 1 (coerce) - Handles invalid inputs: 'abc' → 'abc' (validation fails with clear error) Fixes: Non-deterministic validation errors with MCP clients that serialize numeric parameters as strings in JSON payloads
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR improves client compatibility for the sequential-thinking MCP server by adding input sanitization for numeric parameters. The change addresses validation errors that occur when MCP clients serialize numeric values as strings in JSON payloads.
Key changes:
- Added
sanitizeNumericParam()
helper method to coerce valid numeric strings to numbers - Updated
validateThoughtData()
to sanitize numeric parameters before validation - Maintained existing validation logic and error handling
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
WHY: Copilot review identified inconsistency between regex and validation Regex /^\d+$/ allowed '0' to match, but parsed > 0 rejected it EXPECTED: Regex explicitly excludes zero to match semantic intent Thought numbers are 1-indexed (1, 2, 3, ...), zero is invalid CHANGES: - Updated regex from /^\d+$/ to /^[1-9]\d*$/ - Added comments explaining thought numbers are 1-indexed - Regex now matches: 1, 2, 3, ... (excludes 0) - Maintains parsed > 0 check (now consistent with regex) COPILOT FEEDBACK ADDRESSED: 1. ✅ Regex inconsistency with zero - FIXED 2. ❌ Negative/decimal suggestion - Not applicable - Thought numbers are semantic indices (1st, 2nd, 3rd thought) - Decimals (1.5) and negatives (-1) don't make sense - Current regex already prevents negatives (no minus sign) TESTING: - Accepts: '1' → 1, '2' → 2, '999' → 999 - Rejects: '0' (fails regex), '-1' (fails regex), '1.5' (fails regex) Refs: PR modelcontextprotocol#2812 Copilot review
Thanks for the review, @Copilot! Addressing your feedback: ✅ Comment 1: Regex inconsistency with zero - FIXEDYou're absolutely right about the inconsistency. The regex Fix applied: Updated regex to Rationale: Thought numbers are semantic indices representing "which thought in the sequence" (1st, 2nd, 3rd, etc.). Zero doesn't make sense in this context - thoughts are 1-indexed, not 0-indexed. ❌ Comment 2: Negative numbers and decimals - Not applicableThe suggestion to handle negative numbers and decimals doesn't apply here because:
The function name Updated behavior:
The fix maintains type safety while being explicit about the valid range for thought indices. |
…sequential-thinking
WHY: - MCP SDK validates against tool schema BEFORE calling handler - Schema defined thoughtNumber/totalThoughts/etc as type: 'integer' - String values like '1' failed schema validation before reaching sanitizeNumericParam() - Input sanitization code was correct but never executed EXPECTED: - Schema now accepts both integers and strings for numeric parameters - MCP SDK allows strings to pass schema validation - sanitizeNumericParam() can coerce strings to numbers - Tool works with both thoughtNumber: 1 and thoughtNumber: '1' CHANGES: - Updated thoughtNumber schema: oneOf [integer, string with pattern] - Updated totalThoughts schema: oneOf [integer, string with pattern] - Updated revisesThought schema: oneOf [integer, string with pattern] - Updated branchFromThought schema: oneOf [integer, string with pattern] - Pattern: ^[1-9]\d*$ (matches positive integers, excludes zero) SCHEMA STRUCTURE: oneOf: [ { type: 'integer', minimum: 1 }, { type: 'string', pattern: '^[1-9]\d*$' } ] This allows MCP SDK to accept either: - Integer: 1, 2, 3, ... - String: '1', '2', '3', ... Both are then sanitized by sanitizeNumericParam() before validation. IMPACT: - Completes the input sanitization fix - Schema + sanitization + validation now work together - MCP clients can pass numeric parameters as strings or numbers - No more 'Invalid thoughtNumber: must be a number' errors for valid string numbers Refs: Schema validation happens before handler execution in MCP SDK
…ee-layer defense strategy WHY: - Complete fix requires understanding of BOTH schema update AND input sanitization - Schema oneOf prevents overly strict client-side validation from blocking LLM mistakes - Input sanitization provides server-side defense and type coercion - Together they ensure tool availability while maintaining correctness EXPECTED: - Clear documentation of root cause (client-side schema validation + missing sanitization) - Explanation of three-layer defense: permissive schema, sanitization, strict validation - Real-world scenarios showing why both fixes are required - Design philosophy: liberal in acceptance, strict in production Refs: MCP specification - clients SHOULD validate, servers MUST validate
28311c0
to
ca00790
Compare
WHY: - Sequential Thinking MCP server needs stable local build during development - Prevent NPM from auto-updating dependencies before PR merge - Ensure consistent build environment across development sessions EXPECTED: - NPM uses exact versions (save-exact=true) - Package-lock.json not modified automatically - Prefer offline cache to avoid registry fetches - No automatic dependency updates during local development Refs: Local development workflow for fix/input-sanitization-sequential-thinking branch
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't plan to accept this change - this seems like a model bug that it is passing through the wrong shaped parameters. If we do want to correct this for poorly performing models, the place to do that would probably be the client anyways where it can be implemented once rather than server side.
I don’t have access to the clients and have noticed this issue in both
Copilot, Augment, and Gemini. I felt this was simple fix for any client.
…On Fri, Oct 10, 2025 at 04:27 adam jones ***@***.***> wrote:
***@***.**** requested changes on this pull request.
I think we don't plan to accept this change - this seems like a model bug
that it is passing through the wrong shaped parameters. If we do want to
correct this for poorly performing models, the place to do that would
probably be the client anyways where it can be implemented once rather than
server side.
—
Reply to this email directly, view it on GitHub
<#2812 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAB7TGHCTA6H4L26MOW72HL3W6JZPAVCNFSM6AAAAACIGC5WT2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTGMRSG44DCMZSGY>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
@ketema out of curiosity, what models are you using when this happens? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with Adam that not sure if forcing the values is the right thing to do here. I did have another question though about what models you're using when this happens.
@@ -0,0 +1,19 @@ | |||
# Local NPM configuration for Sequential Thinking MCP Server |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this intentionally checked in?
@@ -0,0 +1,221 @@ | |||
# Sequential Thinking MCP Server - Schema Fix Explanation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this intentionally checked in?
It has mostly happened with Anthropic Claude models and mostly with the
Augment.ai agent, but as mentioned I have had it happen with copilot and
Claude and once with Gemini in an early 1.5 flash model, although I wasn’t
keeping strict count. It just happened enough that I decided to ask why
then make the patch.
…On Sun, Oct 12, 2025 at 21:15 Ola Hungerford ***@***.***> wrote:
***@***.**** commented on this pull request.
Agree with Adam that not sure if forcing the values is the right thing to
do here. I did have another question though about what models you're using
when this happens.
------------------------------
In src/sequentialthinking/.npmrc
<#2812 (comment)>
:
> @@ -0,0 +1,19 @@
+# Local NPM configuration for Sequential Thinking MCP Server
Was this intentionally checked in?
------------------------------
In src/sequentialthinking/SCHEMA_FIX_EXPLANATION.md
<#2812 (comment)>
:
> @@ -0,0 +1,221 @@
+# Sequential Thinking MCP Server - Schema Fix Explanation
Was this intentionally checked in?
—
Reply to this email directly, view it on GitHub
<#2812 (review)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAB7TGBOEQCEZVBHKVKB7I33XL4KHAVCNFSM6AAAAACIGC5WT2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTGMRZG43TEOBVGU>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Sorry about the .npmrc i will remove it
…On Mon, Oct 13, 2025 at 04:13 Ketema Harris ***@***.***> wrote:
It has mostly happened with Anthropic Claude models and mostly with the
Augment.ai agent, but as mentioned I have had it happen with copilot and
Claude and once with Gemini in an early 1.5 flash model, although I wasn’t
keeping strict count. It just happened enough that I decided to ask why
then make the patch.
On Sun, Oct 12, 2025 at 21:15 Ola Hungerford ***@***.***>
wrote:
> ***@***.**** commented on this pull request.
>
> Agree with Adam that not sure if forcing the values is the right thing to
> do here. I did have another question though about what models you're using
> when this happens.
> ------------------------------
>
> In src/sequentialthinking/.npmrc
> <#2812 (comment)>
> :
>
> > @@ -0,0 +1,19 @@
> +# Local NPM configuration for Sequential Thinking MCP Server
>
> Was this intentionally checked in?
> ------------------------------
>
> In src/sequentialthinking/SCHEMA_FIX_EXPLANATION.md
> <#2812 (comment)>
> :
>
> > @@ -0,0 +1,221 @@
> +# Sequential Thinking MCP Server - Schema Fix Explanation
>
> Was this intentionally checked in?
>
> —
> Reply to this email directly, view it on GitHub
> <#2812 (review)>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/AAB7TGBOEQCEZVBHKVKB7I33XL4KHAVCNFSM6AAAAACIGC5WT2VHI2DSMVQWIX3LMV43YUDVNRWFEZLROVSXG5CSMV3GSZLXHMZTGMRZG43TEOBVGU>
> .
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>
|
Problem
Some MCP clients may serialize numeric parameters as strings in JSON payloads, causing validation errors with the current strict type checking.
Error Message:
Root Cause: The
validateThoughtData()
method performs strict type checking (typeof data.thoughtNumber !== 'number'
), which fails when clients pass"1"
(string) instead of1
(number).Solution
Add input sanitization to coerce valid numeric strings to numbers before validation, while maintaining type safety.
Changes
sanitizeNumericParam()
private helper methodthoughtNumber
,totalThoughts
,revisesThought
,branchFromThought
"1"
) to numbers (e.g.,1
)Testing
1
→1
(pass through)"1"
→1
(coerce)"abc"
→"abc"
(validation fails with clear error)Impact
Example
Before:
After:
Testing Evidence
Tested with Augment.AI MCP client:
thoughtNumber: 1
(number)thoughtNumber: "1"
(string, coerced to number)thoughtNumber: "abc"
(invalid, clear error)Additional Context
This fix addresses non-deterministic validation errors observed with MCP clients that use LLM-generated tool calls, where numeric parameters may be serialized as strings depending on the LLM's output format.
The sanitization approach:
This maintains the original validation behavior while improving compatibility with clients that serialize numbers as strings.