Skip to content

[mcp/python-sdk] ClientSession has no way to specify protocolVersion #2307

@tsingh2k15

Description

@tsingh2k15

Initial Checks

Description

I could not determine if this may be design intent, but I ran into issue where ClientSession.initialize() hardcodes protocolVersion=types.LATEST_PROTOCOL_VERSION with no way for the caller to override it. When connecting to an MCP server that requires a specific protocol version (e.g. Snowflake's managed MCP server requires "2025-06-18"), the only workaround is to mutate the module-level constant before calling initialize() and restore it afterward. Please feel free me to provide guidance if this can be resolved differently.

Current behaviour (mcp/client/session.py, v1.26.0)

async def initialize(self) -> types.InitializeResult:
    result = await self.send_request(
        types.ClientRequest(
            types.InitializeRequest(
                params=types.InitializeRequestParams(
                    protocolVersion=types.LATEST_PROTOCOL_VERSION,  # no override possible
                    ...
                )
            )
        ),
        types.InitializeResult,
    )

ClientSession.init() accepts many optional parameters (sampling_callback, client_info, etc.) but has no protocol_version parameter.

Steps to reproduce

  • Install mcp>=1.0
  • Connect to any MCP server that requires a protocol version other than LATEST_PROTOCOL_VERSION
  • Call session.initialize() — the server rejects the handshake
  • Concrete example: Snowflake managed MCP server requires "2025-06-18". With mcp==1.26.0 (LATEST_PROTOCOL_VERSION = "2025-11-25"), the session is terminated immediately after initialize().

Proposed fix

Add an optional protocol_version parameter to ClientSession.init():

def __init__(
    self,
    read_stream: ...,
    write_stream: ...,
    ...
    protocol_version: str | None = None,  # NEW — defaults to LATEST_PROTOCOL_VERSION
) -> None:
    self._protocol_version = protocol_version or types.LATEST_PROTOCOL_VERSION

Then use it in initialize():

protocolVersion=self._protocol_version,

Non-breaking change; existing callers get the current default. Callers that need a specific version pass it explicitly without touching any globals.

Example Code

"""
ClientSession.initialize() hardcodes LATEST_PROTOCOL_VERSION
with no way to override it via the public API.

Tested with: Python 3.14.2, mcp==1.26.0
"""
import asyncio
import mcp.types as mcp_types
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamablehttp_client

MCP_URL = "https://<your-account>.snowflakecomputing.com/api/v2/databases/<DB>/schemas/<SCHEMA>/mcp-servers/<SERVER>"
HEADERS = {"Authorization": "Bearer <your-pat>", "X-Snowflake-Role": "<your-role>"}

# The version Snowflake's MCP server requires during initialize handshake.
# The library hardcodes "2025-11-25" — Snowflake rejects it with "Session terminated".
REQUIRED_VERSION = "2025-06-18"

async def main():
    # Without the patch — Snowflake terminates the session:
    async with streamablehttp_client(url=MCP_URL, headers=HEADERS) as (r, w, _):
         async with ClientSession(r, w) as session:
             await session.initialize()  # raises: "Session terminated"

asyncio.run(main())

Python & MCP Python SDK

Python: 3.14.2
MCP Python SDK: 1.26.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions