Urgent.News

What's breaking now, across thousands of outlets.

Tech

FastMCP 3 4 migration: the breaking changes that compile

FastMCP 4 is GA. If you have an MCP server or client on fastmcp 3.x, you'll upgrade soon. Most of it is painless — FastMCP(...) , @mcp.tool , and mcp.run(transport=...) are all unchanged. The parts that aren't painless are the parts that don't announce themselves. These are field notes on top of the official Upgrading from FastMCP 3 guide — the items that bit hardest when I moved one MCP server…

FastMCP 4 has been released as a GA version, but upgrading from FastMCP 3.x can be challenging. Most changes are painless, such as the unchanged FastMCP(...), @mcp.tool, and mcp.run(transport=...) functions. However, there are breaking changes that can lead to issues when upgrading.

One issue is that the pip install -U fastmcp command can leave an in-place upgrade half-broken. FastMCP 4 is now split into extras, with the fastmcp package serving as a thin meta-package that depends on fastmcp-slim[client,server]. When upgrading in place using pip install -U fastmcp, the base extras are not re-resolved, resulting in an importable shell with nothing in it. To fix this, uninstall and reinstall fastmcp and fastmcp-slim, or recreate the virtual environment.

Another issue is the transition from httpx to httpx2. FastMCP 4 dropped httpx for httpx2 internally, so a FastMCP client call that previously raised httpx.ConnectError now raises httpx2.ConnectError. This can be resolved by migrating the except clauses to catch httpx2.ConnectError or catching FastMCP's own fastmcp.exceptions.ToolError instead. Direct httpx calls remain unaffected as long as httpx is kept as a dependency.

FastMCP 4 also introduces a default mode= auto, which negotiates the modern protocol era. This changes runtime behavior, as no on_initialize handshake occurs, ctx.set_state() doesn't persist, and ctx.elicit() raises. If your client relies on session state, an init hook, or elicitation, pin it back to the legacy mode (Client(server, mode=legacy)).

Some methods have been removed, including ctx.sample(), ctx.sample_step(), and ctx.list_roots(). If your server borrowed the caller's model via ctx.sample(), you'll need to call an LLM directly from the server or stay on FastMCP 3.x. Background tasks have also moved to an extension, so @mcp.tool(task=True) and @mcp.resource/task no longer work by themselves. You must install fastmcp[tasks] and register mcp.add_extension(TasksExtension()).

Finally, FastMCP 4 has version floors for pydantic and starlette. If you use the server's FastAPI extra or starlette 1.x, you must pin the exact versions in your app's dependencies and tests.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

McKinley 1.0

Crackerjack new Mac app for creating and editing custom SF Symbols , from developer Amy Worrall: McKinley is an all-in-one studio for drawing and annotating SF Symbols.

More from Monday 7 September →