v0.3.0 — mcp 2.x
Migration to the mcp 2.x SDK. No change to the simulation, the tools, or the replicate floor.
FastMCP was renamed, not removed — it is now mcp.server.mcpserver.MCPServer, the same class with the same kwargs. The dependency moves to mcp>=2,<3 rather than widening to <3: this package imports mcp.server.mcpserver, absent in 1.x, so a range spanning both majors could resolve to a version that cannot import the server. mcp 2.x requires Python >=3.10, below this package's >=3.11 floor, so the support matrix is unchanged.
The one real API change behind the renames
call_tool now returns a CallToolResult instead of a (content, structured) tuple. Tests read .structured_content directly; the old out[1] if isinstance(out, tuple) else out shim is gone rather than extended, since a shape sniff would silently hand back the result object if the field were renamed again, surfacing the failure far from its cause.
mcp.types fields are snake_case (outputSchema → output_schema, readOnlyHint → read_only_hint). The camelCase spellings survive as pydantic aliases, so constructing ToolAnnotations still works either way — but that rescue does not extend to attribute access, which is what the tests do.
A test that could pass for the wrong reason
test_single_replicate_is_refused_through_the_tool_layer used pytest.raises(Exception). During this migration it caught an unrelated TypeError from a break three lines above it, and only the match="replicates" kept it from passing for the wrong reason. It now expects ToolError, so it can distinguish the refusal under test from any other failure on the way to it.
Full changelog: https://github.com/musharna/breedsim-mcp/blob/master/CHANGELOG.md