deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

FastMCP 4 reaches GA with breaking changes that compile silently

FastMCP 4 is generally available. Core APIs are unchanged, but an extras-based package split, an httpx2 swap and a sessionless client default can break MCP servers and clients without failing at import time.

FastMCP 4 reaches GA with breaking changes that compile silently

FastMCP 4, the Python framework for building Model Context Protocol servers and clients, is now generally available. According to a migration account published on dev.to, most of the visible API surface survives the jump from 3.x unchanged — the FastMCP constructor, the @mcp.tool decorator and mcp.run(transport=...) all behave as before. The danger sits in the changes that never announce themselves: code compiles, imports resolve, and then misbehaves at runtime.

The package split can strand an in-place upgrade

In 4.x, the fastmcp distribution became a thin meta-package that depends on fastmcp-slim[client,server], where the real code now lives; further extras cover options such as anthropic, azure, gemini and openai. Fresh installs are unaffected. But the dev.to author reports that running pip install -U fastmcp over a 3.2.x environment failed to re-resolve those base extras, producing a package that imports yet exposes nothing — from fastmcp import Client raises an ImportError even though the code is present in the wheel. The fix is to uninstall both fastmcp and fastmcp-slim before reinstalling, or to recreate the virtual environment. A related change: fastmcp no longer exposes version, so anything asserting on it should switch to importlib.metadata.version("fastmcp").

httpx2 makes exception handlers go quiet

FastMCP 4 dropped httpx internally in favour of httpx2, a next-generation fork. Because plain httpx usually remains transitively installed, a handler like except httpx.ConnectError around a FastMCP client call still imports and type-checks — it just never matches at runtime. The author recommends grepping for those handlers and either migrating them to httpx2 or catching fastmcp.exceptions.ToolError, which is usually the intent. Anything handed into FastMCP that is built on httpx — a custom client factory, an AsyncClient passed to a transport, an Auth object — must also move to httpx2, while direct httpx usage elsewhere is unaffected if httpx stays a dependency. Two knock-on effects: TLS verification now uses the OS trust store via truststore (honouring SSL_CERT_FILE and SSL_CERT_DIR) instead of bundled certifi, which may verify differently behind corporate CAs; and HTTP log records move from the httpx/httpcore namespaces to httpx2/httpcore2, so logging filters need updating.

Sessionless clients by default

Client(...) now defaults to mode="auto" and negotiates the modern 2026-07-28 protocol era, which is sessionless. That changes runtime behaviour invisibly: no on_initialize handshake runs, so middleware or init hooks tied to it never fire; ctx.set_state() no longer persists to the next call; and ctx.elicit() raises because the modern era has no server-initiated back-channel. Clients doing plain tool calls and resource reads need no change, but anything relying on session state or elicitation should pin mode="legacy". StreamableHttpTransport also dropped sse_read_timeout= in favour of a timeout= argument on the Client.

Removals, import moves and version floors

Several context methods are gone and raise AttributeError: ctx.sample(), ctx.sample_step() and ctx.list_roots(). The FastMCP(sampling_handler=...) option was removed with them, so servers that borrowed the caller's model must now call an LLM directly or stay on 3.x. Background tasks moved into an extension — @mcp.tool(task=True) does nothing until fastmcp[tasks] is installed and mcp.add_extension(TasksExtension()) is registered, otherwise startup raises — and task= is no longer valid on resources or prompts.

Import paths shifted too: Tool and ToolResult now come from fastmcp.tools, Resource from fastmcp.resources, and protocol types such as TextContent from mcp.types. mcp.import_server() becomes mcp.mount() (live composition rather than a snapshot), as_proxy becomes create_proxy from fastmcp.server, and tool transformations go through mcp.add_transform(ToolTransform(...)). The old CachableToolResult typo is fixed as CacheableToolResult with no alias, and McpError now takes code and message directly. SDK v2 renamed model fields from camelCase to snake_case; old reads are bridged with a deprecation warning, and setting fastmcp.settings.mcp_camelcase_compat (env FASTMCP_MCP_CAMELCASE_COMPAT) to false turns remaining camelCase reads into hard errors so they can be cleared now. On the dependency side, pydantic >= 2.12 is a hard requirement, and the FastAPI extra needs starlette >= 1.0.1, meaning FastAPI >= 0.133.0.

New defaults worth auditing

Per the dev.to write-up, three settings changed default behaviour without a line in the upgrade guide: telemetry_mode defaults to "native", auto-instrumenting OpenTelemetry spans for MCP calls (FASTMCP_TELEMETRY_MODE=off disables it); check_for_updates checks PyPI on startup, worth switching off in CI and containers; and client_raise_first_exceptiongroup_error defaults to true, so client errors surface as the first underlying exception rather than an ExceptionGroup — code using except* should be revisited. Newer knobs such as stateless_http and http_host_origin_protection are also listed on the settings page.

Why it matters

MCP servers are becoming standard plumbing between applications and models, and FastMCP is a common way to build them in Python. The defining risk of this release is that its breakages are silent: an upgrade that passes CI can still ship exception handlers that never catch, session state that never persists, and telemetry that starts emitting without anyone asking. Teams should pin fastmcp==4.0.x for applications, floor libraries at fastmcp>=4.0.0, uninstall before upgrading in place, and audit the flipped defaults before rolling out.

  • #mcp
  • #fastmcp
  • #python
  • #model-context-protocol

Related posts