Skip to content

fix(git): migrate to MCP Python SDK v2 constructor-based API - #4606

Open
droidada wants to merge 1 commit into
modelcontextprotocol:mainfrom
droidada:fix/4580-mcp-v2-migration
Open

fix(git): migrate to MCP Python SDK v2 constructor-based API#4606
droidada wants to merge 1 commit into
modelcontextprotocol:mainfrom
droidada:fix/4580-mcp-v2-migration

Conversation

@droidada

@droidada droidada commented Aug 3, 2026

Copy link
Copy Markdown

Fixes #4580. The v1 decorator based handlers (@server.list_tools, @server.call_tool) no longer exist in v2; the low-level Server now takes handlers as on_* constructor arguments. Also pins mcp>=2,<3 in pyproject.toml, the missing upper bound was the actual root cause: an unconstrained mcp>=1.0.0 let a fresh install silently resolve to the incompatible v2 SDK.

Also removes the unused list_repos()/by_roots() helper, confirmed dead via grep, which relied on the now-removed ambient server.request_context property.

Description

Migrates mcp-server-git from the MCP Python SDK v1 decorator API to the v2 constructor-based API, and fixes the dependency constraint that let this break in the first place.

Server Details

  • Server: git
  • Changes to: tools (handler registration and error handling)

Motivation and Context

mcp-server-git fails to start after a fresh install with AttributeError: 'Server' object has no attribute 'list_tools'. Root cause: pyproject.toml declared mcp>=1.0.0 with no upper bound, so a fresh install now resolves the v2 SDK, which removed the decorator-based handler API entirely.

While migrating, I also found and fixed a real regression: v2 removed automatic exception wrapping in the lowlevel Server (handler exceptions no longer become CallToolResult(isError=True) automatically). I confirmed this directly, calling git_diff with an invalid target correctly raised BadName inside the validation logic, but the exception propagated as an unhandled crash instead of a clean error response. handle_call_tool now wraps its body in try/except and returns CallToolResult(is_error=True, ...) explicitly, restoring v1's behavior. Without this fix, every one of this server's existing defense-in-depth validation checks (in git_diff, git_create_branch, git_checkout, git_show, and git_branch) would silently crash the request instead of returning a usable error.

How Has This Been Tested?

Tested with the MCP Inspector CLI against a real client, not just the existing test suite:

  • Confirmed mcp==2.0.0 actually installed (uv pip show mcp), not assumed
  • Full existing pytest suite passes against the real v2 SDK (43 passed)
  • tools/list returns all twelve tools with correct schemas and correct camelCase wire format
  • tools/call for git_log returns real commit history end to end
  • Deliberate failure test: git_diff with target=-x now returns a clean isError: true result with a readable message, instead of the unhandled crash it produced before the fix

Breaking Changes

None for end users of the published server. Internal handler registration changed from decorators to constructor arguments, which only affects contributors to this file directly.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)

Checklist

  • I have read the MCP Protocol Documentation
  • My changes follows MCP security best practices
  • I have updated the server's README accordingly
  • I have tested this with an LLM client
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have documented all environment variables and configuration options

Additional context

None of the underlying git validation logic changed, BadName checks, flag-injection defense in depth, and repo path validation are all unchanged. Only the SDK integration layer and error handling shape changed.

Fixes modelcontextprotocol#4580. The v1 decorator based handlers (@server.list_tools,
@server.call_tool) no longer exist in v2; the low-level Server now
takes handlers as on_* constructor arguments. Also pins mcp>=2,<3
in pyproject.toml, the missing upper bound was the actual root
cause: an unconstrained mcp>=1.0.0 let a fresh install silently
resolve to the incompatible v2 SDK.

Also removes the unused list_repos()/by_roots() helper, confirmed
dead via grep, which relied on the now-removed ambient
server.request_context property.
@droidada
droidada force-pushed the fix/4580-mcp-v2-migration branch from aa56a79 to 985bfce Compare August 3, 2026 15:42
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.

mcp-server-git: Fails to start due to incompatible mcp version

1 participant