TTypeScript SDKSource ↗
connect({ prior: { kind: 'modern', discover } }) — zero-round-trip connect for gateways and distributed clients (protocol revision 2026-07-28).

gateway

connect({ prior: { kind: 'modern', discover } }) — zero-round-trip connect for gateways and distributed clients (protocol revision 2026-07-28).

pnpm --filter @mcp-examples/gateway server -- --http --port 3000
pnpm --filter @mcp-examples/gateway client -- --http http://127.0.0.1:3000/

The 2026 protocol is stateless on HTTP: every request carries the per-request _meta envelope (protocol version, client info, client capabilities), so once you know the server's DiscoverResult there is nothing left to negotiate. A gateway, proxy, or worker fleet that fronts the same server should not re-probe per worker — it probes once and every subsequent connect is free.

The pattern

// 1. Bootstrap: probe once.
const bootstrap = new Client({ name: 'bootstrap', version: '1.0.0' }, { versionNegotiation: { mode: 'auto' } });
await bootstrap.connect(new StreamableHTTPClientTransport(url));
const persisted = JSON.stringify(bootstrap.getDiscoverResult()); // → write to Redis / config / process-local cache
await bootstrap.close();

// 2. Every worker: zero-round-trip connect from the persisted blob.
const worker = new Client({ name: 'worker', version: '1.0.0' });
await worker.connect(new StreamableHTTPClientTransport(url), { prior: { kind: 'modern', discover: JSON.parse(persisted) } });
await worker.callTool({ name: 'echo', arguments: { text: 'hi' } }); // first wire traffic

getDiscoverResult() is populated by the 'auto'/pinned probe path, by client.discover(), and by a modern-verdict connect({ prior }) (a legacy verdict leaves it undefined). The value round-trips through JSON.stringify/JSON.parse.

What this story asserts

The server exposes a request_count tool returning how many MCP requests reached the process (createMcpHandler builds one server instance per request). The client asserts:

  • after the bootstrap probe + one request_count call, the count is 2;
  • after three worker connect({ prior }) calls + one request_count call, the count is 3 — proving the three connects sent zero requests;
  • each worker can callTool immediately;
  • after three echo calls + one request_count call, the count is 7.

When to use prior

  • A gateway/proxy that holds a long-lived connection pool to one server and constructs a fresh Client per downstream request.
  • A horizontally-scaled host where one worker's probe should seed the fleet (persist the blob to a shared cache).
  • Reconnecting after a transient transport drop without re-probing.

Security: same-credential reuse only

Only reuse a persisted DiscoverResult across workers that present the same authorization context as the bootstrap client (key the blob on a credential hash). Adopting a wider prior does not grant access — the server authorizes every request — but it can mislead client-side capability gating.

The modern verdict — prior: { kind: 'modern', discover } wrapping a persisted DiscoverResult — is modern-only: no mutual 2026-07-28+ revision → SdkError(EraNegotiationFailed). For a server known to be legacy, pass the negative verdict instead — prior: { kind: 'legacy' } skips the probe and goes straight to initialize. Freshness is the host's responsibility: date cached legacy verdicts in your own storage and stop supplying them past your policy horizon (a stale one succeeds silently against an upgraded server; with no prior, a mode: 'auto' client re-probes).


Source: examples/gateway/README.md

Generated by smolify with deterministic-repository-import-v1 · 1 source file