Skip to content

comments: support both mcp majors in the MCP server - #292

Merged
bjornars merged 1 commit into
novem-code:mainfrom
bjornars:bsn/mcp-v2-compat
Sep 26, 2026
Merged

bjornars merged 1 commit into
novem-code:mainfrom
bjornars:bsn/mcp-v2-compat

Conversation

@bjornars

Copy link
Copy Markdown
Contributor

mcp 2.x moved mcp.server.fastmcp to mcp.server.mcpserver, renamed FastMCP to MCPServer and took Image with it, and renamed Tool.inputSchema to input_schema. Each is a hard import or attribute error for novem.comments.MCP(), which is why the extra was pinned to <2. All four confirmed against mcp 2.2.0, not inferred.

The failure also lied about itself. ModuleNotFoundError is an ImportError, so an installed 2.x was reported as The "mcp" extra is required — telling the user to install a package they already had.

_import_mcp() resolves either spelling, so the pin opens to <3. That relaxation is only honest because MCPServer turned out to be drop-in for everything this module touches — same positional-name constructor, .tool(), .list_tools(), .run() — which I checked before changing the pin rather than after.

The example needed widening too: v1's call_tool returns a list, or a (list, dict) tuple when the tool declares structured output; v2 returns a CallToolResult, which is not subscriptable at all, so the existing isinstance(result, tuple) guard falls through to result[0] and raises.

Where to spend attention: the pin. Opening it means a fresh pip install novem[mcp] now resolves to 2.x, so this is the change that alters what users get, and the compat tests are all that stand behind it. If you would rather stay on 1.x for now, keeping <2 and taking only the code changes is a coherent half of this PR.

Nothing installed the extra in CI, which is why the drift went unnoticed — uv sync does not include it, so the suite stayed green. The new job runs the compat tests against each major; the tests importorskip so they stay silent for anyone without the extra.

To verify: uv run --with 'mcp>=1,<2' pytest tests/test_mcp_compat.py and again with 'mcp>=2,<3'. Restricting _import_mcp to the v1 module fails four of the five under 2.x.

Fixes #265

mcp 2.x moved mcp.server.fastmcp to mcp.server.mcpserver, renamed
FastMCP to MCPServer and Image along with it, and renamed
Tool.inputSchema to input_schema. Every one of those is a hard import or
attribute error for novem.comments.MCP(), and the extra was pinned to
<2 to avoid them.

Worse, the failure lied about itself. ModuleNotFoundError is an
ImportError, so an installed 2.x was reported as 'The "mcp" extra is
required' -- telling the user to install a package they already had.

_import_mcp() resolves either spelling, so the pin can open to <3.
MCPServer is drop-in for what this module uses: the same positional-name
constructor, .tool(), .list_tools() and .run().

The example's call_tool handling also needed widening: v1 returns a list
or a (list, dict) tuple, while v2 returns a CallToolResult, which is not
subscriptable at all.

Nothing installed the extra in CI, which is why this went unnoticed, so
the new job runs the compat tests against each major.

@sondove sondove left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@bjornars
bjornars merged commit b142315 into novem-code:main Sep 26, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Migrate novem.comments.MCP() to mcp 2.x

2 participants