{"version":3,"file":"stdio.mjs","names":["_stdin: Readable","_stdout: Writable"],"sources":["../src/server/stdio.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<void> {\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<void> {\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<void> {\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"],"mappings":";;;;;;;;;;;;;;;;AAkBA,IAAa,uBAAb,MAAuD;CACnD,AAAQ;CACR,AAAQ,WAAW;CACnB,AAAQ,UAAU;CAElB,YACI,AAAQA,SAAmB,QAAQ,OACnC,AAAQC,UAAoB,QAAQ,QACpC,SASF;EAXU;EACA;AAWR,OAAK,cAAc,IAAI,WAAW,EAAE,eAAe,SAAS,eAAe,CAAC;;CAGhF;CACA;CACA;CAGA,WAAW,UAAkB;AACzB,MAAI;AACA,QAAK,YAAY,OAAO,MAAM;AAC9B,QAAK,mBAAmB;WACnB,OAAO;AACZ,QAAK,UAAU,MAAe;AAC9B,QAAK,OAAO,CAAC,YAAY,GAAG;;;CAGpC,YAAY,UAAiB;AACzB,OAAK,UAAU,MAAM;;CAEzB,kBAAkB,UAAiB;AAC/B,OAAK,UAAU,MAAM;AACrB,OAAK,OAAO,CAAC,YAAY,GAEvB;;;;;CAMN,MAAM,QAAuB;AACzB,MAAI,KAAK,SACL,OAAM,IAAI,MACN,gHACH;AAGL,OAAK,WAAW;AAChB,OAAK,OAAO,GAAG,QAAQ,KAAK,QAAQ;AACpC,OAAK,OAAO,GAAG,SAAS,KAAK,SAAS;AACtC,OAAK,QAAQ,GAAG,SAAS,KAAK,eAAe;;CAGjD,AAAQ,oBAAoB;AACxB,SAAO,KACH,KAAI;GACA,MAAM,UAAU,KAAK,YAAY,aAAa;AAC9C,OAAI,YAAY,KACZ;AAGJ,QAAK,YAAY,QAAQ;WACpB,OAAO;AACZ,QAAK,UAAU,MAAe;;;CAK1C,MAAM,QAAuB;AACzB,MAAI,KAAK,QACL;AAEJ,OAAK,UAAU;AAGf,OAAK,OAAO,IAAI,QAAQ,KAAK,QAAQ;AACrC,OAAK,OAAO,IAAI,SAAS,KAAK,SAAS;AACvC,OAAK,QAAQ,IAAI,SAAS,KAAK,eAAe;AAI9C,MAD+B,KAAK,OAAO,cAAc,OAAO,KACjC,EAG3B,MAAK,OAAO,OAAO;AAIvB,OAAK,YAAY,OAAO;AACxB,OAAK,WAAW;;CAGpB,KAAK,SAAwC;AACzC,MAAI,KAAK,QACL,QAAO,QAAQ,uBAAO,IAAI,MAAM,iCAAiC,CAAC;AAEtE,SAAO,IAAI,SAAS,SAAS,WAAW;GACpC,MAAM,OAAO,iBAAiB,QAAQ;GAEtC,IAAI,UAAU;GACd,MAAM,WAAW,UAAiB;AAC9B,QAAI,QAAS;AACb,cAAU;AACV,SAAK,QAAQ,IAAI,SAAS,QAAQ;AAClC,SAAK,QAAQ,IAAI,SAAS,QAAQ;AAClC,WAAO,MAAM;;GAEjB,MAAM,gBAAgB;AAClB,QAAI,QAAS;AACb,cAAU;AACV,SAAK,QAAQ,IAAI,SAAS,QAAQ;AAClC,SAAK,QAAQ,IAAI,SAAS,QAAQ;AAClC,aAAS;;AAGb,QAAK,QAAQ,KAAK,SAAS,QAAQ;AAEnC,OAAI,KAAK,QAAQ,MAAM,KAAK,EAAE;AAC1B,QAAI,QAAS;AACb,cAAU;AACV,SAAK,QAAQ,IAAI,SAAS,QAAQ;AAClC,aAAS;cACF,CAAC,QACR,MAAK,QAAQ,KAAK,SAAS,QAAQ;IAEzC"}