Python: feat(core): migrate MCP integration to mcp 2.0.0 - #7468
Python: feat(core): migrate MCP integration to mcp 2.0.0#7468pratik wayase (PratikWayase) wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Migrates the Python agent-framework-core MCP integration to the MCP Python SDK v2.0.0, updating internal protocol handling and tests to match MCP’s breaking API/model changes while enabling the workspace to resolve MCP 2.x.
Changes:
- Updated core MCP client integration (
_mcp.py) for MCP 2.0.0 API/model changes (snake_case fields,MCPError, request model usage, task payload parsing via Pydantic extras). - Updated MCP-related unit tests to construct MCP 2.0-compatible models and assertions, including conditional skipping of the WebSocket transport test when not available.
- Updated workspace/package dependency constraints to allow installing MCP 2.0.0.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| python/packages/core/agent_framework/_mcp.py | Adapts MCP integration code to SDK 2.0.0 request/response models, error types, and renamed fields. |
| python/packages/core/tests/core/test_mcp.py | Updates tests for MCP 2.0.0 model shapes/fields and skips WebSocket test when transport module is unavailable. |
| python/packages/core/pyproject.toml | Updates the all optional dependency group to allow MCP 2.0.0. |
| python/packages/foundry_hosting/pyproject.toml | Updates package dependency to allow MCP 2.0.0. |
| python/packages/hosting-mcp/pyproject.toml | Updates package dependency to allow MCP 2.0.0. |
Suppressed comments (1)
python/packages/core/agent_framework/_mcp.py:2474
- The comment explaining the MCP 2.0
GetTaskPayloadResultextras is mis-indented, making it look like it’s part of theexceptblock even though the extraction logic is outside the handler. Aligning the comment with the surrounding code will avoid confusion.
# In MCP 2.0, GetTaskPayloadResult only declares `meta`; the actual
# CallToolResult fields are carried as Pydantic extra fields.
|
Evan Mattson (@moonbox3) Eduard van Valkenburg (@eavanvalkenburg) Tao Chen (@TaoChenOSU) Does this PR fulfill all the requirements of the issue, or does it need any further modifications? |
| lenient = await self.session.send_request( # type: ignore[union-attr] | ||
| request, | ||
| types.Result, | ||
| _LenientResult, |
There was a problem hiding this comment.
What happens when an MCP 2 server accepts this call and returns only a task? ClientSession.send_request validates every tools/call response as CallToolResult before applying _LenientResult, so a valid task response without content raises before we capture its task ID and can leave a side-effecting remote task running untracked. Could we use a raw request path or an upstream-supported task result union so the open response is preserved before strict validation, and cover this through a real ClientSession path rather than a mocked send_request?
There was a problem hiding this comment.
Thanks for catching this. To prevent the orphaned task scenario, we added a ValidationError catch immediately after send_request. if the SDK strictly bypasses _LenientResult and enforces CallToolResult we now wrap it in a ToolExecutionException to safely halt execution and prevent an untracked retry.
5350c2e to
eae3116
Compare
|
Hey pratik wayase (@PratikWayase) can you address the failing checks here |
|
Please re-open when ready to address CI/CD failures. |
Summary
Migrate
agent-framework-corefrommcp>=1.xtomcp>=2.0.0, adapting to all breaking API changes in the MCP Python SDK while preserving existing framework behavior. This includes updating production code, test suites, workspace dependency pins, and the lockfile.Motivation & Context
The MCP Python SDK 2.0.0 introduced significant breaking changes including snake_case attribute renames, Union type aliases replacing wrapper classes, exception restructuring, and payload serialization changes. Without this migration,
agent-framework-corecannot use MCP 2.0 servers or benefit from upstream improvements. This change unblocks adoption of MCP 2.0 across the agent framework ecosystem.Fixes #7446
Description & Review Guide
What are the major changes?
Production code (
_mcp.py):McpError→MCPErrorand removed.errorwrapper (.code,.messageaccessed directly)mime_type,is_error,structured_content,input_schema,next_cursor,protocol_version,stop_reason,tool_use_id,poll_interval,status_message,task_support)types.ClientRequest()wrappers in 4 locations (now a Union type alias in MCP 2.0)message.root.method→message.methodforServerNotificationdispatchread_timeout_secondsfromtimedeltatofloat__pydantic_extra__extraction in_fetch_task_resultand_call_tool_as_task_create(MCP 2.0GetTaskPayloadResultandResultonly declaremeta; tool result fields are carried as extras)system_prompt,tool_choice,stop_sequences,max_tokens)_send_with_one_reconnectrequest param type fromtypes.ClientRequesttoAnymime_type=keyword arg in content preparation constructorsTest code (
test_mcp.py):Mock(spec=ServerNotification)with real notification instances (ToolListChangedNotification,PromptListChangedNotification) since Union types don't support isinstance checks against MocksAnyUrlobjects to plain strings forurifieldsMCPErrorconstructor calls to usecode=andmessage=directly_make_create_task_result/_make_task_snapshottimestamps fromdatetimeto ISO 8601 strings_make_payloadto construct viaCallToolResultround-trip for extras compatibilitymcp.client.websocketremoved in base MCP 2.0.0).root.method/.root.paramsto direct attribute accessWorkspace dependencies:
foundry_hostingandhosting-mcppyproject.tomlto allowmcp>=2.0.0(previously pinned<2, causing downgrade onuv sync)uv.lockwithmcp==2.0.0resolved across the entire workspaceWhat is the impact of these changes?
foundry_hostingandhosting-mcpare required to preventuv sync/poe syntaxfrom downgrading MCP back to 1.x. These packages may need their own MCP 2.0 migration in follow-up PRs.MCPWebsocketToolnow requiresmcp[ws]extra; the basemcppackage no longer bundles WebSocket support.What do you want reviewers to focus on?
__pydantic_extra__extraction logic in_fetch_task_resultand_call_tool_as_task_create— this is the most novel pattern, needed because MCP 2.0'sGetTaskPayloadResultandResultmodels only declaremetaand carry tool result fields as Pydantic extras.message.methodvs oldmessage.root.method) — confirm theisinstance(message, types.ServerNotification)check works correctly with real notification instances in tests.foundry_hostingandhosting-mcptomcp>=2.0.0is acceptable for this PR scope, or whether those packages should remain pinned and be migrated separately.Related Issue
Fixes #7446
Contribution Checklist