Upgrade a Python server from SDK 1.x (FastMCP) to 2.x (MCPServer)
- Spec
2025-11-25 → 2026-07-28- Evidence
- E2Reproducedarm64
- Python SDK
mcp@2.3.0- Verified
Most Python MCP tutorials were written for SDK 1.x and start with from mcp.server.fastmcp import FastMCP. If your project does not pin the version, a fresh install now gets 2.x and that line fails.
We ran the same 1.x server with mcp==1.30.0 and mcp==2.3.0 and fixed it step by step. The errors below are what we saw.
Step 1: the import
Section titled “Step 1: the import”On 2.3.0, the v1 import fails immediately:
ModuleNotFoundError: No module named 'mcp.server.fastmcp'. This is mcp 2.x, where FastMCP was renamedto MCPServer (from mcp.server.mcpserver import MCPServer) and other APIs changed; see the migration guideat https://py.sdk.modelcontextprotocol.io/v2/migration/#fastmcp-renamed-to-mcpserver or pin 'mcp<2'to keep running v1 code.If you just need the old code to run, pin the old line: mcp<2 in your requirements. Otherwise rename:
from mcp.server.fastmcp import FastMCP, Contextmcp = FastMCP("demo")
# 2.xfrom mcp.server.mcpserver import MCPServer, Contextmcp = MCPServer("demo")Step 2: settings moved to run()
Section titled “Step 2: settings moved to run()”In 1.x, transport settings went to the constructor:
mcp = FastMCP("demo", host="127.0.0.1", port=8000, stateless_http=True, json_response=True)mcp.run(transport="streamable-http")With only the import renamed, 2.3.0 stops with:
TypeError: MCPServer.__init__() got an unexpected keyword argument 'host'Move them to run():
mcp = MCPServer("demo")mcp.run(transport="streamable-http", host="127.0.0.1", port=8000, stateless_http=True, json_response=True)Code that sets them afterwards fails too: mcp.settings.port = 8000 raised ValueError: "Settings" object has no field "port". According to the migration guide, the SDK also no longer reads MCP_* environment variables or .env files, so read those yourself and pass the values in.
After these two steps our server ran on 2.3.0 and answered both a 2025-11-25 initialize and a 2026-07-28 request.
Step 3: things that still run but changed
Section titled “Step 3: things that still run but changed”| What | 1.x | 2.x (what we saw) |
|---|---|---|
| Default server name | FastMCP |
mcp-server |
| Reported version when you set none | The mcp package version (1.30.0) |
An empty string |
await ctx.info(...) |
Works | Works, with MCPDeprecationWarning: The logging capability is deprecated as of 2026-07-28 (SEP-2577). |
Set name and version explicitly, and move log output to Python’s logging module writing to stderr. Logging over MCP is deprecated in the 2026-07-28 spec.
Other changes in the migration guide
Section titled “Other changes in the migration guide”We did not test each of these; they come from the official migration guide. Check the ones your code touches:
ctx.fastmcpis nowctx.mcp_server.FastMCPErroris nowMCPServerError.McpErroris nowMCPError, imported frommcp.MCPServer.get_context()is gone; declare actx: Contextparameter on the tool instead.mount_pathis gone. Mount the app with Starlette’sMount(see the HTTP guide).- A mounted Streamable HTTP app needs
mcp.session_manager.run()in the outer app’s lifespan. - Attributes on result and type objects are snake_case:
structured_content,is_error,input_schema. - Synchronous
deftools now run in a worker thread. Useasync defif the tool needs the event loop. - A missing resource returns
-32602with the URI in the error data. - The low-level
ServerAPI changed from decorators to constructor arguments such ason_call_tool.
Sources
MCPDev is community documentation. It is not affiliated with the Model Context Protocol project or with the vendors of the clients it covers.