anthropics / anthropics/claude-ai-mcp

Claude.ai MCP connector rejects long Japanese tool args with -32602 (path: enum field) before reaching MCP server

Open
#408 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
No language data
Stars
471
Forks
76
PR merge metrics
No merged PRs in 30d

Description

## Summary

Claude.ai's MCP connector rejects certain tool calls **before** they reach the MCP server, returning `MCP error -32602: Input validation error` with the offending path pointed at an **enum field** even though the enum value (e.g. `"other"`, `"feature"`) is valid. The rejection appears to depend on the content of a different string field (e.g. `body`).

Verified that the request never reaches the server: Vercel runtime logs of the MCP server show **no incoming POST during the failures**, while successful requests with simpler bodies do show up.

## Environment

- Claude.ai web UI (not Claude Code, not the API)
- Custom remote MCP server (Streamable HTTP, OAuth, `mcp-handler@1.1.0` / `@modelcontextprotocol/sdk` latest)
- Tool: `crm_feedback_submit` with input schema:
```ts
{
title: z.string().trim().min(1).max(200),
body: z.string().trim().min(1).max(10_000),
category: z.enum(["bug", "feature", "question", "other"]),
}
```
- Server: `crm.nihonpmipartners.co.jp/mcp` (returns serverVersion `mcp-handler@1.1.0`)

## Reproduction matrix (real session)

Issue numbers in parentheses confirm GitHub Issue creation succeeded on server side:

| Test | body content | Result |
|---|---|---|
| Minimal `other` | `動作確認用 issue` | ✅ #133 |
| Minimal `feature` | `動作確認` | ✅ #134 |
| Backtick only | `` `bash scripts/release.sh --verify` `` | ✅ #135 |
| Markdown headers | `## A\n\n## B` | ✅ #136 |
| Hash mention | `PR #129 と PR #131 と PR #132` | ✅ #140 |
| Numbered list + slashes | `1. .github/pull_request_template.md\n2. .github/workflows/ci.yml\n3. ship.sh` | ✅ #141 |
| ASCII 700 chars | Lorem ipsum 700 chars | ✅ #138 |
| Japanese 600 chars | 600 chars plain Japanese | ✅ #139 |
| **Hyphen list + parens + versions** | `調査結果:\n- 同種の skip 痕跡が過去にも 5 回 (v1.0.3, v1.0.4)\n- 構造的なヒューマンエラー (release.sh 自身は正常動作)` | ❌ rejected |
| **Single-line variant of same content** | Same content joined on one line | ❌ rejected |
| **Original failing content (~700 chars)** | Full feedback with Japanese + version numbers + parens + hyphen lists + `bash scripts/...` | ❌ rejected |

All rejections produce:
```json
{
"code": "invalid_value",
"values": ["bug", "feature", "question", "other"],
"path": ["category"],
"message": "Invalid input"
}
```

…even when `category` was set to a valid value (`"other"`, `"feature"`). The error path is misleading.

## Server-side evidence

Searched Vercel runtime logs of the production MCP server for "Invalid input" / "feedback_submit" during the failure window: **0 hits**. Only the successful requests show up as POST /mcp. The rejection happens entirely on the Claude.ai side and the server never receives the call.

## Hypothesis

Claude.ai's connector appears to run client-side input validation against the tool's declared JSON Schema (derived from the server's `inputSchema`). The validation is **stricter than the declared schema** — `body` is well within `min(1) / max(10000)`, contains no `null`s, and `category` is a literal enum match. Either:

1. Args are sanitized or filtered (e.g. prompt-injection / content policy heuristic) and the resulting object is missing fields → Zod reports the first missing required field as `"Invalid input"`, which happens to be `category` in declaration order.
2. mcp-handler's `inputSchema: ZodObject.shape` → JSON Schema conversion drops constraints in a way that interacts badly with certain content shapes.

Either way, the user-visible error message is misleading because it points at `category` when the actual problem is elsewhere (likely in `body`).

## Asks

1. **Document any input validation / content filter** that Claude.ai connector applies to MCP tool args (the public docs at https://platform.claude.com/docs/en/docs/agents-and-tools/mcp-connector mention only tool description truncation and tool response token limits, nothing about input args).
2. **Improve the error path/message** when client-side validation rejects — pointing at `category` for a body-related rejection causes hours of debugging.
3. **If this is intentional safety filtering**, expose a way to know which field triggered it (or at least include a non-misleading error code so apps can show users a meaningful retry hint).

## Workaround

Currently we tell users to either (a) shorten the body, (b) avoid combinations of hyphen-bulleted Japanese with parenthesized version numbers and shell-script names, or (c) submit via the in-app web form (which bypasses MCP). None of this is documented or discoverable.

## Repro environment metadata

- Date: 2026-06-06
- mcp-handler: 1.1.0
- MCP spec version returned by `server_info`: 2025-11-25
- Auth: OAuth Bearer via claude.ai NPMI社内CRM custom connector
- Server-side schema: posted in full above (Zod, ZodRawShape via `.shape`)
- Full repro examples and matrix above are from real GitHub Issues that were either created or rejected on the same MCP server during the same session.

Happy to provide additional reproduction data, full Zod source, or live server URL if useful.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.