MCP tool_use arg validation rejects valid large string payloads (~16KB+) before transit
Summary
Calling an MCP tool with a large string argument (~13–16KB markdown content) fails inside Claude Code's MCP client layer before any HTTP request reaches the MCP server. The MCP server independently accepts payloads 5x larger via direct invocation, indicating the rejection happens client-side, not at the protocol or server boundary.
Environment
- Claude Code: 2.1.126
- OS: macOS 26.4.1 (build 25E253)
- MCP server: custom mcp-lite-based server (Supabase Edge Function backing)
- Tool affected:
save_file(writes a file artifact, acceptscontent: string) - Tool argument schema: standard JSON Schema,
content: { type: "string" }with nomaxLengthdeclared
Repro
- Configure a custom MCP server with a tool accepting a
content: stringparameter (nomaxLengthin the declared schema) - From Claude Code, invoke the tool with
contentcontaining a markdown payload of ~16KB or more - Observe the call fails inside Claude Code before any HTTP request reaches the MCP server
Expected
The tool call should be transmitted to the MCP server with the content argument intact. Per MCP spec, tool argument validation beyond shape is the server's responsibility — clients should not enforce hidden size ceilings that aren't declared in the tool schema.
Actual
- Call fails before transit with a validation-shaped error (failure mode looks Zod-flavored)
- No call log row appears on the MCP server
- The same call with a smaller payload (e.g., 8KB) succeeds and produces a server log row
- Direct invocation of the same tool's underlying server function (bypassing the Claude Code MCP client) succeeds with payloads up to 68,117 bytes — over 5x the failing client-side size
Evidence
| Test | Payload size | Result |
|---|---|---|
| Direct server invocation (bypassing Claude Code MCP client) | 68,117 bytes | ✅ Success, returns artifact ID |
| Via Claude Code MCP client | ~16KB | ❌ Fails before transit |
| Via Claude Code MCP client | ~8KB | ✅ Success |
The MCP server's storage column is text (unbounded). The tool's JSON Schema declares content: { type: "string" } with no maxLength. There's no documented size limit on the Claude Code side either.
Why it matters
- Tool authors building large-text tools (markdown editors, code-gen tools, file-write tools, document processors) hit a silent ceiling that's not in their schema or server config
- The failure mode is opaque — users see a generic validation rejection, not a "size limit" message, making it look like the tool itself is broken
- Workarounds require defensive client-side chunking the protocol doesn't require, or surfacing the size cap as defensive UX in tool descriptions
Suggested investigation
Check whether Claude Code's MCP client applies argument-value validation (e.g., via a Zod or similar runtime schema layer) on top of MCP's required shape validation. If yes, verify that any implicit string-length caps either:
- Match the declared tool schema's \
maxLength\(if present), or - Are configurable, or
- Are documented and surface a clear "size limit exceeded" error to the model so the model can chunk
Per MCP spec (https://modelcontextprotocol.io/specification), argument validation beyond shape is the server's responsibility. A client-side cap that overrides the declared schema breaks the contract.
Workaround
Added a defensive UX hint to the affected tool's description telling callers to expect the ~13–16KB limit and chunk longer content. This is a band-aid — the real fix is removing or documenting the client-side cap.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗