Proof of Concept - Python MCP SDK 2 Migration - #10427
Open
gsmith-alvarez wants to merge 8 commits into
Open
Conversation
In MCP SDK 2.0, FastMCP was renamed to MCPServer and the import path changed from mcp.server.fastmcp to mcp.server.mcpserver. Transport-specific parameters (stateless_http, streamable_http_path, transport_security) were also moved off the MCPServer constructor and onto streamable_http_app(), as the constructor no longer accepts them. Changes: - Replace with in both code_server/main.py and server/main.py - Move stateless_http, streamable_http_path, and transport_security from MCPServer() constructor to streamable_http_app() calls - Remove redundant constructor arguments (stateless_http was a duplicate since it was also set at app creation time in v1)
MCP SDK 2.0 renamed all Pydantic model fields from camelCase to snake_case. The JSON wire format is unchanged (Pydantic aliases handle serialization), but Python attribute access now uses snake_case names. Key renames per the migration guide: - CallToolResult.isError -> is_error - Tool.inputSchema -> input_schema Changes in client.py: - _create_error_result(): use is_error=True (was isError=True) - is_error_result(): check both is_error and isError via getattr for cross-version compatibility - extract_text_content(): use self.is_error_result() helper instead of inline hasattr(result, "isError") check (eliminates duplication) - _add_server_tools(): read tool.input_schema with fallback to tool.inputSchema for cross-version compat; pass inputSchema to Tool() constructor which accepts both spellings via Pydantic populate_by_name Changes in tool_manager.py: - _convert_mcp_tool(): use mcp_tool.input_schema (was inputSchema)
MCP SDK 2.0 removed the deprecated streamablehttp_client function (renamed to streamable_http_client in v1.x). The legacy fallback test that patches streamablehttp_client now fails at import time because the attribute no longer exists on mcp.client.streamable_http. Changes: - test_http_connector_connect_legacy_fallback: remove @patch decorator for streamablehttp_client and instead check hasattr() at runtime, calling pytest.skip() when the legacy function is absent. This keeps the test working on MCP 1.x (where streamablehttp_client exists) while gracefully skipping on MCP 2.0+ where it was removed.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
|
All contributors have signed the CLA ✍️ ✅ |
for more information, see https://pre-commit.ci
mcp==2.0.0 was published 2026-07-28. The previous "7 days" window excluded it from dependency resolution, causing Vercel deploy failures.
Contributor
There was a problem hiding this comment.
Pull request overview
Proof-of-concept migration of marimo’s MCP integration to the Python MCP SDK 2.x API surface (server/client/tool schema naming and transport wiring), along with dependency constraint updates to target MCP 2.x.
Changes:
- Migrate MCP server setup from
FastMCPtoMCPServer, moving HTTP transport config intostreamable_http_app(...). - Update MCP client/tool handling to prefer snake_case fields (e.g.
is_error,input_schema) with selective backward-compat fallbacks. - Update dependency constraints to require
mcp>=2and adjust tests accordingly (including removing legacy fallback coverage).
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/_server/ai/test_mcp.py | Removes legacy streamable HTTP fallback test aligned with dropping older MCP SDK behavior. |
| pyproject.toml | Updates MCP optional dependency constraints to MCP 2.x and adjusts formatting. |
| marimo/_server/ai/tools/tool_manager.py | Updates MCP tool schema field access to snake_case. |
| marimo/_server/ai/mcp/transport.py | Updates streamable HTTP connector to use MCP SDK 2 client + httpx2. |
| marimo/_server/ai/mcp/client.py | Updates error/tool schema handling for MCP SDK 2 with compatibility fallbacks. |
| marimo/_mcp/server/main.py | Migrates the main MCP server from FastMCP to MCPServer and updates HTTP app wiring. |
| marimo/_mcp/code_server/main.py | Migrates the code-mode MCP server from FastMCP to MCPServer and updates HTTP app wiring. |
| timeout=server_def.timeout, | ||
| ) | ||
| # Establish streamable HTTP connection | ||
| read, write = await exit_stack.enter_async_context( |
Contributor
Author
There was a problem hiding this comment.
The new streamable_http_client is a 2-tuple of read and write. So *_ is no longer needed.
Comment on lines
176
to
180
| return ToolDefinition( | ||
| name=namespaced_name or mcp_tool.name, | ||
| description=mcp_tool.description or "No description available", | ||
| parameters=mcp_tool.inputSchema, | ||
| parameters=mcp_tool.input_schema, | ||
| source="mcp", |
Comment on lines
116
to
119
| mcp = [ | ||
| "mcp>=1.0.0,<2", # MCP 2.0 is a major rework, unsupported for now. | ||
| "mcp>=2", # MCP 2.0 is a major rework, unsupported for now. | ||
| "pydantic>2", | ||
| ] |
Contributor
Author
There was a problem hiding this comment.
httpx2 is a transitive dependency of mcp>=2
Comment on lines
458
to
460
| return CallToolResult( | ||
| isError=True, | ||
| is_error=True, | ||
| content=[TextContent(type="text", text=error_message)], |
gsmith-alvarez
marked this pull request as draft
August 2, 2026 01:16
gsmith-alvarez
marked this pull request as ready for review
August 2, 2026 01:17
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#10388
#10373
#10433
📝 Summary
Seeing that my orginal pr was only part of the migration I wanted to see if I could do the rest of it for a small project.
I do not expect this to be merged as 2.0 largely breaks compatibility with 1.0.
I hope this pr serves more to assist when the migration eventually occurs.
Key changes:
FastMCP was renamed to MCPServer
The MCPServer object no longer take
stateless_http,streamable_http_path,transport_securityand these now must be passed intomcp.streamable_http_app().The SDK has transitioned from preferring CamalCase to preferring snake_case.
The tests were mostly just updated to use snake_case for when calling the server and I updated the Tool type to use the snake_case preferred from the SDK.
Finally, I dropped the try/except for support for
streamablehttp_clientand adopted thehttpx2as advised from their docs.Resources
Here is a picture to show that the server is responding.
NOTE:
I had to hardcore the
exclude-newertag for this to work.Also, don't know how to fix the ruff formatting so that it doesn't clog up the git change.
📋 Pre-Review Checklist
✅ Merge Checklist