Build1 publisher3 min readPublished
The code moved into fastmcp-slim behind client and server extras, and pip -U over 3.2.x does not always re-resolve them. The httpx2 swap breaks a second class of code that still compiles.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
The meta-package is the whole mechanism. In 4.x, `fastmcp` carries no code of its own; it declares a dependency on `fastmcp-slim[client,server]`, and `fastmcp-slim` holds the modules [2]. The remaining functionality sits behind extras: `client`, `server`, `mcp`, `anthropic`, `apps`, `azure`, `code-mode`, `gemini`, `openai`, nine in total [3][25].
On a clean install none of this is visible, because `pip install fastmcp` resolves the base extras and everything imports [4]. The reported failure came from upgrading in place over 3.2.x with `pip install -U fastmcp`, where pip did not re-resolve those base extras and left a package that imported but contained nothing [5]. `fastmcp.__file__` returned `None`, `dir(fastmcp)` returned an empty list, and `from fastmcp import Client` raised `ImportError ... (unknown location)` [6]. That is what a directory with no modules in it looks like from the interpreter side. According to the author it burned two false-alarm debugging sessions, since a `ModuleNotFoundError` on a submodule that is genuinely in the wheel is a persuasive symptom [9].
The repair is to uninstall both `fastmcp` and `fastmcp-slim` and install again, pinning `fastmcp==4.0.x` if you want the version you tested, or to rebuild the virtualenv [7]. Before you generalise the diagnosis: this was hit with `pip -U`, and `uv pip install -U` was not tested [8]. FastMCP documents a separate pip file-manifest problem on the 3.2 to 3.3 hop and notes that uv is unaffected by that one, which is a different bug [8]. Carrying "uv is fine" across from the older note is an assumption, not a finding.
The asymmetry matters for how you find out. A CI job that builds a fresh environment every run will stay green [4]; the machines that break are the ones with history, including any host where a deploy step bumps a pin in place [5].
The second class of breakage compiles and type-checks. FastMCP 4 dropped `httpx` for `httpx2` internally, so a client call that raised `httpx.ConnectError` now raises `httpx2.ConnectError` [11]. Because `httpx` usually remains transitively installed, the old `except httpx.ConnectError` still resolves and simply stops matching [12]. The suggested sweep is a grep for `except httpx.` and a check of whether each one wraps a FastMCP `Client` or transport call [12]. Anything you hand in that was built on `httpx` moves too: a custom `httpx_client_factory`, an `httpx.AsyncClient` given to a transport, an `httpx.Auth` [13]. Log filters keyed on `httpx` or `httpcore.*` need repointing at `httpx2` and `httpcore2.*` [15].
Then the default protocol era. `Client(...)` now defaults to `mode="auto"` and negotiates the sessionless `2026-07-28` era, where the `on_initialize` handshake never fires, `ctx.set_state()` does not persist to the next call, and `ctx.elicit()` raises [16][17]. Clients doing plain `call_tool` and `read_resource` need no change [24]; anything leaning on session state or an init hook gets pinned with `mode="legacy"` [18]. `StreamableHttpTransport` also lost `sse_read_timeout=`, which moves to `timeout=` on the `Client` [19]. Elicitation still exists but requires `response_type` and raises on modern connections, so the rewrite is a guard tool returning an "input required" result [23].
`FastMCP(...)`, `@mcp.tool` and `mcp.run(transport=...)` are unchanged [21]. That is exactly why the rest is quiet: the surface your code touches still looks right.
Ranked by verification strength, evidence, and original report placement.
FastMCP 4 is GA, and servers or clients on fastmcp 3.x will upgrade soon.
In FastMCP 4 the fastmcp package is a thin meta-package that depends on fastmcp-slim[client,server]; fastmcp-slim carries the actual code.
fastmcp-slim's extras are client, server, mcp, anthropic, apps, azure, code-mode, gemini and openai.
On a fresh install the split is invisible: pip install fastmcp pulls fastmcp-slim[client,server] and everything works.
The author upgraded in place with pip install -U fastmcp over fastmcp 3.2.x; pip did not re-resolve the base extras, leaving an importable shell with nothing in it.
After the in-place upgrade, fastmcp.__file__ was None, dir(fastmcp) returned an empty list, and from fastmcp import Client raised ImportError: cannot import name 'Client' from 'fastmcp' (unknown location).
Follow any of these and your For You feed starts watching them — no settings page required.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
One transcript, one reader of the guide
The empty-install claim carries its own proof: a pasted session where fastmcp.__file__ is None, dir(fastmcp) comes back empty, and the Client import fails at an unknown location. That is checkable by anyone with a spare venv. The dozen items around it, including the nine extras, the httpx2 exception rename and the sessionless 2026-07-28 era, reach us through one developer's summary of the project's upgrade guide, with no maintainer statement or release note in our coverage, and the pip behaviour was seen on a single machine with the uv path untried.
A single migration, no ecosystem read
Usage evidence stops at one engineer moving one server and two clients. FastMCP 4's GA status is asserted in the same post rather than shown through a release artefact, and there is no download data, issue traffic or second team reporting the empty-shell install, so the frequency of the failure mode is unknown.
Framing slightly wider than the test
The headline generalises a single pip run into a property of in-place upgrades; the hedge that pip does not always re-resolve is fair, but one observation is doing the work of a pattern. Pulling the other way, the technical notes decline easy drama: the common case of plain call_tool and read_resource clients is flagged as needing no change at all, and the core decorators are called unchanged. Net stretch is small.
No disclosed stake, blog-post pull
No commercial relationship to FastMCP is stated or visible, and the post sends readers to the project's own upgrade guide rather than to anything the author sells. What remains is the ordinary incentive of a developer blog to lead with the most alarming failure, sharpened by the author's admission that this one cost him the same debugging session twice.
Cheap to verify, thinly corroborated
The mechanics hang together and each item names the exact symbol, flag or command involved, so a sceptic can falsify most of it in a test environment quickly. Confidence stays below halfway because every claim, including the ones with production reach such as OS trust-store verification and the renamed log namespaces, traces back to one publisher, a single machine, and one person's reading of the upgrade guide.
build
255 tool schemas, 91K tokens: pricing the two MCP costs nobody budgets1 publisher
build
AWS's Agent Toolkit ships two independent halves that break in different places1 publisher
build
One MCP command, three JSON shapes, and a failure mode that never errors1 publisher
build
Your CI Build Is Slow Because The Cache Is Empty, Not Because The Base Image Is Fat1 publisher
Publishers with included, body-backed reporting in this cluster.
1 article · September 7, 2026