mcp 2.0.0 (MCP protocol revision 2026-07-28) was released on 2026-07-28. This repo pins mcp>=1.27.0,<2.0.0 and fastmcp>=3.2.4,<4.0.0. I did a real dry run of the upgrade to find out what it would take, and hit one hard blocker plus one failure worth flagging early. Filing rather than sending a PR because the blocker is not in your hands.
No urgency implied: the SDK's own migration guide states v2 speaks the 2025-era protocol unless a server explicitly opts in, and the spec carries a minimum twelve-month deprecation window. mcp 1.x also continues receiving critical fixes.
The blocker
Every fastmcp release through stable 3.4.5 transitively requires mcp>=1.24.0,<2.0. Only the 4.0.0 pre-release line (4.0.0a1, 4.0.0a2, 4.0.0b1) accepts mcp>=2.0.0. So uv lock fails outright on bumping mcp alone, and only resolves with --prerelease=allow once fastmcp is also moved to the beta. There is nothing to do here until fastmcp 4 ships stable.
What I found by running it anyway
With mcp==2.0.0 + fastmcp==4.0.0b1, from mcp_atlassian.servers import main_mcp imports cleanly, and pytest tests/unit gives 3688 passed / 3 failed / 5 skipped. All three failures share one root cause:
AttributeError: 'ErrorPreservingFastMCP' object has no attribute '_call_tool_mcp'
AtlassianMCP._call_tool_mcp (src/mcp_atlassian/servers/main.py:361-373) ends in return await super()._call_tool_mcp(key, arguments), and that method no longer exists on FastMCP in 4.0.0b1. Its replacement is a different name and a different parameter shape, so it is not a rename-only fix:
_on_call_tool(ctx: ServerRequestContext, params: CallToolRequestParams) -> CallToolResult | InputRequiredResult | BaseModel
The reason only call-side tests break is that _list_tools_mcp's override never calls super(); it drives its own filtering off the still-present public self.list_tools().
The one I would flag hardest: the third failure is tests/unit/servers/test_mcp_protocol.py::TestMCPProtocolIntegration::test_call_tool_mcp_enforces_enablement_at_dispatch, whose own docstring cites GHSA-3r68 ("A tool filtered out of the listing must not be invocable by name... Verifies denied calls never reach the underlying executor"). Because the failure mode is super() disappearing from the dispatch override, this is worth treating as a security-relevant porting step rather than a routine test fix, and worth confirming the enablement check still holds on the new _on_call_tool path.
The other two failures are tests/unit/servers/test_error_handling.py::test_deprecated_tool_is_preserved_in_registered_mcp_tool[asyncio-inner] and [asyncio-outer].
Deprecation warnings to pick up eventually
These still work but are on notice, all SDK-wide renames rather than anything specific to this repo:
Tool.inputSchema -> input_schema, hit directly at src/mcp_atlassian/servers/main.py:88 (schema = tool.inputSchema in _sanitize_schema_for_compatibility)
ToolAnnotations.destructiveHint -> destructive_hint
BlobResourceContents.mimeType / ImageContent.mimeType -> mime_type
Scope, once unblocked
Smaller than it might appear: the one method port, the two affected test files, and the three deprecation call sites. Roughly 3-4 files. Happy to open the PR once fastmcp 4 is stable, or sooner if you would accept a branch pinned to the pre-release.
One note on the --stateless flag: it is not made obsolete by mcp 2.0, it still gates real behaviour on the legacy path. But mcp 2.0 routes any request actually carrying the 2026-07-28 _meta.protocolVersion to a handler that has no session concept regardless of that flag, so it becomes a no-op for clients speaking the new revision. That may be worth a docs line when the upgrade lands.
mcp2.0.0 (MCP protocol revision2026-07-28) was released on 2026-07-28. This repo pinsmcp>=1.27.0,<2.0.0andfastmcp>=3.2.4,<4.0.0. I did a real dry run of the upgrade to find out what it would take, and hit one hard blocker plus one failure worth flagging early. Filing rather than sending a PR because the blocker is not in your hands.No urgency implied: the SDK's own migration guide states v2 speaks the 2025-era protocol unless a server explicitly opts in, and the spec carries a minimum twelve-month deprecation window.
mcp1.x also continues receiving critical fixes.The blocker
Every
fastmcprelease through stable 3.4.5 transitively requiresmcp>=1.24.0,<2.0. Only the4.0.0pre-release line (4.0.0a1,4.0.0a2,4.0.0b1) acceptsmcp>=2.0.0. Souv lockfails outright on bumpingmcpalone, and only resolves with--prerelease=allowoncefastmcpis also moved to the beta. There is nothing to do here untilfastmcp4 ships stable.What I found by running it anyway
With
mcp==2.0.0+fastmcp==4.0.0b1,from mcp_atlassian.servers import main_mcpimports cleanly, andpytest tests/unitgives 3688 passed / 3 failed / 5 skipped. All three failures share one root cause:AtlassianMCP._call_tool_mcp(src/mcp_atlassian/servers/main.py:361-373) ends inreturn await super()._call_tool_mcp(key, arguments), and that method no longer exists onFastMCPin 4.0.0b1. Its replacement is a different name and a different parameter shape, so it is not a rename-only fix:The reason only call-side tests break is that
_list_tools_mcp's override never callssuper(); it drives its own filtering off the still-present publicself.list_tools().The one I would flag hardest: the third failure is
tests/unit/servers/test_mcp_protocol.py::TestMCPProtocolIntegration::test_call_tool_mcp_enforces_enablement_at_dispatch, whose own docstring cites GHSA-3r68 ("A tool filtered out of the listing must not be invocable by name... Verifies denied calls never reach the underlying executor"). Because the failure mode issuper()disappearing from the dispatch override, this is worth treating as a security-relevant porting step rather than a routine test fix, and worth confirming the enablement check still holds on the new_on_call_toolpath.The other two failures are
tests/unit/servers/test_error_handling.py::test_deprecated_tool_is_preserved_in_registered_mcp_tool[asyncio-inner]and[asyncio-outer].Deprecation warnings to pick up eventually
These still work but are on notice, all SDK-wide renames rather than anything specific to this repo:
Tool.inputSchema->input_schema, hit directly atsrc/mcp_atlassian/servers/main.py:88(schema = tool.inputSchemain_sanitize_schema_for_compatibility)ToolAnnotations.destructiveHint->destructive_hintBlobResourceContents.mimeType/ImageContent.mimeType->mime_typeScope, once unblocked
Smaller than it might appear: the one method port, the two affected test files, and the three deprecation call sites. Roughly 3-4 files. Happy to open the PR once
fastmcp4 is stable, or sooner if you would accept a branch pinned to the pre-release.One note on the
--statelessflag: it is not made obsolete by mcp 2.0, it still gates real behaviour on the legacy path. Butmcp2.0 routes any request actually carrying the 2026-07-28_meta.protocolVersionto a handler that has no session concept regardless of that flag, so it becomes a no-op for clients speaking the new revision. That may be worth a docs line when the upgrade lands.