# Migration Guide: v1 to v2 This guide covers the breaking changes introduced in v2 of the MCP Python SDK and how to update your code. ## Overview Version 2 of the MCP Python SDK introduces several breaking changes to improve the API, align with the MCP specification, and provide better type safety. ## Breaking Changes ### `streamablehttp_client` removed The deprecated `streamablehttp_client` function has been removed. Use `streamable_http_client` instead. **Before (v1):** ```python from mcp.client.streamable_http import streamablehttp_client async with streamablehttp_client( url="http://localhost:8000/mcp", headers={"Authorization": "Bearer token"}, timeout=30, sse_read_timeout=300, auth=my_auth, ) as (read_stream, write_stream, get_session_id): ... ``` **After (v2):** ```python import httpx from mcp.client.streamable_http import streamable_http_client # Configure headers, timeout, and auth on the httpx.AsyncClient http_client = httpx.AsyncClient( headers={"Authorization": "Bearer token"}, timeout=httpx.Timeout(30, read=300), auth=my_auth, ) async with http_client: async with streamable_http_client( url="http://localhost:8000/mcp", http_client=http_client, ) as (read_stream, write_stream, get_session_id): ... ``` ### `StreamableHTTPTransport` parameters removed The `headers`, `timeout`, `sse_read_timeout`, and `auth` parameters have been removed from `StreamableHTTPTransport`. Configure these on the `httpx.AsyncClient` instead (see example above). ### Removed type aliases and classes The following deprecated type aliases and classes have been removed from `mcp.types`: | Removed | Replacement | |---------|-------------| | `Content` | `ContentBlock` | | `ResourceReference` | `ResourceTemplateReference` | **Before (v1):** ```python from mcp.types import Content, ResourceReference ``` **After (v2):** ```python from mcp.types import ContentBlock, ResourceTemplateReference ``` ### `args` parameter removed from `ClientSessionGroup.call_tool()` The deprecated `args` parameter has been removed from `ClientSessionGroup.call_tool()`. Use `arguments` instead. **Before (v1):** ```python result = await session_group.call_tool("my_tool", args={"key": "value"}) ``` **After (v2):** ```python result = await session_group.call_tool("my_tool", arguments={"key": "value"}) ``` ### `cursor` parameter removed from `ClientSession` list methods The deprecated `cursor` parameter has been removed from the following `ClientSession` methods: - `list_resources()` - `list_resource_templates()` - `list_prompts()` - `list_tools()` Use `params=PaginatedRequestParams(cursor=...)` instead. **Before (v1):** ```python result = await session.list_resources(cursor="next_page_token") result = await session.list_tools(cursor="next_page_token") ``` **After (v2):** ```python from mcp.types import PaginatedRequestParams result = await session.list_resources(params=PaginatedRequestParams(cursor="next_page_token")) result = await session.list_tools(params=PaginatedRequestParams(cursor="next_page_token")) ``` ### `mount_path` parameter removed from FastMCP The `mount_path` parameter has been removed from `FastMCP.__init__()`, `FastMCP.run()`, `FastMCP.run_sse_async()`, and `FastMCP.sse_app()`. It was also removed from the `Settings` class. This parameter was redundant because the SSE transport already handles sub-path mounting via ASGI's standard `root_path` mechanism. When using Starlette's `Mount("/path", app=mcp.sse_app())`, Starlette automatically sets `root_path` in the ASGI scope, and the `SseServerTransport` uses this to construct the correct message endpoint path. ### Resource URI type changed from `AnyUrl` to `str` The `uri` field on resource-related types now uses `str` instead of Pydantic's `AnyUrl`. This aligns with the [MCP specification schema](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/schema/draft/schema.ts) which defines URIs as plain strings (`uri: string`) without strict URL validation. This change allows relative paths like `users/me` that were previously rejected. **Before (v1):** ```python from pydantic import AnyUrl from mcp.types import Resource # Required wrapping in AnyUrl resource = Resource(name="test", uri=AnyUrl("users/me")) # Would fail validation ``` **After (v2):** ```python from mcp.types import Resource # Plain strings accepted resource = Resource(name="test", uri="users/me") # Works resource = Resource(name="test", uri="custom://scheme") # Works resource = Resource(name="test", uri="https://example.com") # Works ``` If your code passes `AnyUrl` objects to URI fields, convert them to strings: ```python # If you have an AnyUrl from elsewhere uri = str(my_any_url) # Convert to string ``` Affected types: - `Resource.uri` - `ReadResourceRequestParams.uri` - `ResourceContents.uri` (and subclasses `TextResourceContents`, `BlobResourceContents`) - `SubscribeRequestParams.uri` - `UnsubscribeRequestParams.uri` - `ResourceUpdatedNotificationParams.uri` The `ClientSession.read_resource()`, `subscribe_resource()`, and `unsubscribe_resource()` methods now accept both `str` and `AnyUrl` for backwards compatibility. ## Deprecations ## New Features ## Need Help? If you encounter issues during migration: 1. Check the [API Reference](api.md) for updated method signatures 2. Review the [examples](https://github.com/modelcontextprotocol/python-sdk/tree/main/examples) for updated usage patterns 3. Open an issue on [GitHub](https://github.com/modelcontextprotocol/python-sdk/issues) if you find a bug or need further assistance