Repository navigation
feat: migrate MCP client and AgentOS server to mcp 2.x - #9269
Conversation
PR TriageMissing tests: This PR modifies source code but does not include any test changes. Please add or update tests to cover your changes. |
|
hey @ProgrammerPlus1998 can you resolve the conflicts? |
67027f2 to
c335ede
Compare
mcp 2.0.0 renamed McpError to MCPError, removed streamablehttp_client, and changed ClientSession timeouts and mcp.types field names. The unbounded `mcp>=1.9.2` constraint lets fresh installs resolve to the incompatible 2.0.0, and the surrounding try/except then re-raised a misleading "`mcp` not installed" error. - Constrain the mcp extra to `mcp>=1.9.2,<2.0.0` - Distinguish "mcp not installed" (ModuleNotFoundError) from an incompatible-but-installed mcp (ImportError), and report the real cause plus the supported range in the latter case Refs agno-agi#9267
mcp 2.0.0 renamed McpError to MCPError, removed streamablehttp_client, changed ClientSession timeouts to float seconds, renamed mcp.types fields to snake_case, and dropped timeout/sse_read_timeout kwargs from streamable_http_client. This migrates agno's MCP client (MCPTools, MultiMCPTools, utils) and the AgentOS MCP server/auth onto mcp 2.x. - Raise the mcp extra to mcp>=2.0.0,<3.0.0 and fastmcp>=4.0.0b1,<5 (pre-release, until stable 4.x ships). - Map streamable-http timeouts onto an httpx2.Timeout via create_mcp_http_client, following the SDK's own v2 pattern. - Adapt AgentOS auth to the v2 OAuthClientInformationFull (required client_id, Optional token_endpoint_auth_method/redirect_uris). - Floor httpx[http2]>=0.28.1: pre-release resolvers otherwise pick httpx 1.0 dev builds that drop HTTPStatusError and break fastmcp 4. - Update MCP and AgentOS tests to the v2 API surface. Fixes agno-agi#9267
httpx2.Timeout(read=None) means no read limit at all. A raw StreamableHTTPClientParams-style dict that set `timeout` without `sse_read_timeout` (or vice versa) therefore produced a Timeout with an unbounded read side, where the mcp 1.x client would have applied the SDK's own default (300s stream read / 30s operations). Default the missing knob instead of passing None through. Also cover _streamable_http_connection directly: both timeouts set, each knob missing, legacy timedelta values, and the no-custom-client path were previously only exercised through mocks.
Nothing in agno calls a 2.1-only API, but 2.1.0 carries client-side interop fixes MCPTools benefits from against newer servers: cache-hint fields from later revisions are ignored instead of failing list_tools() (agno-agi#3223), boolean sub-schemas are accepted in tool schema properties (agno-agi#3353), and recursive return types get an object-rooted outputSchema pre-2026 clients accept (agno-agi#3337). The full unit suite is validated against 2.1.0.
20ae40d to
e50db29
Compare
|
Rebased onto the post-v3.0.0 Rebase adjustments
Fix found while rebasing
Tests
Dependency floor
Validation
|
|
Status update — this is now rebased onto v3.0.0 and raises the mcp floor to 2.1.0. One thing to flag for review: it currently pulls Given v3 deleted |
|
Hi @kausmeows @ysolanky — good news: FastMCP 4.0.0 stable shipped today, which was the last blocker on this PR. I've updated the pin from This is ready to merge whenever you have a moment. Thanks! |
|
thanks @ProgrammerPlus1998 we'll take a look on this. cc @sannya-singal |
The merge from main brought back mcp 1.x call sites in context/web/parallel_mcp.py and streamable-http header tests written against the v1 streamablehttp_client signature. Update them to the v2 convention: headers/timeouts ride on an httpx2 client built by create_mcp_http_client, streamable_http_client yields a 2-tuple, ClientSession read timeout is float seconds, and CallToolResult uses is_error.
ToolAnnotations in mcp 2.x renames its Python attributes to snake_case while keeping the protocol's camelCase wire names as aliases, so the allowlist guard now compares against aliases (the names the protocol actually defines; agno's public annotation keys are unchanged). FastMCP 4 derives a display title from the tool name when a tool publishes none, so the duck-typing guard asserts the look-alike attribute is ignored rather than asserting title stays unset.
|
Update: after the latest merge from main, CI flagged a few call sites that came in from main still using the mcp 1.x API. Fixed in the last two commits:
CI is now fully green on the merge with main (all style checks + all 5 test shards). Ready for review. |
1f3fc16 to
b5f7fdf
Compare
Summary
mcp2.0.0 (released 2026-07-28) shipped breaking changes across the client and server surface: it renamedMcpErrortoMCPError, removedstreamablehttp_client, changedClientSessiontimeouts to float seconds, renamedmcp.typesfields to snake_case, and dropped thetimeout/sse_read_timeout/authkwargs fromstreamable_http_client. Because themcpextra declared an unboundedmcp>=1.9.2, a freshpip install agno[mcp]resolved to the incompatible 2.0.0 and crashed on import (see #9267).The blocker that made a quick "cap it" the only option has since cleared: fastmcp 4.0.0b1 now supports
mcp>=2.0.0,<3.0.0(PrefectHQ/fastmcp #4655). So this PR does the full migration rather than a temporary pin.Changes:
pyproject.toml):mcp = ["mcp>=2.0.0,<3.0.0", "fastmcp>=4.0.0b1,<5"](pre-release fastmcp until stable 4.x ships). Addedhttpx[http2]>=0.28.1floor — pre-release resolvers otherwise pullhttpx 1.0dev builds that dropHTTPStatusErrorand crashfastmcp.server.serveron import.utils/mcp.py,tools/mcp/mcp.py,tools/mcp/multi_mcp.py,tools/mcp/params.py):McpError→MCPError;streamablehttp_client→streamable_http_client(now yields a 2-tuple);read_timeout_secondsas float; snake_case attribute access (is_error,structured_content,mime_type,input_schema);model_dump_json(by_alias=True)for wire output;StreamableHTTPClientParamstimeouts as float seconds. A shared helper_streamable_http_connection()maps the removedtimeout/sse_read_timeoutkwargs onto anhttpx2.Timeoutvia the SDK's owncreate_mcp_http_client(the same pattern fastmcp 4 uses).os/mcp_auth_builtin.py): adapted to the v2OAuthClientInformationFull—client_idis now a requiredstr(removed deadNoneguards),token_endpoint_auth_method/redirect_urisareOptional(handled),model_dump_json(by_alias=True)for stored client metadata.context/web/exa_mcp.py,context/web/parallel_mcp.py):StreamableHTTPClientParams(timeout=...)as float seconds.MCPError, snake_caseCallToolResult, 2-tuple transports).Fixes #9267
Type of change
Checklist
./scripts/format.shand./scripts/validate.sh)Duplicate and AI-Generated PR Check
Additional Notes
Verified in a clean environment against
mcp 2.0.0+fastmcp 4.0.0b1+mcp-types 2.0.0:libs/agnosource files clean under the mcp 2.0 environment.formatandcheckclean (1998 files).tests/unit/tools/test_mcp.py: 76 passed.test_mcp_auth_builtin,test_mcp_oauth,test_mcp_run_results,test_mcp_server,test_mcp_resolution,test_mcp_surface_v2,test_mcp_auth_tier2,test_registry_mcp_tools): 230 passed.MCPToolsover stdio against a fastmcp 4.0.0b1 / mcp 2.0.0 server completes connect →list_tools→call_toolsuccessfully.Two things worth a maintainer's eye:
>=4.0.0b1,<5). The intent is to move to the stable fastmcp 4.x as soon as it ships; happy to gate that here or track it separately.FastMCP/Contextare no longer top-level exports; AgentOS already imports them fromfastmcp.server.server/fastmcp.server.context, which is compatible.Status: do not merge yet. This pins fastmcp to the
4.0.0b1pre-release. I'll update the pin to the stable fastmcp 4.x once it ships and re-verify — the PR should only be merged after that.