fix: auto-parse params when LLM serializes as JSON string#5
Open
Jasper-1222 wants to merge 4 commits into
Open
fix: auto-parse params when LLM serializes as JSON string#5Jasper-1222 wants to merge 4 commits into
Jasper-1222 wants to merge 4 commits into
Conversation
Claude Desktop and other MCP clients sometimes serialize the `params`
argument as a JSON-encoded string (e.g. `"{\"question\":\"test\"}"`)
instead of a native JSON object. This caused Pydantic validation to
fail with `Input should be a valid dictionary [input_type=str]`.
Changes:
- Add `@field_validator` to `InvokeOpenRPCRequest.params` that auto-
detects JSON strings and parses them before Pydantic validation.
Handles edge cases: None, empty string, whitespace-only string,
JSON null literal, valid JSON objects, and valid JSON arrays.
- Add structured warning log when auto-repair occurs to help
operators identify client-side serialization issues.
- Update `inputSchema` for `anp.invokeOpenRPC` to include explicit
`anyOf: [object, array, null]` type constraints. This gives the
LLM a clear schema hint that params should not be a string.
This is a defensive fix — the stringification originates from LLM
tool-call generation, not from mcp2anp itself. FastMCP already
implements similar handling in `pre_parse_json` (func_metadata.py).
Refs: agent-network-protocol/mcp2anp
The `setup_logging` function configured `StreamHandler(sys.stdout)`, which interleaves log lines with MCP JSON-RPC messages on stdout. This breaks the MCP stdio transport as the client expects only valid JSON-RPC frames on stdout. Changed `StreamHandler(sys.stdout)` to `StreamHandler(sys.stderr)` so that structured logs go to stderr while stdout remains clean for the MCP protocol wire format.
Address pre-existing ruff lint issues in logging.py.
b5bd062 to
537deac
Compare
The anyOf type constraint on params caused MCP client-side validation to reject JSON strings before they reached the field_validator, defeating the purpose of the fix. Remove the constraint and keep only the field_validator in models.py as the defensive layer. Root cause: MCP clients validate tool arguments against inputSchema before sending them to the server. When an LLM serializes params as a JSON string, the client-side schema check rejects it because string is not in [object, array, null]. Our server-side fix never executes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
修复
anp.invokeOpenRPC的params参数无法处理 JSON 字符串输入的问题。现象
Claude Desktop / Hermes 等 MCP 客户端在调用
anp.invokeOpenRPC时,LLM 有时会将params参数序列化为 JSON 字符串(如"{\"question\":\"test\"}")而非原生 JSON 对象。这导致 Pydantic 校验失败,错误信息为Input should be a valid dictionary [input_type=str]。根因
这不是 mcp2anp 自身的 bug——字符串化来自 LLM 的工具调用生成行为。MCP 生态系统的 FastMCP 库已经在
pre_parse_json(func_metadata.py)中记录了同样的现象并实现了兼容处理。mcp2anp 的server.py使用底层mcp.server.Server类,绕过了 FastMCP 的pre_parse_json。修复
InvokeOpenRPCRequest.params字段上添加@field_validator(mode="before"),自动检测 JSON 字符串并解析inputSchema添加anyOf: [object, array, null]类型约束,减少 LLM 序列化的概率Verification
uv run pytest所有测试通过(8/8 MCP bridge tests)Risk
低风险。
field_validator仅对字符串类型的 params 做 JSON 解析,正确的 dict/list 值直接透传。