Skip to content

fix(agent-scan): Tool.inputSchema renamed to input_schema in mcp 2.0 - #614

Open
toBeYoungD wants to merge 1 commit into
Tencent:mainfrom
toBeYoungD:fix/agent-scan-input-schema-2.0
Open

fix(agent-scan): Tool.inputSchema renamed to input_schema in mcp 2.0#614
toBeYoungD wants to merge 1 commit into
Tencent:mainfrom
toBeYoungD:fix/agent-scan-input-schema-2.0

Conversation

@toBeYoungD

Copy link
Copy Markdown

问题

mcp==2.0.0 环境下,agent-scan 连接 MCP 服务器成功(initialize / list_tools 均正常),但在遍历工具 schema 时抛出:

AttributeError: 'Tool' object has no attribute 'inputSchema'

最终表现为 Agent-Scan 任务连接 MCP 服务器失败。

根因

MCP Python SDK 2.0.0 将 Tool 模型的 inputSchema 字段(camelCase)改名为 input_schema(snake_case)。agent_scan/utils/mcp_tools.pydescribe_mcp_tools() 仍访问 t.inputSchema,而 agent-scan 的 requirements.txt 已锁定 mcp==2.0.0,因此该 bug 必然触发。

mcp-scan 的同款问题已在 #609 (dc5ae7f) 修复,agent-scan 被遗漏。

改动

  • agent_scan/utils/mcp_tools.pydescribe_mcp_tools() 内 3 处 t.inputSchemat.input_schema
  • pytests/test_mcp_sdk_v2.py:新增回归测试 test_describe_mcp_tools_reads_input_schema,用 mcp 2.0 形状的 Tool 桩(只有 input_schema 属性)验证 describe_mcp_tools() 正常读取 schema 并缓存到 _tools_schema;修复前该测试失败,修复后通过

验证

在 agent 镜像内(Python 3.12 + mcp==2.0.0)运行:

python -m unittest discover -s pytests -v

结果:2 个测试全部通过(新增的 schema 测试 + 原有的 streamable-http 传输层测试,无回归)。

MCP Python SDK 2.0.0 (pinned in agent-scan requirements.txt) renamed the
Tool model's inputSchema attribute (camelCase) to input_schema
(snake_case). describe_mcp_tools() still accessed t.inputSchema, so any
Agent-Scan task that connects to a live MCP server raises
AttributeError: 'Tool' object has no attribute 'inputSchema' when
enumerating tools.

mcp-scan got the same fix in PR Tencent#609 (dc5ae7f); agent-scan was missed.

Changes:
- Replace t.inputSchema with t.input_schema (3 occurrences in
  describe_mcp_tools()).
- Add a regression test for describe_mcp_tools() in
  pytests/test_mcp_sdk_v2.py using an mcp 2.0-shaped Tool stub.

Verified both tests pass with mcp==2.0.0 inside the agent image.
@boy-hack

Copy link
Copy Markdown
Collaborator

Thanks @toBeYoungD — clean, well-scoped fix and the root cause is spot on: mcp==2.0.0 renames Tool.inputSchemainput_schema, and agent-scan's requirements.txt locks to 2.0.0, so the old attribute access was guaranteed to throw AttributeError. Good that you added the regression test (MCP20ToolSchemaTests) using a stub that only exposes input_schema — that precisely guards against a future reversion.

Two non-blocking suggestions:

  • Forward-compat robustness: since the SDK field name is version-dependent, consider a small helper that reads getattr(t, "input_schema", None) or t.inputSchema (with a guard) so the code degrades gracefully if a mixed-version environment ever appears. Not required given the pinned requirement, but cheap insurance.
  • mcp-scan parity: you noted fix(mcp-scan): adapt to MCP Python SDK 2.x API changes #609 already fixed the same issue in mcp-scan — worth confirming the two modules don't share a common helper that should hold this logic, to avoid a third copy drifting later.

Otherwise this is correct and ready to merge.

@toBeYoungD

Copy link
Copy Markdown
Author

Thanks for the review!

On the getattr guard — I kept the direct access deliberately, for two reasons:

Version mixing can't occur in any supported deployment: requirements.txt pins mcp==2.0.0 (used by the Docker agent image, where the resolution is baked in), and pyproject.toml bounds it to mcp>=2.0.0,<3.0.0 for source installs.
mcp_tools.py already imports SDK-2.0-only APIs at module load time (from mcp.shared._httpx_utils import create_mcp_http_client), so under a hypothetical mcp 1.x environment the import fails long before describe_mcp_tools() is ever reached — the guard wouldn't rescue that scenario.

It also keeps agent-scan consistent with the already-merged mcp-scan fix in #609, which uses plain t.input_schema as well. Happy to add the guard if you feel strongly, but I'd prefer the two modules stay symmetric here.

On mcp-scan parity — confirmed there is no shared helper today: mcp-scan/ and agent-scan/ are independent sub-projects (separate venvs and pyprojects, each spawned as a subprocess by the Go agent), and each carries its own full copy of MCPTools. Unifying them into a common package would be a refactor well beyond this PR's scope — happy to open a separate issue to discuss that if the maintainers are interested.

@boy-hack

Copy link
Copy Markdown
Collaborator

Thanks for the detailed follow-up, @toBeYoungD — and your reasoning on the getattr guard is sound, so I'm convinced the direct t.input_schema access is the right call here:

  1. Version mixing genuinely can't happen in a supported deployment: requirements.txt pins mcp==2.0.0 (baked into the Docker agent image) and pyproject.toml bounds it to >=2.0.0,<3.0.0, so there's no 1.x/2.x ambiguity to defend against.
  2. mcp_tools.py already imports SDK-2.0-only symbols (create_mcp_http_client) at module load — under a hypothetical 1.x environment that import fails long before describe_mcp_tools() runs, so the guard wouldn't rescue anything.
  3. Staying symmetric with the already-merged mcp-scan fix (fix(mcp-scan): adapt to MCP Python SDK 2.x API changes #609), which also uses plain t.input_schema, keeps the two independent sub-projects consistent.

The regression test (MCP20ToolSchemaTests) using a stub that only exposes input_schema is exactly the right guard against reversion. The root cause, fix, and test are all correct.

Approving — this is ready to merge. 🚀

(Leaving as review comment only; not merging.)

@toBeYoungD

Copy link
Copy Markdown
Author

Friendly ping @NY1024 -- this PR is approved and all checks are green. Could you help merge when you have a moment? It unblocks Agent-Scan tasks against MCP 2.0 servers (same issue class as #609). Thanks!

@boy-hack

boy-hack commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

@toBeYoungD — still approved from my earlier review; the root cause, fix, and regression test are all correct, and checks are green. The @NY1024 merge ping is the right next step. Leaving the merge to a maintainer — ready to land whenever one has a moment. 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants