{"version":3,"file":"stdio.cjs","names":["_stdin: Readable","process","_stdout: Writable","ReadBuffer","serializeMessage","_wire: Transport","_onInstanceClose: () => void","_outboundIntercept?: (message: JSONRPCMessage) => 'handled' | undefined","isJSONRPCResultResponse","isJSONRPCErrorResponse","isJSONRPCRequest","isJSONRPCNotification","carriesValidModernEnvelopeClaim","hasEnvelopeClaim","requestMetaOf","validateEnvelopeMeta","envelopeClaimVersion","SUPPORTED_MODERN_PROTOCOL_VERSIONS","state: EntryState","discarding: StdioConnectionChannel | undefined","StdioListenRouter","DEFAULT_MAX_SUBSCRIPTIONS","UnsupportedProtocolVersionError","modernOnlyStrictRejection","McpServer","serverIdentityOf","channel: StdioConnectionChannel","ProtocolErrorCode","queue: JSONRPCMessage[]"],"sources":["../src/server/stdio.ts","../src/server/serveStdio.ts"],"sourcesContent":["import type { Readable, Writable } from 'node:stream';\n\nimport type { JSONRPCMessage, Transport } from '@modelcontextprotocol/core-internal';\nimport { ReadBuffer, serializeMessage } from '@modelcontextprotocol/core-internal';\nimport { process } from '@modelcontextprotocol/server/_shims';\n\n/**\n * Server transport for stdio: this communicates with an MCP client by reading from the current process' `stdin` and writing to `stdout`.\n *\n * This transport is only available in Node.js environments.\n *\n * @example\n * ```ts source=\"./stdio.examples.ts#StdioServerTransport_basicUsage\"\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' });\n * const transport = new StdioServerTransport();\n * await server.connect(transport);\n * ```\n */\nexport class StdioServerTransport implements Transport {\n private _readBuffer: ReadBuffer;\n private _started = false;\n private _closed = false;\n\n constructor(\n private _stdin: Readable = process.stdin,\n private _stdout: Writable = process.stdout,\n options?: {\n /**\n * Maximum size of the read buffer in bytes. If a single message exceeds\n * this size the transport will emit an error and close.\n *\n * Defaults to 10 MB.\n */\n maxBufferSize?: number;\n }\n ) {\n this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });\n }\n\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: JSONRPCMessage) => void;\n\n // Arrow functions to bind `this` properly, while maintaining function identity.\n _ondata = (chunk: Buffer) => {\n try {\n this._readBuffer.append(chunk);\n this.processReadBuffer();\n } catch (error) {\n this.onerror?.(error as Error);\n this.close().catch(() => {});\n }\n };\n _onerror = (error: Error) => {\n this.onerror?.(error);\n };\n _onstdouterror = (error: Error) => {\n this.onerror?.(error);\n this.close().catch(() => {\n // Ignore errors during close — we're already in an error path\n });\n };\n\n /**\n * Starts listening for messages on `stdin`.\n */\n async start(): Promise {\n if (this._started) {\n throw new Error(\n 'StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.'\n );\n }\n\n this._started = true;\n this._stdin.on('data', this._ondata);\n this._stdin.on('error', this._onerror);\n this._stdout.on('error', this._onstdouterror);\n }\n\n private processReadBuffer() {\n while (true) {\n try {\n const message = this._readBuffer.readMessage();\n if (message === null) {\n break;\n }\n\n this.onmessage?.(message);\n } catch (error) {\n this.onerror?.(error as Error);\n }\n }\n }\n\n async close(): Promise {\n if (this._closed) {\n return;\n }\n this._closed = true;\n\n // Remove our event listeners first\n this._stdin.off('data', this._ondata);\n this._stdin.off('error', this._onerror);\n this._stdout.off('error', this._onstdouterror);\n\n // Check if we were the only data listener\n const remainingDataListeners = this._stdin.listenerCount('data');\n if (remainingDataListeners === 0) {\n // Only pause stdin if we were the only listener\n // This prevents interfering with other parts of the application that might be using stdin\n this._stdin.pause();\n }\n\n // Clear the buffer and notify closure\n this._readBuffer.clear();\n this.onclose?.();\n }\n\n send(message: JSONRPCMessage): Promise {\n if (this._closed) {\n return Promise.reject(new Error('StdioServerTransport is closed'));\n }\n return new Promise((resolve, reject) => {\n const json = serializeMessage(message);\n\n let settled = false;\n const onError = (error: Error) => {\n if (settled) return;\n settled = true;\n this._stdout.off('error', onError);\n this._stdout.off('drain', onDrain);\n reject(error);\n };\n const onDrain = () => {\n if (settled) return;\n settled = true;\n this._stdout.off('error', onError);\n this._stdout.off('drain', onDrain);\n resolve();\n };\n\n this._stdout.once('error', onError);\n\n if (this._stdout.write(json)) {\n if (settled) return;\n settled = true;\n this._stdout.off('error', onError);\n resolve();\n } else if (!settled) {\n this._stdout.once('drain', onDrain);\n }\n });\n }\n}\n","/**\n * `serveStdio` — the stdio entry point for serving the 2026-07-28 protocol\n * revision on a long-lived connection, with 2025-era serving as the default\n * for clients that open with the `initialize` handshake.\n *\n * The entry owns the stdio transport and the era decision for the connection.\n * It classifies the connection's opening exchange exactly once (using the\n * same body-primary rules as the HTTP entry), constructs ONE server instance\n * from the consumer's factory for the era the client opened with, pins that\n * instance for the lifetime of the connection, and passes every later message\n * straight through to it. No per-message era classification ever runs after\n * the connection is pinned — exactly mirroring how `createMcpHandler`\n * classifies an HTTP request before any instance exists.\n *\n * The opening exchange:\n *\n * - An `initialize` request (or any claim-less message) opens a 2025-era\n * session: the factory builds a legacy instance and the connection is\n * pinned to it (`legacy: 'serve'`, the default). With `legacy: 'reject'`\n * the opening is answered with the unsupported-protocol-version error\n * naming the supported modern revisions instead.\n * - A request carrying a valid per-request `_meta` envelope naming a\n * supported modern revision pins the connection to a modern instance\n * (era-marked and given the modern-only handlers, exactly like the HTTP\n * entry's modern path).\n * - A `server/discover` probe is answered by an optimistically built modern\n * instance but does NOT pin the connection yet: the spec's stdio\n * backward-compatibility flow lets a client probe first and then either\n * continue with modern requests (which pins the connection modern) or fall\n * back to the `initialize` handshake when no mutually supported modern\n * revision exists — in which case the probe instance is discarded and a\n * fresh legacy instance serves the handshake.\n * - Once the modern era is pinned, a later claim-less `initialize` is\n * rejected with the unsupported-protocol-version error naming the supported\n * revisions (the spec recommends naming them in any error returned to\n * `initialize`, and forbids falling back once the modern era is confirmed).\n *\n * Every instance the factory produces serves exactly one era; the ambiguity\n * of the opening exchange lives entirely in this entry. In the probe-fallback\n * case the factory is called twice (once for the discarded probe instance,\n * once for the legacy instance), so factories should be cheap and\n * side-effect-free to construct — the same expectation `createMcpHandler`\n * already sets for per-request construction.\n *\n * Hand-constructed servers connected directly to a `StdioServerTransport`\n * are unaffected by this entry: they keep serving the 2025-era protocol they\n * were written for.\n */\nimport type {\n CancelledNotificationParams,\n JSONRPCMessage,\n JSONRPCNotification,\n JSONRPCRequest,\n MessageClassification,\n MessageExtraInfo,\n RequestId,\n Transport,\n TransportSendOptions\n} from '@modelcontextprotocol/core-internal';\nimport {\n carriesValidModernEnvelopeClaim,\n envelopeClaimVersion,\n hasEnvelopeClaim,\n isJSONRPCErrorResponse,\n isJSONRPCNotification,\n isJSONRPCRequest,\n isJSONRPCResultResponse,\n modernOnlyStrictRejection,\n ProtocolErrorCode,\n requestMetaOf,\n setNegotiatedProtocolVersion,\n SUPPORTED_MODERN_PROTOCOL_VERSIONS,\n UnsupportedProtocolVersionError,\n validateEnvelopeMeta\n} from '@modelcontextprotocol/core-internal';\n\nimport type { McpServerFactory } from './createMcpHandler';\nimport { DEFAULT_MAX_SUBSCRIPTIONS, StdioListenRouter } from './listenRouter';\nimport { McpServer } from './mcp';\nimport type { Server } from './server';\nimport { installModernOnlyHandlers, serverIdentityOf } from './server';\nimport { StdioServerTransport } from './stdio';\n\n/** Options for {@linkcode serveStdio}. */\nexport interface ServeStdioOptions {\n /**\n * How a 2025-era opening (an `initialize` request, or any claim-less\n * message) is handled:\n *\n * - `'serve'` (default) — the connection is pinned to a 2025-era instance\n * from the same factory and served exactly as a hand-wired stdio server\n * serves it today.\n * - `'reject'` — the opening request is answered with the\n * unsupported-protocol-version error naming the supported modern\n * revisions (claim-less notifications are dropped); the connection\n * stays open for a modern opening.\n */\n legacy?: 'serve' | 'reject';\n /**\n * Bring your own transport (for example a `StdioServerTransport`\n * constructed over a Unix domain socket or TCP stream, per the stdio\n * binding's custom-transport guidance). Defaults to a\n * {@linkcode StdioServerTransport} over the current process's stdio. The\n * entry owns the transport: it starts it, receives every inbound message,\n * and closes it when the connection ends.\n */\n transport?: Transport;\n /** Callback for out-of-band errors (reporting only; it never alters what is written to the wire). */\n onerror?: (error: Error) => void;\n /**\n * Reject a new `subscriptions/listen` with `-32603` 'Subscription limit\n * reached' (in-band, before the ack) when this many subscriptions are\n * already open on this connection.\n * @default 1024\n */\n maxSubscriptions?: number;\n}\n\n/** The handle returned by {@linkcode serveStdio}. */\nexport interface StdioServerHandle {\n /** Tears the connection down: closes the pinned instance (if any) and the underlying transport. */\n close(): Promise;\n}\n\n/* ------------------------------------------------------------------------ *\n * Per-instance channel\n * ------------------------------------------------------------------------ */\n\n/**\n * How long the probe-discard path waits for the probe instance to answer the\n * requests it was delivered before closing it. The wait normally settles as\n * soon as the DiscoverResult is handed to the wire (or immediately, when a\n * delivered cancellation already settled the probe); the bound is a backstop\n * so no edge can ever hold the connection's inbound pump indefinitely behind\n * the discard.\n */\nconst DISCARD_ANSWER_TIMEOUT_MS = 3000;\n\n/**\n * The transport a pinned instance is connected to: a thin channel that writes\n * through to the entry-owned wire transport and receives the messages the\n * entry forwards. The wire transport itself is never handed to an instance —\n * that is what lets the entry discard an optimistic probe instance (close the\n * channel) without tearing down the connection.\n */\nclass StdioConnectionChannel implements Transport {\n onclose?: () => void;\n onerror?: (error: Error) => void;\n onmessage?: (message: T, extra?: MessageExtraInfo) => void;\n\n private _closed = false;\n /** Request ids the entry delivered to the instance that the instance has not yet answered. */\n private readonly _pendingRequests = new Set();\n private _drainWaiters: Array<() => void> = [];\n\n constructor(\n private readonly _wire: Transport,\n private readonly _onInstanceClose: () => void,\n /**\n * Optional first-look on outbound messages. When set and returning\n * `'handled'`, the channel does not write the message to the wire\n * (the entry already wrote whatever was appropriate). Used by the\n * modern-era listen router to fan a change notification out onto the\n * active subscriptions instead of broadcasting it unsolicited.\n */\n private readonly _outboundIntercept?: (message: JSONRPCMessage) => 'handled' | undefined\n ) {}\n\n async start(): Promise {\n // The entry already started the wire transport; connecting an\n // instance to its channel must not start anything again.\n }\n\n async send(message: JSONRPCMessage, options?: TransportSendOptions): Promise {\n if (isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message)) {\n // The instance answered a delivered request: settle it whether or\n // not the wire write below succeeds (write failures surface\n // through the wire's own error reporting).\n const { id } = message;\n if (id !== undefined) {\n this._settle(id);\n }\n }\n if (this._closed) {\n // A discarded or torn-down instance has nowhere to write; late\n // sends are dropped.\n return;\n }\n if (this._outboundIntercept?.(message) === 'handled') {\n return;\n }\n return this._wire.send(message, options);\n }\n\n setProtocolVersion = (version: string): void => {\n this._wire.setProtocolVersion?.(version);\n };\n\n /** Forwards one inbound message to the connected instance. */\n deliver(message: JSONRPCMessage, extra?: MessageExtraInfo): void {\n if (this._closed) {\n return;\n }\n if (isJSONRPCRequest(message)) {\n this._pendingRequests.add(message.id);\n } else if (isJSONRPCNotification(message) && message.method === 'notifications/cancelled') {\n // By protocol contract a cancelled request may legitimately go\n // unanswered (the instance aborts the in-flight handler and writes\n // nothing for it), so a delivered cancellation settles the request\n // it names: nothing should keep waiting for an answer that may\n // never come. Non-cancelled requests still settle only when their\n // answer is handed to the wire.\n const cancelledId = (message.params as CancelledNotificationParams | undefined)?.requestId;\n if (cancelledId !== undefined) {\n this._settle(cancelledId);\n }\n }\n this.onmessage?.(message, extra);\n }\n\n /**\n * Resolves once every request delivered to the instance has been answered\n * through {@linkcode send}, settled by a delivered cancellation, or the\n * channel has been closed and nothing further can be answered. The wait is\n * bounded by `timeoutMs` as a backstop so no edge can hold the caller\n * indefinitely; resolves `false` only when the bound elapsed with requests\n * still unanswered. Used by the probe-discard path so a probe request the\n * entry accepted is never silently dropped.\n */\n async whenRequestsAnswered(timeoutMs: number): Promise {\n if (this._closed || this._pendingRequests.size === 0) {\n return true;\n }\n return await new Promise(resolve => {\n const waiter = (): void => {\n clearTimeout(timer);\n resolve(true);\n };\n const timer = setTimeout(() => {\n this._drainWaiters = this._drainWaiters.filter(pending => pending !== waiter);\n resolve(false);\n }, timeoutMs);\n this._drainWaiters.push(waiter);\n });\n }\n\n async close(): Promise {\n if (this._closed) {\n return;\n }\n this._closed = true;\n // Nothing further can be answered through a closed channel; release\n // anyone waiting on in-flight answers.\n this._pendingRequests.clear();\n this._releaseDrainWaiters();\n try {\n this._onInstanceClose();\n } finally {\n this.onclose?.();\n }\n }\n\n private _settle(id: RequestId): void {\n this._pendingRequests.delete(id);\n if (this._pendingRequests.size === 0) {\n this._releaseDrainWaiters();\n }\n }\n\n private _releaseDrainWaiters(): void {\n const waiters = this._drainWaiters;\n this._drainWaiters = [];\n for (const waiter of waiters) {\n waiter();\n }\n }\n}\n\n/* ------------------------------------------------------------------------ *\n * Opening-exchange classification\n * ------------------------------------------------------------------------ */\n\ninterface EnvelopeIssue {\n key: string;\n problem: string;\n}\n\ntype OpeningClassification =\n /** A 2025-era opening: `initialize`, or any message without an envelope claim. */\n | { kind: 'legacy'; reason: 'initialize' | 'no-claim'; requestedVersion?: string }\n /** A valid envelope claim naming a modern revision this entry serves. */\n | { kind: 'modern'; revision: string; classification: MessageClassification }\n /** A present envelope claim whose envelope is malformed. */\n | { kind: 'invalid-envelope'; issue: EnvelopeIssue }\n /** A valid envelope claim naming a revision this entry does not serve (unknown future or 2025-era). */\n | { kind: 'unsupported-revision'; requested: string };\n\n/**\n * Classifies one message of the opening exchange with the same body-primary\n * rules the HTTP entry applies per request: `initialize` is the legacy\n * handshake unless it carries a valid modern envelope claim; a present claim\n * is validated (never silently ignored); a claim-less message is 2025-era\n * traffic. There is no header layer on stdio, so the body is the only signal.\n */\nfunction classifyOpeningMessage(message: JSONRPCRequest | JSONRPCNotification): OpeningClassification {\n const params = message.params;\n\n if (message.method === 'initialize' && !carriesValidModernEnvelopeClaim(params)) {\n const requestedVersion =\n params !== null && typeof params === 'object' && typeof (params as { protocolVersion?: unknown }).protocolVersion === 'string'\n ? ((params as { protocolVersion: string }).protocolVersion as string)\n : undefined;\n return { kind: 'legacy', reason: 'initialize', ...(requestedVersion !== undefined && { requestedVersion }) };\n }\n\n if (!hasEnvelopeClaim(params)) {\n return { kind: 'legacy', reason: 'no-claim' };\n }\n\n // A present claim is validated, never silently ignored — a malformed\n // envelope behind the claim is an invalid-params answer, not a fall back\n // to legacy serving (mirrors the HTTP entry's envelope rung).\n const meta = requestMetaOf(params);\n const issues = meta === undefined ? [] : validateEnvelopeMeta(meta);\n const firstIssue = issues[0];\n if (firstIssue !== undefined) {\n return { kind: 'invalid-envelope', issue: firstIssue };\n }\n\n const claimedVersion = envelopeClaimVersion(params);\n if (claimedVersion === undefined || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) {\n // The claim names a revision this entry does not serve (an unknown\n // future revision, or a 2025-era revision delivered via the envelope\n // mechanism) — answered like the HTTP entry's modern path.\n return { kind: 'unsupported-revision', requested: claimedVersion ?? 'unknown' };\n }\n\n return { kind: 'modern', revision: claimedVersion, classification: { era: 'modern', revision: claimedVersion } };\n}\n\n/* ------------------------------------------------------------------------ *\n * The entry\n * ------------------------------------------------------------------------ */\n\ninterface ConnectedInstance {\n product: McpServer | Server;\n channel: StdioConnectionChannel;\n}\n\ntype EntryState =\n /** Waiting for the connection's opening message. */\n | { phase: 'opening' }\n /** A `server/discover` probe was answered; the era is not pinned yet. */\n | { phase: 'probe'; instance: ConnectedInstance }\n /** The connection is pinned to one instance serving one era. */\n | { phase: 'pinned'; era: 'legacy' | 'modern'; instance: ConnectedInstance }\n | { phase: 'closed' };\n\n/**\n * Serves MCP over stdio from a server factory, owning the era decision for\n * the connection: the opening exchange selects the era, ONE instance from the\n * factory is pinned for the connection lifetime, and everything after passes\n * straight through to it. See the module documentation for the opening rules.\n *\n * ```ts\n * import { serveStdio } from '@modelcontextprotocol/server/stdio';\n *\n * serveStdio(() => {\n * const server = new McpServer({ name: 'my-server', version: '1.0.0' }, { capabilities: { tools: {} } });\n * // register tools/resources/prompts once — the same factory serves both eras\n * return server;\n * });\n * ```\n */\nexport function serveStdio(factory: McpServerFactory, options: ServeStdioOptions = {}): StdioServerHandle {\n const legacyMode = options.legacy ?? 'serve';\n const wire = options.transport ?? new StdioServerTransport();\n\n let state: EntryState = { phase: 'opening' };\n /** Channel currently being discarded (its close must not tear the connection down). */\n let discarding: StdioConnectionChannel | undefined;\n let closing = false;\n\n /**\n * Whether the connection has been torn down (`handle.close()` or the wire\n * closing). The opening arms re-check this after every await: a close can\n * race factory construction, and the continuation must neither resurrect\n * the connection state nor keep a late-resolved instance around.\n */\n const isTornDown = (): boolean => closing || state.phase === 'closed';\n\n const reportError = (error: Error) => {\n try {\n options.onerror?.(error);\n } catch {\n // Reporting must never affect the wire.\n }\n };\n\n const writeErrorResponse = (id: RequestId, code: number, message: string, data?: unknown): Promise =>\n wire\n .send({ jsonrpc: '2.0', id, error: { code, message, ...(data !== undefined && { data }) } })\n .catch(error => reportError(toError(error)));\n\n /**\n * Entry-handled `subscriptions/listen` for this connection: holds the\n * active subscriptions, serves inbound listen / cancelled-of-listen\n * before the pinned instance is consulted, and rewrites the instance's\n * outbound change notifications onto the active subscriptions. Only\n * consulted on a modern-pinned connection — on a legacy connection\n * change notifications pass straight through (the 2025 unsolicited\n * delivery model is unchanged).\n */\n const listenRouter = new StdioListenRouter(options.maxSubscriptions ?? DEFAULT_MAX_SUBSCRIPTIONS);\n\n /** Outbound intercept installed on a modern instance's channel. */\n const modernOutboundIntercept = (message: JSONRPCMessage): 'handled' | undefined => {\n if (!isJSONRPCNotification(message)) return undefined;\n const routed = listenRouter.routeOutbound(message);\n if (routed === 'passthrough') return undefined;\n // A subscription-gated change notification on the modern era: one\n // stamped copy per subscription that opted in (an empty array means\n // it is dropped — the modern era never delivers an un-requested\n // change type unsolicited). Nothing else from the instance is\n // affected.\n for (const stamped of routed) {\n void wire.send({ jsonrpc: '2.0', ...stamped }).catch(error => reportError(toError(error)));\n }\n return 'handled';\n };\n\n /**\n * Entry-handled inbound listen routing for a modern-pinned connection.\n * Returns `true` when the message was served at the entry and must NOT\n * be delivered to the pinned instance.\n */\n const tryServeListen = async (message: JSONRPCMessage): Promise => {\n if (isJSONRPCRequest(message) && message.method === 'subscriptions/listen') {\n // Entry-handled listen is its own request-handling subsystem; it\n // applies the same per-request envelope rung the instance's\n // `_onrequest` would (method-existence is N/A here — the entry\n // recognized the method — so envelope validation is the first\n // applicable rung) and the same supported-revision check the\n // opening classifier and the HTTP entry apply per request. Reuses\n // the same validators the opening classifier uses.\n const meta = requestMetaOf(message.params);\n const issue = hasEnvelopeClaim(message.params)\n ? (meta === undefined ? [] : validateEnvelopeMeta(meta))[0]\n : { key: '_meta', problem: 'the per-request envelope is required on protocol revision 2026-07-28' };\n const claimedVersion = envelopeClaimVersion(message.params);\n let reply;\n if (issue !== undefined) {\n reply = {\n jsonrpc: '2.0' as const,\n id: message.id,\n error: { code: -32_602, message: `Invalid _meta envelope: ${issue.key}: ${issue.problem}` }\n };\n } else if (claimedVersion === undefined || !SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(claimedVersion)) {\n const error = new UnsupportedProtocolVersionError({\n supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],\n requested: claimedVersion ?? 'unknown'\n });\n reply = { jsonrpc: '2.0' as const, id: message.id, error: { code: error.code, message: error.message, data: error.data } };\n } else {\n reply = listenRouter.serve(message);\n }\n await wire\n .send('error' in reply ? reply : { jsonrpc: '2.0', method: reply.method, params: reply.params })\n .catch(error => reportError(toError(error)));\n return true;\n }\n if (isJSONRPCNotification(message) && message.method === 'notifications/cancelled') {\n const cancelledId = (message.params as CancelledNotificationParams | undefined)?.requestId;\n // Inbound cancel of a parked listen: tear the subscription down\n // and DO NOT deliver to the instance (it never saw the listen\n // request). After this point nothing further is delivered for\n // that subscription id (post-cancel hardening).\n if (cancelledId !== undefined && listenRouter.cancel(cancelledId)) {\n return true;\n }\n }\n return false;\n };\n\n /** Answers a 2025-era request the entry will not serve (the modern-only rejection cells). */\n const answerLegacyRejection = (\n request: JSONRPCRequest,\n reason: 'initialize' | 'no-claim',\n requestedVersion?: string\n ): Promise => {\n const rejection = modernOnlyStrictRejection(\n { kind: 'legacy', reason, ...(requestedVersion !== undefined && { requestedVersion }) },\n SUPPORTED_MODERN_PROTOCOL_VERSIONS\n );\n if (rejection === undefined) {\n return Promise.resolve();\n }\n reportError(new Error(`Rejected 2025-era request on a modern-only stdio connection (${rejection.cell}): ${rejection.message}`));\n return writeErrorResponse(request.id, rejection.code, rejection.message, rejection.data);\n };\n\n const onInstanceClosed = (channel: StdioConnectionChannel) => {\n if (closing || channel === discarding) {\n return;\n }\n // The pinned (or probe) instance was closed from the instance side:\n // the connection is over.\n void closeAll();\n };\n\n const connectInstance = async (era: 'legacy' | 'modern', revision?: string): Promise => {\n const product = await factory({ era });\n const server = product instanceof McpServer ? product.server : product;\n if (era === 'modern') {\n // Era-write at instance binding, then modern-only handler\n // installation — the same helpers the HTTP entry's modern path\n // uses, before the instance is connected.\n setNegotiatedProtocolVersion(server, revision);\n installModernOnlyHandlers(server, SUPPORTED_MODERN_PROTOCOL_VERSIONS);\n // The listen router was created before this instance existed; now\n // that capabilities are known, hand them over (with the identity\n // stamped onto graceful-close results) so the acknowledged filter\n // is narrowed against what the server actually advertises.\n listenRouter.setServerCapabilities(server.getCapabilities(), serverIdentityOf(server));\n }\n const channel: StdioConnectionChannel = new StdioConnectionChannel(\n wire,\n () => onInstanceClosed(channel),\n era === 'modern' ? modernOutboundIntercept : undefined\n );\n await product.connect(channel);\n return { product, channel };\n };\n\n /** Closes an instance whose factory resolved only after the connection was torn down. */\n const disposeLateInstance = (instance: ConnectedInstance): Promise =>\n instance.product.close().catch(error => reportError(toError(error)));\n\n const discardProbeInstance = async (instance: ConnectedInstance): Promise => {\n // The probe instance served only the discover exchange; closing its\n // channel must not tear down the connection the fallback is about to\n // continue on.\n discarding = instance.channel;\n try {\n // A probe request the entry accepted must never go silently\n // unanswered: a client may pipeline its fallback `initialize`\n // straight behind `server/discover` without waiting, and closing\n // the instance aborts whatever it still has in flight. Let the\n // in-flight DiscoverResult reach the wire before the instance is\n // closed; the probe instance only ever receives `server/discover`,\n // whose entry-installed handler always answers promptly. A probe\n // the client cancelled is already settled by the delivered\n // cancellation (a cancelled request may go unanswered), and the\n // wait is bounded as a backstop so nothing can wedge the\n // connection's pump behind the discard.\n const answered = await instance.channel.whenRequestsAnswered(DISCARD_ANSWER_TIMEOUT_MS);\n if (!answered) {\n reportError(\n new Error(\n `Discarded the probe instance with requests still unanswered after ${DISCARD_ANSWER_TIMEOUT_MS}ms; continuing with the fallback`\n )\n );\n }\n await instance.product.close();\n } catch (error) {\n reportError(toError(error));\n } finally {\n discarding = undefined;\n }\n };\n\n const processMessage = async (message: JSONRPCMessage): Promise => {\n if (state.phase === 'closed') {\n return;\n }\n\n if (state.phase === 'pinned') {\n if (\n state.era === 'modern' &&\n isJSONRPCRequest(message) &&\n message.method === 'initialize' &&\n !carriesValidModernEnvelopeClaim(message.params)\n ) {\n // The modern era is confirmed for this connection; a late\n // legacy handshake is answered with the version error naming\n // the supported revisions (the specification recommends\n // naming them in any error returned to `initialize`, and\n // rules out falling back once the modern era is confirmed).\n const requestedVersion =\n message.params !== null &&\n typeof message.params === 'object' &&\n typeof (message.params as { protocolVersion?: unknown }).protocolVersion === 'string'\n ? ((message.params as { protocolVersion: string }).protocolVersion as string)\n : undefined;\n await answerLegacyRejection(message, 'initialize', requestedVersion);\n return;\n }\n if (state.era === 'modern' && (await tryServeListen(message))) {\n return;\n }\n state.instance.channel.deliver(message);\n return;\n }\n\n // Negotiation window ('opening' | 'probe').\n if (!isJSONRPCRequest(message) && !isJSONRPCNotification(message)) {\n // A JSON-RPC response before any era is pinned: nothing has been\n // asked of the client yet, so there is nothing it can answer.\n reportError(new Error('Discarded a JSON-RPC response received before the connection negotiated an era'));\n return;\n }\n\n const opening = classifyOpeningMessage(message);\n switch (opening.kind) {\n case 'invalid-envelope': {\n const detail = `Invalid _meta envelope for protocol revision 2026-07-28: ${opening.issue.key}: ${opening.issue.problem}`;\n if (isJSONRPCRequest(message)) {\n await writeErrorResponse(message.id, ProtocolErrorCode.InvalidParams, detail, { envelope: opening.issue });\n } else {\n reportError(new Error(`Discarded a notification with a malformed envelope: ${detail}`));\n }\n return;\n }\n case 'unsupported-revision': {\n if (isJSONRPCRequest(message)) {\n const error = new UnsupportedProtocolVersionError({\n supported: [...SUPPORTED_MODERN_PROTOCOL_VERSIONS],\n requested: opening.requested\n });\n reportError(error);\n await writeErrorResponse(message.id, error.code, error.message, error.data);\n } else {\n reportError(new Error(`Discarded a notification claiming unsupported protocol revision ${opening.requested}`));\n }\n return;\n }\n case 'modern': {\n if (isJSONRPCRequest(message) && message.method === 'server/discover') {\n if (state.phase === 'probe') {\n // A repeated probe is answered by the same optimistic\n // instance and the negotiation window stays open: only\n // a non-discover enveloped request commits the\n // connection to the modern era, so a later fallback\n // `initialize` is still served by a fresh legacy\n // instance.\n state.instance.channel.deliver(message, { classification: opening.classification });\n return;\n }\n // Probe: answer from an optimistically built modern\n // instance so the advertisement reflects the real server\n // definition, but do not pin the connection yet — the\n // client may still fall back to `initialize` when it\n // shares no modern revision with the advertisement.\n const instance = await connectInstance('modern', opening.revision);\n if (isTornDown()) {\n // The connection was torn down while the factory was\n // building the probe instance: dispose of it and stay\n // closed instead of resurrecting the negotiation\n // window; nothing is delivered or answered.\n await disposeLateInstance(instance);\n return;\n }\n state = { phase: 'probe', instance };\n instance.channel.deliver(message, { classification: opening.classification });\n return;\n }\n if (state.phase === 'probe') {\n if (isJSONRPCNotification(message)) {\n // An enveloped notification during the negotiation\n // window (for example a notifications/cancelled for\n // the probe itself) is delivered to the probe instance\n // without committing the era: only a non-discover\n // enveloped request pins the connection, so a later\n // fallback `initialize` is still served by a fresh\n // legacy instance.\n state.instance.channel.deliver(message, { classification: opening.classification });\n return;\n }\n // The probe was followed by a modern request: the client\n // committed to the modern era — pin the probe instance.\n state = { phase: 'pinned', era: 'modern', instance: state.instance };\n } else {\n const instance = await connectInstance('modern', opening.revision);\n if (isTornDown()) {\n // Closed while the factory was building the modern\n // instance: dispose of it and stay closed.\n await disposeLateInstance(instance);\n return;\n }\n state = { phase: 'pinned', era: 'modern', instance };\n }\n if (await tryServeListen(message)) {\n return;\n }\n state.instance.channel.deliver(message, { classification: opening.classification });\n return;\n }\n case 'legacy': {\n if (legacyMode === 'reject') {\n if (isJSONRPCRequest(message)) {\n await answerLegacyRejection(message, opening.reason, opening.requestedVersion);\n }\n // Claim-less notifications are accepted and dropped (the\n // stdio analog of the HTTP entry's 202-and-drop); the\n // connection stays open for a modern opening.\n return;\n }\n if (state.phase === 'probe') {\n // Probe-then-fallback: the client probed, found no\n // mutually supported modern revision, and fell back to\n // the 2025 handshake on the same connection. The probe\n // instance is discarded; a fresh legacy instance serves\n // the handshake.\n await discardProbeInstance(state.instance);\n if (isTornDown()) {\n // Closed while the probe was being discarded: stay closed.\n return;\n }\n state = { phase: 'opening' };\n }\n const instance = await connectInstance('legacy');\n if (isTornDown()) {\n // Closed while the factory was building the legacy\n // instance: dispose of it and stay closed.\n await disposeLateInstance(instance);\n return;\n }\n state = { phase: 'pinned', era: 'legacy', instance };\n state.instance.channel.deliver(message);\n return;\n }\n }\n };\n\n // Inbound messages are processed strictly in arrival order: the queue\n // absorbs anything that arrives while the opening exchange is still being\n // decided (factory construction and instance connection are async).\n const queue: JSONRPCMessage[] = [];\n let pumping = false;\n const pump = async (): Promise => {\n if (pumping) {\n return;\n }\n pumping = true;\n try {\n while (queue.length > 0) {\n const message = queue.shift()!;\n try {\n await processMessage(message);\n } catch (error) {\n // Every arm of processMessage that answers a request does\n // so through writeErrorResponse (which never throws — wire\n // failures are routed to onerror) and returns right after,\n // so an error escaping to here means the request was never\n // answered. Answer it now: a throwing factory or a failed\n // connect during the opening exchange must not leave the\n // client's request hanging (the stdio analog of the HTTP\n // entry's internal-server-error response). Notifications\n // carry no id to answer and are only reported.\n if (isJSONRPCRequest(message)) {\n await writeErrorResponse(message.id, ProtocolErrorCode.InternalError, 'Internal server error');\n }\n reportError(toError(error));\n }\n }\n } finally {\n pumping = false;\n }\n };\n\n const closeAll = async (): Promise => {\n if (closing || state.phase === 'closed') {\n return;\n }\n closing = true;\n const current = state;\n state = { phase: 'closed' };\n // Stdio server-side graceful teardown: emit the empty\n // `subscriptions/listen` JSON-RPC result for every active subscription\n // (the spec's graceful-close signal — `SubscriptionsListenResult`)\n // before the wire is closed, so the client distinguishes graceful end\n // from a transport drop.\n for (const result of listenRouter.teardownAll()) {\n await wire.send(result).catch(error => reportError(toError(error)));\n }\n if (current.phase === 'probe' || current.phase === 'pinned') {\n await current.instance.product.close().catch(error => reportError(toError(error)));\n }\n await wire.close().catch(error => reportError(toError(error)));\n };\n\n wire.onmessage = (message: JSONRPCMessage) => {\n queue.push(message);\n void pump();\n };\n wire.onerror = error => {\n reportError(error);\n if (state.phase === 'probe' || state.phase === 'pinned') {\n state.instance.channel.onerror?.(error);\n }\n };\n wire.onclose = () => {\n if (closing || state.phase === 'closed') {\n return;\n }\n closing = true;\n const current = state;\n state = { phase: 'closed' };\n if (current.phase === 'probe' || current.phase === 'pinned') {\n void current.instance.product.close().catch(error => reportError(toError(error)));\n }\n };\n\n const started = wire.start().catch(error => {\n reportError(toError(error));\n throw error;\n });\n // Surface a failed start through onerror (above); close() still resolves.\n started.catch(() => {});\n\n return {\n close: async () => {\n await started.catch(() => {});\n await closeAll();\n }\n };\n}\n\nfunction toError(value: unknown): Error {\n return value instanceof Error ? value : new Error(String(value));\n}\n"],"mappings":"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"}