Skip to content

fix(deps): require mcp>=1.19.0 for in-process SDK MCP tools#891

Merged
qing-ant merged 2 commits intomainfrom
qing/fix-mcp-min-version
Apr 28, 2026
Merged

fix(deps): require mcp>=1.19.0 for in-process SDK MCP tools#891
qing-ant merged 2 commits intomainfrom
qing/fix-mcp-min-version

Conversation

@qing-ant
Copy link
Copy Markdown
Contributor

@qing-ant qing-ant commented Apr 28, 2026

Problem

create_sdk_mcp_server tool handlers have returned CallToolResult objects since v0.1.51 (PR #717). The mcp package's @server.call_tool() decorator only accepts CallToolResult returns from mcp>=1.19.0. With older versions it falls through the iterable branch (pydantic models iterate as (field, value) tuples), fails validation, and swallows the result into _make_error_result(str(e)).

Effect: in-process SDK MCP tools run their handler, but the model receives a ~5KB pydantic "20 validation errors for CallToolResult" blob with is_error=True instead of the actual output. Silent data loss.

This only bites users who pip install -U claude-agent-sdk in an existing env — fresh installs pull latest mcp and work fine. stdio/HTTP/SSE MCP servers are unaffected.

Fix

Bump the floor: mcp>=0.1.0mcp>=1.19.0.

Verification

Boundary-tested with a direct request_handlers[CallToolRequest] repro:

mcp version result
1.12.4 isError: True, validation error blob
1.18.0 isError: True, validation error blob
1.19.0 isError: False, tool output returned
1.27.0 isError: False, tool output returned
  • pip install -e . 'mcp==1.12.4'ResolutionImpossible (pin enforced)
  • Full ClaudeSDKClient e2e with create_sdk_mcp_server: tool result reaches the model
  • pytest: 755 passed, 3 skipped · mypy: clean · ruff: clean

Reported internally.

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — straightforward, well-verified dependency floor bump; the inline note about the release-automation prompt is a non-blocking follow-up.

Extended reasoning...

Overview

This PR raises the mcp dependency floor from >=0.1.0 to >=1.19.0 in pyproject.toml, adds a corresponding ## Unreleased entry to CHANGELOG.md, and widens the regex in tests/test_changelog.py to accept the new ## Unreleased heading. Three files, ~10 changed lines total, no runtime code touched.

Security risks

None. This is a minimum-version constraint tightening on an existing dependency plus documentation/test-fixture updates. No new code paths, no auth/crypto/permissions surface, no new packages introduced.

Level of scrutiny

Low. The core change is a one-line dependency pin with a thoroughly documented rationale: SDK MCP tool handlers have returned CallToolResult since v0.1.51 (#717), and the PR description shows boundary testing across four mcp versions confirming 1.19.0 is the exact floor where this works. Tightening a floor from an effectively-unbounded >=0.1.0 to a verified-compatible >=1.19.0 is the conventional fix and only affects users on stale mcp installs (who are currently broken anyway). The changelog and test-regex tweaks are mechanical and self-evidently correct.

Other factors

  • No CODEOWNERS file in the repo.
  • Full test suite, mypy, and ruff reported clean in the PR description.
  • The one finding from review is a [Nit] about the generate-changelog release prompt not yet knowing about the ## Unreleased convention. That's a valid process observation but explicitly non-blocking — the prompt already instructs the agent to "follow the existing format in CHANGELOG.md", and release PRs get human review regardless. It can be addressed in a follow-up and does not affect the correctness of this fix.

Comment thread CHANGELOG.md Outdated
create_sdk_mcp_server tool handlers return CallToolResult objects since
v0.1.51 (PR #717). mcp<1.19.0 cannot handle this return type from
@server.call_tool() decorated functions — it falls through the iterable
branch, fails pydantic validation, and silently swallows the tool output
into an error result.

Users upgrading claude-agent-sdk in an existing env with old mcp would
see in-process SDK MCP tools run but return validation error blobs
instead of actual results.
@qing-ant qing-ant force-pushed the qing/fix-mcp-min-version branch from b67740e to bfef196 Compare April 28, 2026 17:29
@qing-ant qing-ant enabled auto-merge (squash) April 28, 2026 17:38
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — switching to a concrete ## 0.1.70 heading resolves the earlier release-automation concern, and the dependency floor bump itself is straightforward and well-verified.

Extended reasoning...

Overview

This PR touches two files: a single-line edit in pyproject.toml raising the mcp dependency floor from >=0.1.0 to >=1.19.0, and a corresponding changelog entry. The motivation is that in-process SDK MCP tool handlers return CallToolResult objects (since v0.1.51 / #717), which the mcp package's call_tool decorator only handles correctly from 1.19.0 onward; the PR description includes boundary testing across four mcp versions confirming 1.19.0 is the precise cutoff.

Since my previous review, the author dropped the ## Unreleased changelog convention (and the accompanying tests/test_changelog.py regex change) in favor of a concrete ## 0.1.70 section. That sidesteps the release-automation prompt mismatch I flagged — the generate-changelog command will now find the next-version section already in place rather than encountering an unfamiliar heading. The diff is now strictly two files, both trivial.

Security risks

None. This is a dependency floor increase on an existing, already-required package — it narrows the accepted version range rather than introducing new code, new packages, or new attack surface. No auth, crypto, permissions, or input-handling paths are touched.

Level of scrutiny

Low. A one-line version-constraint bump with a documented, reproducible justification and a matching changelog entry is about as mechanical as PRs get. The only user-facing effect is that pip install -U claude-agent-sdk in an environment with a stale mcp will now force an mcp upgrade instead of silently breaking tool results — which is the intended fix.

Other factors

The PR description reports the full test suite (755 passed), mypy, and ruff all clean, plus a ResolutionImpossible check confirming pip enforces the new pin and an end-to-end ClaudeSDKClient verification. The changelog entry follows the existing ### Bug Fixes format used throughout the file. No outstanding reviewer comments remain — my earlier inline note is fully addressed by the revised approach.

@qing-ant qing-ant merged commit 8f8f7f4 into main Apr 28, 2026
15 checks passed
@qing-ant qing-ant deleted the qing/fix-mcp-min-version branch April 28, 2026 21:12
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — with the changelog changes dropped this is just a well-justified one-line dependency floor bump.

Extended reasoning...

Overview

Single-line change in pyproject.toml: raises the mcp dependency floor from >=0.1.0 to >=1.19.0. The PR originally also touched CHANGELOG.md and tests/test_changelog.py, but the author removed those in commit 3618147 after my earlier comment about the ## Unreleased convention conflicting with the release automation. That inline comment is now resolved and moot — the file it referenced is no longer in the diff.

Security risks

None. This is a version-constraint tightening on an existing dependency; no new packages, no code, no auth/crypto/permissions surface.

Level of scrutiny

Low. A dependency floor bump is mechanical, and this one is unusually well-supported: the PR description includes a boundary-tested compatibility matrix (1.18.0 fails, 1.19.0 passes), a ResolutionImpossible check confirming the pin is enforced, an end-to-end ClaudeSDKClient repro, and clean pytest/mypy/ruff runs. The rationale (CallToolResult return support landed in mcp 1.19.0, required since SDK v0.1.51 / PR #717) is specific and verifiable.

Other factors

  • The only user-visible effect is that pip install -U claude-agent-sdk will now also pull mcp>=1.19.0 in environments with an older pin — which is precisely the failure mode being fixed (silent is_error=True validation blobs instead of tool output).
  • mcp>=1.19.0 still requires Python >=3.10, matching this package's requires-python, so no Python-version compatibility regression.
  • No CODEOWNERS file in the repo.
  • No outstanding reviewer comments; the bug-hunting pass on the current revision found nothing.

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