Repository navigation
feat: migrate to the mcp 2.0 SDK, release 0.5.0 - #6
Merged
Merged
Conversation
Completes the work 0.4.2 deferred. 2.0.0 removed the @app.list_tools() / @app.call_tool() decorators the server registered all 85 tools with (#2); they are replaced by on_list_tools / on_call_tool callbacks on the Server constructor, which take a ServerRequestContext plus typed request params and return ListToolsResult / CallToolResult instead of bare content lists. The pin inverts: mcp>=2.0.0. The 0.4.2 ceiling was load-bearing because the code spoke 1.x; now the floor is, because the code speaks 2.x. An upper bound returns when 3.0 is on the horizon. The wire output is deliberately byte-identical to 0.4.x — same tool names, same schemas, same response content, same error strings. A migration that also changes behaviour cannot be verified as a migration. Returning is_error=True on the exception path is the semantically correct thing and is left as a follow-up. Also: the server now reports its version in the handshake, read from the installed distribution rather than duplicated in source. smoke.yml asserted by calling server.list_tools() with no arguments, which this change breaks — the handler's signature belongs to the SDK. It now asserts against server.ALL_TOOLS, the registry we actually own, so the test measures the package and not the SDK's calling convention. Verified against the built wheel installed in a clean venv (never src/): - 85 tools, 85 handlers, no orphans either direction - entry point exits 0 on EOF - initialize still negotiates protocolVersion 2025-03-26, and inputSchema is still camelCase on the wire (mcp 2.0 keeps the camelCase aliases, so none of the 85 tool definitions changed) - selenium-mcp-test Java suite: 68/68 pass over real stdio JSON-RPC - the new floor is real: forced onto mcp 1.29.0 the import fails loudly at ServerRequestContext, and pip refuses the combination Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the loop on #2. 0.4.2 stopped the bleeding by pinning
mcp<2.0.0; this does the migration that pin was holding the door open for.The change
mcp2.0.0 removed the@app.list_tools()/@app.call_tool()decorators the server registered all 85 tools with. They're replaced byon_list_tools/on_call_toolcallbacks on theServerconstructor — handlers now take aServerRequestContextplus typed request params and returnListToolsResult/CallToolResultrather than bare content lists.The surface really was as small as the gate predicted.
mcp2.0 keeps camelCase aliases on its models (populate_by_name+validate_by_alias), soTool(..., inputSchema=...)still validates — none of the 85 tool definitions across the fourtools/*.pyfiles needed a single edit. Onlyserver.pychanged.The pin inverts to
mcp>=2.0.0. The 0.4.2 ceiling was load-bearing because the code spoke 1.x; the floor is load-bearing now because the code speaks 2.x.No wire change, on purpose
Tool names, input schemas, response content and error strings are byte-for-byte what 0.4.x emitted. A migration that also changes behaviour can't be verified as a migration. Returning
is_error: trueon the exception path is the semantically correct thing and is deliberately left as a follow-up.smoke.ymlhad to change — and it caught itselfThe smoke test called
server.list_tools()with no arguments, so this migration breaks it. That signature belongs to the SDK, not to us. It now asserts againstserver.ALL_TOOLS— the registry we own — so the test measures the package rather than the SDK's calling convention.Verification
Against the built wheel installed into a clean venv, never
src/:initializestill negotiatesprotocolVersion 2025-03-26inputSchemastill camelCase intools/listselenium-mcp-testJava suitemcp1.29.0 the import fails loudly atServerRequestContext; pip refuses the combination outrightSuite run under
xvfbwith the clean venv first onPATH, sopython -m selenium_mcp.serverresolved to the installed artifact.The CHANGELOG's Infrastructure section describes Trusted Publishing and Dependabot, which land in #5. More importantly: do not tag 0.5.0 until #5 is merged and the PyPI publisher is enrolled, or the release will fail at the 403 that has been failing since ~July 1 and 0.5.0 will need publishing by hand like the three before it.