import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js' import type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js' /** * In-process linked transport pair for running an MCP server and client * in the same process without spawning a subprocess. * * `send()` on one side delivers to `onmessage` on the other. * `close()` on either side calls `onclose` on both. */ class InProcessTransport implements Transport { private peer: InProcessTransport | undefined private closed = false onclose?: () => void onerror?: (error: Error) => void onmessage?: (message: JSONRPCMessage) => void /** @internal */ _setPeer(peer: InProcessTransport): void { this.peer = peer } async start(): Promise {} async send(message: JSONRPCMessage): Promise { if (this.closed) { throw new Error('Transport is closed') } // Deliver to the other side asynchronously to avoid stack depth issues // with synchronous request/response cycles queueMicrotask(() => { this.peer?.onmessage?.(message) }) } async close(): Promise { if (this.closed) { return } this.closed = true this.onclose?.() // Close the peer if it hasn't already closed if (this.peer && !this.peer.closed) { this.peer.closed = true this.peer.onclose?.() } } } /** * Creates a pair of linked transports for in-process MCP communication. * Messages sent on one transport are delivered to the other's `onmessage`. * * @returns [clientTransport, serverTransport] */ export function createLinkedTransportPair(): [Transport, Transport] { const a = new InProcessTransport() const b = new InProcessTransport() a._setPeer(b) b._setPeer(a) return [a, b] }