mcp-server 1.5.0: optional params normalize; schemas declare fields (RT #1505) - #31
Conversation
…RT #1505)
Luna fills every optional tool parameter with 0 or ""; servers that
rejected those produced tool errors, and three in a row lock an agent out
of the whole MCP server. Normalize optional blanks to None, keep required
params strict, forbid free-form object params (they yield {} from strict
tool-calling models), describe every field, and put constraints in the
published schema so a gateway can tell valid from invalid.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ReQxcDTpbWp8dzyPYf5bMp
| - Pydantic models enforce strict data types with `extra="forbid"` | ||
| - Allowlists for permitted values (states, scopes, statuses) | ||
| - Resource identifiers validated against injection patterns | ||
| - **Optional parameters normalize, they don't reject.** An optional value of `""` (or whitespace only), `null`, or a non-positive ID means "not given" and becomes `None`. Required parameters keep rejecting empty values. Models from the OpenAI family send every optional parameter rather than omitting it, and each rejection is a tool error an agent's client may count against the whole server (RT #1505). |
There was a problem hiding this comment.
MEDIUM (Bug Hunter): The requirements conflict for optional ID fields. Line 36 says non-positive IDs normalize to None, which means those inputs are accepted; line 39 requires ge=1 in the published schema, which marks them invalid. The same mismatch applies to empty strings for typed ID fields. A gateway relying on the schema may reject inputs before the normalization rule can run.
Suggestion: Make the requirements consistent: either have the published schema represent all accepted normalization inputs, or clarify that gateways must allow these inputs through to server-side normalization and that ge=1 applies only after normalization.
Evidence:
“An optional value of `""` (or whitespace only), `null`, or a non-positive ID means 'not given' and becomes `None`.” … “ID fields declare `ge=1` … so the published `inputSchema` is enough for a gateway to tell a valid value from an invalid one.”
| - Valid full input | ||
| - Invalid/rejected inputs (empty strings, too-long values, extra fields) | ||
| - Invalid/rejected inputs (empty required strings, too-long values, extra fields) | ||
| - Every optional field: `""` and `null` normalize to `None` (and `0` for ID fields) |
There was a problem hiding this comment.
MEDIUM (Test Coverage): The required optional-field tests do not cover all normalization cases specified above. The behavior includes whitespace-only values and non-positive IDs, but the checklist names only the empty string, null, and zero. Tests could therefore omit whitespace-only and negative-ID cases while still satisfying this requirement.
Suggestion: Require tests for whitespace-only optional strings and negative IDs, in addition to empty strings, null values, and zero for ID fields.
Evidence:
Line 36 says optional whitespace-only values normalize to None and non-positive IDs mean “not given”; line 287 requires testing only `""` and `null` (and `0` for ID fields).
| - Valid full input | ||
| - Invalid/rejected inputs (empty strings, too-long values, extra fields) | ||
| - Invalid/rejected inputs (empty required strings, too-long values, extra fields) | ||
| - Every optional field: `""` and `null` normalize to `None` (and `0` for ID fields) |
There was a problem hiding this comment.
LOW (Consistency Check): The test requirement covers 0 for ID fields, but the profile says all non-positive optional IDs normalize to None. This leaves negative IDs unspecified in the required test coverage.
Suggestion: Change the test requirement to cover non-positive ID values, or explicitly narrow the normalization rule to zero.
Evidence:
`- Every optional field: `""` and `null` normalize to `None` (and `0` for ID fields)` contrasts with line 36: `a non-positive ID means "not given" and becomes `None``.
| - Pydantic models enforce strict data types with `extra="forbid"` | ||
| - Allowlists for permitted values (states, scopes, statuses) | ||
| - Resource identifiers validated against injection patterns | ||
| - **Optional parameters normalize, they don't reject.** An optional value of `""` (or whitespace only), `null`, or a non-positive ID means "not given" and becomes `None`. Required parameters keep rejecting empty values. Models from the OpenAI family send every optional parameter rather than omitting it, and each rejection is a tool error an agent's client may count against the whole server (RT #1505). |
There was a problem hiding this comment.
MEDIUM (General Review): The input contract gives conflicting requirements for optional ID fields: non-positive values, including 0, normalize to None, but ID fields must declare ge=1 and the published schema is said to identify valid inputs. A caller following the schema would treat 0 as invalid even though the profile says it should be accepted and normalized.
Suggestion: Clarify whether the schema describes raw inputs or normalized values, and make the ID constraint guidance consistent with the intended treatment of 0 and other non-positive values.
Evidence:
`An optional value of ... a non-positive ID means "not given" and becomes None` (line 36); `ID fields declare ge=1` and the schema should tell a gateway a valid value from an invalid one (line 39).
…yer; full test matrix Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ReQxcDTpbWp8dzyPYf5bMp
|
|
||
| ### Added | ||
| - **MCP Server profile 1.5.0** — Layer 2 tool-input rules from RT #1505: | ||
| optional parameters normalize `""`/`null`/non-positive IDs to `None` |
There was a problem hiding this comment.
LOW (Consistency Check): The changelog summarizes optional-value normalization but omits whitespace-only strings, which the updated MCP profile explicitly includes as values normalized to None.
Suggestion: Include whitespace-only strings in the changelog summary so it matches the profile's stated behavior.
Evidence:
Changelog: `optional parameters normalize ""/null/non-positive IDs to None`; profile: `An optional value of "" (or whitespace only), null, or a non-positive ID means "not given"`.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ReQxcDTpbWp8dzyPYf5bMp
Adds four Layer 2 rules to the MCP Server profile, plus the matching test requirements. They come from RT #1505, where every Metsuke gather failed after Kagetora moved to openai/gpt-6-luna.
""/whitespace,null, and non-positive IDs becomeNone. Required parameters stay strict.list[dict]payload got[{}, {}, {}, {}]from Luna.descriptionon every field.ge=1on IDs, length, format), so Trentina's schema-driven normalization (Schema-driven argument normalization for optional tool parameters mcp-trentina#241) can act on them.mcp-metsuke 1.0.0/1.1.0 and mcp-feed-reader 0.2.2 already comply. Other servers adopt the rules as they're touched.
🤖 Generated with Claude Code
https://claude.ai/code/session_01ReQxcDTpbWp8dzyPYf5bMp