Skip to content

[MCP-PROTOCOL]: Migrate to Python MCP SDK 2.0.0 #5559

Description

@jonpspri

Epic Overview

Migrate ContextForge from Python MCP SDK 1.x to 2.0.0, addressing all breaking changes, adopting new features, and ensuring full compatibility with the updated MCP specification.

Migration Guide Reference: https://py.sdk.modelcontextprotocol.io/v2/migration/

Background

MCP Python SDK v2.0.0 introduces significant breaking changes to improve API design, align with the MCP specification, and enhance type safety. This is a major version upgrade requiring comprehensive code changes and thorough testing.

Key Breaking Changes

1. Core Renames & Imports

  • FastMCPMCPServer (main server class)
  • mcp.typesmcp-types package (standalone)
  • McpErrorMCPError (exception class)

2. Field Naming Convention

  • All fields changed from camelCase to snake_case:
    • inputSchemainput_schema
    • isErroris_error
    • nextCursornext_cursor
    • progressTokenprogress_token
  • Critical: Must use by_alias=True when serializing models to JSON

3. Type System Changes

  • Resource URIs now str instead of AnyUrl
  • Extra fields on MCP types no longer preserved (use _meta instead)
  • RootModel unions replaced with TypeAdapter validation
  • Stricter field validation across the board

4. Server Changes

  • Constructor signature changed
  • Context injection via ctx parameter (not mcp.get_context())
  • Sync handlers now run on worker threads
  • Transport parameters moved from constructor to run() method
  • MCPError raised in handlers surfaces as JSON-RPC error

5. Client Changes

  • Connection mode defaults to 'auto' (use 'legacy' for old behavior)
  • get_server_capabilities() → properties: server_capabilities, server_info, protocol_version
  • cursor parameter removed (use params=PaginatedRequestParams(cursor=...))
  • Timeouts now float seconds instead of timedelta
  • Request timeout error code: 408-32001 (REQUEST_TIMEOUT)
  • streamablehttp_client removed (use streamable_http_client)
  • WebSocket transport removed entirely

Migration Phases

Phase 1: Dependency Updates & Core Renames (1 week)

Dependencies:

  • Update minimum versions: anyio ≥4.9, pydantic ≥2.12, sse-starlette ≥3.0
  • Add mcp-types package dependency
  • Update pyproject.toml with new version constraints
  • Verify no dependency conflicts

Core Renames:

  • Replace FastMCPMCPServer imports
  • Replace McpErrorMCPError throughout codebase
  • Update mcp.typesmcp_types imports
  • Update all import statements in test files

Verification:

  • All imports resolve correctly
  • No import errors in CI/CD
  • Dependency installation succeeds

Phase 2: Field Name Migration (1-2 weeks)

Code Changes:

  • Convert all camelCase fields to snake_case:
    • inputSchemainput_schema
    • isErroris_error
    • nextCursornext_cursor
    • progressTokenprogress_token
    • Review all MCP type usages for field name changes
  • Add by_alias=True to all JSON serialization calls
  • Update Pydantic model definitions
  • Update test assertions and fixtures

Verification:

  • All field accesses use snake_case
  • JSON serialization produces correct camelCase output
  • No AttributeError exceptions in tests
  • API responses match expected format

Phase 3: Server Migration (2-3 weeks)

MCPServer Constructor:

  • Update constructor calls: FastMCP(name, desc)MCPServer(name, instructions=desc)
  • Move transport parameters from constructor to run() method
  • Update all server initialization code

Context Injection:

  • Replace mcp.get_context() with ctx: Context parameter injection
  • Update all tool handlers to accept ctx parameter
  • Update all resource handlers to accept ctx parameter
  • Update all prompt handlers to accept ctx parameter

Handler Behavior:

  • Review sync handlers (now run on worker threads)
  • Update return types: ensure call_tool() returns CallToolResult
  • Update error handling: MCPError now surfaces as JSON-RPC error
  • Remove automatic error wrapping assumptions

Low-Level Server Changes:

  • Update handler registration from decorators to constructor on_* parameters
  • Update handlers to receive (ctx, params) instead of unpacked arguments
  • Update handlers to return full result types (no automatic wrapping)
  • Remove request_context property usage (use injected ctx)

Verification:

  • All server handlers updated
  • Context injection working correctly
  • Error handling behaves as expected
  • Transport configuration correct

Phase 4: Client Migration (1-2 weeks)

Connection Mode:

  • Review client connection mode (defaults to 'auto')
  • Add mode='legacy' where needed for backward compatibility
  • Test both auto and legacy modes

API Changes:

  • Replace get_server_capabilities() with properties
  • Update pagination: remove cursor parameter, use params=PaginatedRequestParams(cursor=...)
  • Convert timeout timedelta to float seconds
  • Update error code handling: 408-32001

Transport Changes:

  • Replace streamablehttp_client with streamable_http_client
  • Remove get_session_id callback usage
  • Remove WebSocket transport usage (if any)

Verification:

  • All client code updated
  • Connection modes working correctly
  • Pagination working correctly
  • Timeouts working correctly

Phase 5: Type System Updates (1 week)

Resource URIs:

  • Update resource URI handling: AnyUrlstr
  • Use urllib.parse for URI parsing where needed
  • Update URI validation logic

Extra Fields:

  • Replace extra field preservation with _meta usage
  • Update RootModel unions to TypeAdapter validation
  • Review and update field validation logic

Verification:

  • URI handling working correctly
  • Metadata preservation working correctly
  • Type validation working correctly

Phase 6: New Features Adoption (1-2 weeks)

Multi-Round Requests:

  • Implement InputRequiredResult for tools requiring client input
  • Implement InputRequiredResult for resources requiring client input
  • Implement InputRequiredResult for prompts requiring client input
  • Add tests for multi-round request flows

Enhanced Security:

  • Review resource templates for path-safety enforcement
  • Implement RFC 6570 URI template support
  • Update OAuth validation logic

Protocol Improvements:

  • Ensure _meta envelope on every request
  • Verify OpenTelemetry integration (enabled by default)
  • Update error codes and validation

Verification:

  • Multi-round requests working correctly
  • Security enhancements in place
  • Protocol improvements validated

Phase 7: Deprecation Handling (1 week)

Address Deprecations:

  • Review client resource subscriptions (SEP-2575)
  • Review roots, sampling, logging methods (SEP-2577)
  • Review client-to-server progress (deprecated 2026-07-28)
  • Replace SUPPORTED_PROTOCOL_VERSIONS with HANDSHAKE_PROTOCOL_VERSIONS
  • Plan migration away from deprecated features

Verification:

  • No deprecation warnings in logs
  • Migration plan documented for deprecated features

Phase 8: Testing & Validation (2-3 weeks)

Unit Tests:

  • Update all unit tests for SDK 2.0.0
  • Add tests for new features
  • Add tests for migration edge cases
  • Achieve >90% test coverage

Integration Tests:

  • Update integration tests for SDK 2.0.0
  • Test server-client interactions
  • Test transport configurations
  • Test error handling

End-to-End Tests:

  • Update E2E tests for SDK 2.0.0
  • Test full request/response flows
  • Test multi-round requests
  • Test pagination and timeouts

Performance Tests:

  • Benchmark SDK 2.0.0 performance
  • Compare with SDK 1.x baseline
  • Identify and address performance regressions

Verification:

  • All tests passing
  • No regressions detected
  • Performance acceptable

Phase 9: Documentation & Deployment (1 week)

Documentation:

  • Update API documentation for SDK 2.0.0
  • Create migration guide for users
  • Update developer documentation
  • Update deployment guides
  • Document breaking changes

Deployment:

  • Deploy to staging environment
  • Validate staging deployment
  • Deploy to production
  • Monitor production deployment

Verification:

  • Documentation complete and accurate
  • Deployment successful
  • No production issues

Acceptance Criteria

  • All SDK 1.x code migrated to SDK 2.0.0
  • All breaking changes addressed
  • All field names converted to snake_case
  • All server handlers updated with context injection
  • All client code updated for new API
  • All type system changes implemented
  • New features adopted where applicable
  • Deprecations addressed with migration plan
  • Test coverage >90%
  • All tests passing (unit, integration, E2E)
  • Performance benchmarks met
  • Documentation complete
  • Successful production deployment
  • No regressions in functionality

Common Migration Issues & Fixes

Issue: AttributeError: 'Tool' object has no attribute 'inputSchema'

Fix: Use input_schema (snake_case)

Issue: ModuleNotFoundError: No module named 'mcp.server.fastmcp'

Fix: Import from mcp.server.mcpserver

Issue: TypeError: unsupported operand type(s) for +: 'float' and 'datetime.timedelta'

Fix: Replace timedelta(seconds=30) with 30 (plain float)

Issue: Sync handler raises RuntimeError from asyncio.get_running_loop()

Fix: Declare handler as async def or avoid asyncio calls (runs on worker thread)

Issue: Resource URI AttributeError: 'str' object has no attribute 'host'

Fix: URIs are now plain strings; use urllib.parse to parse them

Dependencies

  • Python MCP SDK 2.0.0
  • mcp-types package
  • anyio ≥4.9
  • pydantic ≥2.12
  • sse-starlette ≥3.0
  • Existing ContextForge codebase

Related Issues

Success Metrics

  • 100% SDK 1.x code migrated to SDK 2.0.0
  • Zero breaking changes for end users
  • Test coverage >90%
  • No performance regressions
  • Successful production deployment
  • Zero critical bugs in first 30 days

Timeline Estimate

  • Phase 1: Dependency Updates & Core Renames (1 week)
  • Phase 2: Field Name Migration (1-2 weeks)
  • Phase 3: Server Migration (2-3 weeks)
  • Phase 4: Client Migration (1-2 weeks)
  • Phase 5: Type System Updates (1 week)
  • Phase 6: New Features Adoption (1-2 weeks)
  • Phase 7: Deprecation Handling (1 week)
  • Phase 8: Testing & Validation (2-3 weeks)
  • Phase 9: Documentation & Deployment (1 week)

Total: 11-16 weeks

Risks & Mitigation

Risk: Breaking Changes Impact Production

  • Mitigation: Comprehensive testing, staged rollout, rollback plan

Risk: Performance Regressions

  • Mitigation: Performance benchmarking, optimization, monitoring

Risk: Incomplete Migration

  • Mitigation: Thorough code review, automated checks, migration checklist

Risk: User Impact

  • Mitigation: Clear communication, migration guide, support resources

Notes

This is a major version upgrade with extensive breaking changes. The migration must be thorough and well-tested to avoid production issues. The phased approach ensures systematic migration with validation at each step.

References

Labels

epic, mcp-protocol, enhancement, breaking-change

Metadata

Metadata

Assignees

Labels

control-planeImpacts the control plane -- configuration and control.enhancementNew feature or requestmcp-protocolAlignment with MCP protocol or specification

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions