Conversation
The MCP Python SDK released 2.0 on 2026-07-28, which renamed FastMCP to MCPServer and moved mcp.server.fastmcp.* to mcp.server.mcpserver.*. The sample code's pyproject.toml allowed mcp>=1.20.0, so a fresh `uv sync` resolved to 2.x and the server failed on its first import with ModuleNotFoundError. Also fixes a Windows incompatibility that readers reported in the tutorial comments. The client wrapped the server process in a POSIX shell (`sh -c "... 2>/dev/null"`) purely to silence server stderr. On Windows, `sh` isn't on PATH and /dev/null doesn't exist, so stdio_client() failed to spawn the subprocess. Launching sys.executable directly and routing stderr through the SDK's own errlog parameter works identically on Windows, macOS, and Linux. Changes: - mcp_server.py: FastMCP -> MCPServer - mcp_client.py: drop the `sh -c` wrapper for sys.executable + errlog - pyproject.toml: pin mcp>=2.2.0,<3 - uv.lock: regenerate (mcp 1.18.0 -> 2.2.0, openai 2.6.0 -> 3.11.0) The lockfile was already out of sync before this change, pinning mcp>=1.17.0 against a pyproject that specified >=1.20.0. Verified with `uv run python -m mcp_client mcp_server/mcp_server.py --members`, which lists the server's tool, prompt, and resource correctly on mcp 2.2.0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Holding off on merging this — Final QA on the companion tutorial (CMS post 2355) didn't run, and the card is back with the author: https://trello.com/c/PTZubVff The blocker is the The Resolution agreed on the card is to move to the latest The |
- openai>=2.6.1 (unbounded) resolved to 3.11.0 in uv.lock, drifting from the article's pinned 2.6.1 and causing a version mismatch reviewers flagged. Pin to openai>=3.16.2,<4.0 to match the article and regenerate uv.lock. - Bump MODEL to gpt-5.4-mini (gpt-4o-mini's mini-tier successor) since gpt-4o-mini's currency was already flagged as unverified. - gpt-5.4-mini rejects the max_tokens param; switch both chat.completions.create() calls to max_completion_tokens. - mcp 2.x renamed Tool.inputSchema to Tool.input_schema. _get_tools() still read the old camelCase name via getattr(), which silently fell back to an empty schema and dropped every tool's parameters. Fixed to input_schema and verified live that tool-call arguments are populated correctly again. - Sync the mcp specifier's upper bound (<3 -> <3.0) with the article.
The MCP Python SDK released 2.0 on 2026-07-28 (2.2.0 is current), renaming
FastMCPtoMCPServerand movingmcp.server.fastmcp.*tomcp.server.mcpserver.*. This folder'spyproject.tomlallowedmcp>=1.20.0with no upper bound, so a freshuv synctoday resolves to 2.x and the sample server dies on its first import withModuleNotFoundError: No module named 'mcp.server.fastmcp'.This also fixes a Windows bug that two readers reported on Build a Python MCP Client to Test Servers From Your Terminal (2025-11-24 and 2026-05-03) and that Bartosz diagnosed in the thread. The client wrapped the server process in a POSIX shell,
sh -c "{sys.executable} {server_path} 2>/dev/null", purely to silence the server's stderr. On Windows,shisn't on PATH and/dev/nulldoesn't exist, sostdio_client()can't spawn the subprocess and the app dumps a stacktrace. Runningsys.executabledirectly and passing the SDK's ownerrlogparameter behaves the same on Windows, macOS, and Linux.What changed
mcp_server/mcp_server.py:FastMCP→MCPServermcp_client/mcp_client.py: dropped thesh -cwrapper forsys.executable+errlog, addedimport ospyproject.toml:mcp>=1.20.0→mcp>=2.2.0,<3uv.lock: regeneratedOnly the server's import and constructor needed changing. Every client-side API the tutorial teaches —
ClientSession,StdioServerParameters,stdio_client(),.list_tools()/.list_prompts()/.list_resources(), and.call_tool()withresult.content[0].text— is unchanged in 2.x, and the migration guide's client-side breaks (the removedcursorparam,timedelta→ float timeouts) don't apply because this code never used either.Two incidental fixes: the lockfile was already out of sync before this change, pinning
mcp>=1.17.0against a pyproject that said>=1.20.0; andgreeting_prompt()returned"Great {name} kindly."where the tutorial says"Greet".openaimoves to 3.11.0 in the regenerated lock — I checkedhandlers.py'sOpenAI()and.chat.completions.create()usage against it and no code change was needed.Testing
uv run python -m mcp_client mcp_server/mcp_server.py --memberslists the server's tool, prompt, and resource correctly on mcp 2.2.0, andcall_tool()round-trips. The Windows path wasn't tested on a Windows machine — the fix removes the POSIX-only dependency, which is what broke.Ran
ruff format --check,ruff check, anddircheck.pylocally with ruff 0.14.1 and all pass.Related
Matches the tutorial update in CMS post 2355, a clone of 2015 that isn't published yet. Python MCP Server: Connect LLMs to Your Data has the same 2.x break with a larger blast radius, since
FastMCPis that tutorial's subject — out of scope here, still needs its own fix.🤖 Generated with Claude Code