MCPcopy Index your code
hub / github.com/modelcontextprotocol/python-sdk / negotiate_auto

Function negotiate_auto

src/mcp/client/_probe.py:41–79  ·  view source on GitHub ↗

Drive the ``mode='auto'`` connect-time policy on ``session``. Probes ``server/discover`` once (twice if the server names a mutual modern version via -32022), then either ``adopt()``s the result or falls back to ``initialize()``. Idempotent only in the sense that one of ``session.dis

(session: ClientSession)

Source from the content-addressed store, hash-verified

39
40
41async def negotiate_auto(session: ClientSession) -> None:
42 """Drive the ``mode='auto'`` connect-time policy on ``session``.
43
44 Probes ``server/discover`` once (twice if the server names a mutual
45 modern version via -32022), then either ``adopt()``s the result or falls
46 back to ``initialize()``. Idempotent only in the sense that one of
47 ``session.discover_result`` / ``session.initialize_result`` is set on
48 return.
49
50 Raises:
51 MCPError: The server is modern-only and shares no version with this
52 client (-32022 with a disjoint ``supported`` list).
53 Exception: Any transport/network error from the probe propagates as-is.
54 """
55 version = LATEST_MODERN_VERSION
56 for attempt in range(2):
57 try:
58 raw = await session.send_discover(version)
59 except MCPError as e:
60 if e.code == UNSUPPORTED_PROTOCOL_VERSION:
61 supported = _parse_supported(e.error.data)
62 mutual = [v for v in MODERN_PROTOCOL_VERSIONS if v in (supported or ())]
63 if mutual and attempt == 0:
64 version = mutual[-1]
65 continue
66 if supported is not None and not any(v in HANDSHAKE_PROTOCOL_VERSIONS for v in supported):
67 raise # server is modern-only and disjoint — real incompatibility
68 await session.initialize() # every other rpc-error → legacy (the denylist)
69 return
70 # any other exception (httpx.TransportError, ConnectionError, anyio errors,
71 # RuntimeError from adopt) → propagate
72 try:
73 result = types.DiscoverResult.model_validate(raw)
74 except ValidationError:
75 await session.initialize() # unparseable result → not modern evidence
76 return
77 session.adopt(result)
78 return
79 raise AssertionError("unreachable") # pragma: no cover — loop body always returns or raises

Callers 2

__aenter__Method · 0.90
_negotiateFunction · 0.90

Calls 4

_parse_supportedFunction · 0.85
send_discoverMethod · 0.45
initializeMethod · 0.45
adoptMethod · 0.45

Tested by 1

_negotiateFunction · 0.72