Skip to content

feat: migrate MCP tooling to mcp 2.x - #6537

Open
ProgrammerPlus1998 wants to merge 1 commit into
google:mainfrom
ProgrammerPlus1998:feat/mcp-2x-migration
Open

feat: migrate MCP tooling to mcp 2.x#6537
ProgrammerPlus1998 wants to merge 1 commit into
google:mainfrom
ProgrammerPlus1998:feat/mcp-2x-migration

Conversation

@ProgrammerPlus1998

@ProgrammerPlus1998 ProgrammerPlus1998 commented Jul 31, 2026

Copy link
Copy Markdown

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:

adk-python pins the MCP Python SDK below 2.0 (mcp>=1.24,<2), which blocks
installing alongside mcp 2.0.0. The 2.0 release makes several breaking changes
to the SDK surface that the MCP tool integration relies on.

Solution:

Bump the dependency to mcp>=2.0.0,<3 and adapt to the 2.0 API:

  • McpErrorMCPError; ProgressFnT now lives in mcp.shared.dispatcher
    (mcp.shared.session was removed).
  • Read snake_case model attributes (input_schema, output_schema, is_error,
    mime_type) instead of the removed camelCase aliases.
  • ClientSession(read_timeout_seconds=...) now takes float seconds rather than
    a timedelta.
  • The public McpHttpClientFactory moved to a private module, so declare the
    equivalent factory Protocol locally instead of importing it.
  • to_mcp_server: mcp.server.fastmcp was removed; build the server with
    mcp.server.mcpserver.MCPServer instead.

Behavior change worth a closer look (review requested):

In mcp 2.0 the server-side Context.session is a fresh ServerSession per
request rather than one stable object per connection. The agent-as-MCP-server
feature kept one ADK session per MCP connection keyed on ctx.session, which no
longer works. _connection_key now keys that map on the underlying shared
Connection object (read via ctx.session._connection, falling back to the
session itself). Connection is shared by every request on a connection and is
weak-referenceable, so WeakKeyDictionary cleanup still works. This touches a
private SDK attribute because mcp.server.mcpserver.Context exposes no public
per-connection identifier — happy to switch to a public hook if the maintainers
can point me at one.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Updated the MCP tool unit tests to the 2.0 surface (snake_case attributes,
MCPError(code=..., message=...), float timeouts, and an in-memory
client/server helper replacing the removed
create_connected_server_and_client_session).

tests/unittests/tools/mcp_tool/ ......... 226 passed, 0 failed

(run against an environment with mcp==2.0.0 installed)

Manual End-to-End (E2E) Tests:

Verified _connection_key against the real mcp 2.0 SDK: two ServerSession
objects built on one shared Connection resolve to the same key, distinct from
either per-request session, and a session object without _connection falls
back to itself.

To exercise the agent-as-server path manually:

from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.mcp_tool._agent_to_mcp import to_mcp_server

agent = LlmAgent(name="assistant", model="gemini-2.0-flash", ...)
server = to_mcp_server(agent)
server.run(transport="stdio")

then call the exposed tool twice over one MCP connection and confirm the second
call continues the same ADK conversation.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

Additional context

The dependency-floor changes in mcp 2.0 (pydantic>=2.12, anyio>=4.9,
typing-extensions>=4.13, plus new required opentelemetry-api and
mcp-types) are satisfied by ADK's existing constraints.

@google-cla

google-cla Bot commented Jul 31, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@adk-bot adk-bot added the mcp [Component] This issues is related to MCP support label Jul 31, 2026
@ProgrammerPlus1998

Copy link
Copy Markdown
Author

I've signed the CLA. Could a maintainer please re-trigger the CLA check?

Bump the mcp dependency to >=2.0.0,<3 and adapt the MCP tool
integration to the 2.0 SDK surface:

- McpError -> MCPError; ProgressFnT now lives in mcp.shared.dispatcher
  (mcp.shared.session was removed).
- Read snake_case model attributes (input_schema, output_schema,
  is_error, mime_type) instead of the removed camelCase aliases.
- ClientSession read_timeout_seconds now takes float seconds, not a
  timedelta.
- streamable_http_client / streamable-http layer: the public
  McpHttpClientFactory moved to a private module, so declare the
  equivalent factory Protocol locally.
- to_mcp_server: mcp.server.fastmcp was removed; build the server with
  mcp.server.mcpserver.MCPServer instead.

In mcp 2.0 the server-side Context.session is a fresh ServerSession per
request rather than per connection, so key the per-connection ADK
session map on the shared underlying Connection object (with a fallback
to the session) to keep one conversation per MCP connection.

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

Labels

mcp [Component] This issues is related to MCP support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support mcp 2.x (Python SDK): pin blocks mcp 2.0.0

3 participants