[Bug] Claude Desktop extensions broken after MCP server upgrade
Bug Description
MCP Python SDK 2.0.0 breaks Claude Desktop extensions/servers with an unpinned mcp dependency
Summary
The release of the MCP Python SDK mcp 2.0.0 (published to PyPI on 2026-07-28) removed the FastMCP 1.x compatibility layer (mcp.server.fastmcp) and renamed McpError to MCPError in mcp.shared.exceptions. Any MCP server package that declares an unpinned dependency such as mcp>=1.9.4 now resolves mcp==2.0.0 at install time and crashes on import, before the server can complete the MCP handshake.
In Claude Desktop this surfaces as the extension failing to start with only a generic error in the logs:
Server transport closed unexpectedly, this is likely due to the process exiting early/Server disconnected
Because launchers like uvx re-resolve dependencies into ephemeral environments, this broke previously-working installations overnight, with no change on the user's machine.
Environment
- OS: macOS (Darwin 25.5.0, Apple Silicon)
- Claude Desktop: latest as of 2026-07-29, servers launched via
uvx - uv/uvx: installed at
~/.local/bin/uvx - mcp (Python SDK): 2.0.0 (resolved automatically)
Affected servers (confirmed)
1. Docling MCP — Claude Desktop extension
The Docling extension bundles/resolves docling-mcp 2.1.0, which declares mcp[cli]>=1.9.4 (no upper bound). The resolved environment contains mcp 2.0.0, and the server dies on startup:
Traceback (most recent call last):
File ".../bin/docling-mcp-server", line 6, in <module>
from docling_mcp.servers.mcp_server import app
File ".../site-packages/docling_mcp/servers/mcp_server.py", line 9, in <module>
from docling_mcp.shared import mcp
File ".../site-packages/docling_mcp/shared.py", line 3, in <module>
from mcp.server.fastmcp import FastMCP
ModuleNotFoundError: No module named 'mcp.server.fastmcp'
Note: docling-mcp 2.2.0 (released 2026-07-28) already fixes the constraint to mcp[cli]>=1.9.4,<2.0.0 — but the Claude Desktop extension still launches 2.1.0. The extension bundle needs to be updated/re-published so users pick up the fixed version.
2. mcp-server-fetch (modelcontextprotocol/servers)
The latest release (2026.7.10) still declares mcp>=1.1.3 with no upper bound and fails the same way:
Traceback (most recent call last):
File ".../bin/mcp-server-fetch", line 6, in <module>
from mcp_server_fetch import main
File ".../site-packages/mcp_server_fetch/server.py", line 6, in <module>
from mcp.shared.exceptions import McpError
ImportError: cannot import name 'McpError' from 'mcp.shared.exceptions'. Did you mean: 'MCPError'?
Any other server with an unpinned mcp dependency that still imports mcp.server.fastmcp or McpError is affected the same way.
Steps to reproduce
- Install the Docling MCP extension in Claude Desktop (or configure
uvx mcp-server-fetchas a server). - Restart Claude Desktop so the server environment is (re-)resolved after 2026-07-28.
- The server crashes on import; Claude Desktop logs "Server disconnected".
Or reproduce outside Claude Desktop:
uvx mcp-server-fetch # ImportError: cannot import name 'McpError'
Workaround (verified)
Pin the SDK below 2.0 at launch time with uvx --with:
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"docling": {
"command": "/Users/<you>/.local/bin/uvx",
"args": [
"--from", "docling-mcp",
"--with", "mcp[cli]<2",
"docling-mcp-server",
"--transport", "stdio"
]
},
"fetch": {
"command": "/Users/<you>/.local/bin/uvx",
"args": ["--with", "mcp<2", "mcp-server-fetch"]
}
}
}
(Note: docling-mcp-server now defaults to streamable-http on port 8000, so --transport stdio is required for a config-based stdio server.)
Suggested fixes
- Server maintainers: add an upper bound (
mcp>=1.9.4,<2.0.0) or migrate to the 2.0 SDK APIs.docling-mcphas done this in 2.2.0;mcp-server-fetchstill needs it. - Extension publishers (Claude Desktop directory): re-publish extension bundles against the fixed package versions; consider pinning fully-resolved dependencies in
.mcpbbundles so a PyPI release can't break installed extensions. - Claude Desktop: when a stdio server exits before the
initializeresponse, surfacing the child process's stderr (the Python traceback above) directly in the extension UI would make failures like this self-explanatory instead of a generic "Server disconnected".
Environment Info
- Platform: darwin
- Terminal: ghostty
- Version: 2.1.220
- Feedback ID: 46f1517c-0d55-43d0-9233-de5949b1266d