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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions