Type Alias: MCPProtocolOptions
MCPProtocolOptions =
ProtocolOptions&object
Defined in: node_modules/.bun/@modelcontextprotocol+client@2.2.0/node_modules/@modelcontextprotocol/client/dist/index.d.mts:1891
Type Declaration
cachePartition?
optionalcachePartition?:string
Opaque per-principal identifier for response-cache writes whose
server-reported cacheScope is 'private' (the spec's "MUST NOT share
across authorization contexts"). Within the connected server's
namespace, 'public'-scoped entries live at the shared
[serverIdentity, ''] partition and 'private'-scoped entries at
[serverIdentity, cachePartition]. Set this to a stable identity of
the authorization context (e.g. the auth subject) when one
responseCacheStore backs several principals; with the
default '' every entry — public or private — lives at the server's
shared partition, which is the safe single-tenant posture.
capabilities?
optionalcapabilities?:ClientCapabilities
Capabilities to advertise as being supported by this client.
defaultCacheTtlMs?
optionaldefaultCacheTtlMs?:number
TTL (ms) applied when a cacheable result arrives without a ttlMs
field. Default 0 — a result without an explicit hint is never served
from cache (every call refetches), but it is still stored so the
tools/list-derived index that Client.callTool | callTool's
SEP-2243 mirroring and output-schema validation read keeps working
regardless. The spec defines absent-or-≤0 as "immediately stale".
inputRequired?
optionalinputRequired?:InputRequiredOptions
Multi-round-trip auto-fulfilment (protocol revision 2026-07-28).
On the 2026-07-28 era, servers obtain client input (elicitation,
sampling, roots) by answering tools/call, prompts/get, or
resources/read with an input_required result instead of sending a
server→client request. By default the client fulfils those embedded
requests automatically through the SAME handlers registered via
Client.setRequestHandler | setRequestHandler (e.g.
elicitation/create), then retries the original call with the
collected inputResponses and a byte-exact echo of the opaque
requestState, on a fresh request id, up to maxRounds rounds.
client.callTool() (and its siblings) keep returning their plain
result type — the interactive rounds happen inside the call.
Set autoFulfill: false for manual mode: an input_required response
then surfaces as a typed error unless the individual call passes
allowInputRequired: true (pair it with withInputRequired() on the
explicit-schema path to type both outcomes).
Has no effect on 2025-era connections, which have no input_required
vocabulary.
jsonSchemaValidator?
optionaljsonSchemaValidator?:jsonSchemaValidator
JSON Schema validator for tool output validation.
The validator is used to validate structured content returned by tools against their declared output schemas.
Default
Runtime-selected validator (AJV-backed on Node.js, @cfworker/json-schema-backed on browser/workerd runtimes)
listChanged?
optionallistChanged?:ListChangedHandlers
Configure handlers for list changed notifications (tools, prompts, resources).
Example
const client = new Client(
{ name: 'my-client', version: '1.0.0' },
{
listChanged: {
tools: {
onChanged: (error, tools) => {
if (error) {
console.error('Failed to refresh tools:', error);
return;
}
console.log('Tools updated:', tools);
}
},
prompts: {
onChanged: (error, prompts) => console.log('Prompts updated:', prompts)
}
}
}
);
listMaxPages?
optionallistMaxPages?:number
Cap on the number of pages the auto-aggregating
Client.listTools | listTools() /
Client.listPrompts | listPrompts() /
Client.listResources | listResources() /
Client.listResourceTemplates | listResourceTemplates() walk
fetches before throwing (a defence against a server whose nextCursor
never converges). 0 disables the cap. Default: 64. Applies only to
the no-argument auto-aggregate path; an explicit-cursor per-page call
is never capped.
responseCacheStore?
optionalresponseCacheStore?:ResponseCacheStore
The response-cache store backing the client's derived views (the cached
tools/list result that Client.callTool | callTool's output
validation and SEP-2243 header mirroring read) and the SEP-2549
cache-hint serving on the cacheable verbs. Defaults to a fresh
InMemoryResponseCacheStore per client.
Entries are automatically scoped by connected-server identity (derived
from serverInfo after connect) AND, for 'private'-scoped results,
by cachePartition — encoded collision-free via JSON.stringify, so a
server cannot craft a serverInfo that bleeds into another server's
namespace or another principal's slot. One store may therefore back
several clients (e.g. a host pool against the same server, or one
persistent KV across servers); list_changed evictions are scoped to
the connected server's partitions, so co-tenants are unaffected. Set
cachePartition to your principal identifier (e.g. the auth subject)
when sharing across principals. Note serverInfo is self-reported — a
server that deliberately impersonates
another's name/version shares its 'public' slot; the
per-principal isolation via cachePartition holds regardless.
versionNegotiation?
optionalversionNegotiation?:VersionNegotiationOptions
Opt-in protocol version negotiation (protocol revision 2026-07-28 and later).
The default is 'legacy': absent (or mode: 'legacy'), connect()
runs the plain 2025 sequence, byte-identical to today's behavior (no
probe, no new headers). Opt into 'auto' or pin to talk to a 2026-07-28
server.
mode: 'auto'—connect()probes the server withserver/discoverfirst: definitive modern evidence selects the modern era; definitive legacy signals (and anything unrecognized) fall back to the plain legacyinitializehandshake, byte-equivalent to a 2025 client. On the SDK's own stdio transport (the baseStdioClientTransportexactly; subclasses probe in place) the probe runs on a short-lived sibling process spawned from the same parameters (one extra spawn per connect; its stderr is discarded) and the caller's transport starts once, after the era is known; HTTP — and custom or subclassed stdio-shaped transports — probe on the connection itself. A network outage rejects with a typed connect error. A probe timeout is transport-aware: on stdio it indicates a legacy server (some legacy servers never answer unknown pre-initializerequests) and falls back toinitialize; on HTTP it rejects with a typed timeout error (silence on a deployed server is an outage, not a legacy signal).mode: { pin: '2026-07-28' }— modern era at exactly the pinned revision; no probe-and-fallback: anything else fails loudly.
Probe policy lives under probe: { timeoutMs?, maxRetries? }; the probe
inherits the client's standard request timeout unless overridden, and
maxRetries (default 0) governs timeout re-sends only — the
spec-mandated -32022 corrective continuation is never counted against it.
Once a modern era is negotiated, the client automatically attaches the
per-request _meta envelope (the reserved protocol-version / client-info /
client-capabilities keys) to every outgoing request and notification;
user-supplied _meta keys take precedence over the auto-attached ones.