/ services / mcp / InProcessTransport.ts
InProcessTransport.ts
 1  import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'
 2  import type { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js'
 3  
 4  /**
 5   * In-process linked transport pair for running an MCP server and client
 6   * in the same process without spawning a subprocess.
 7   *
 8   * `send()` on one side delivers to `onmessage` on the other.
 9   * `close()` on either side calls `onclose` on both.
10   */
11  class InProcessTransport implements Transport {
12    private peer: InProcessTransport | undefined
13    private closed = false
14  
15    onclose?: () => void
16    onerror?: (error: Error) => void
17    onmessage?: (message: JSONRPCMessage) => void
18  
19    /** @internal */
20    _setPeer(peer: InProcessTransport): void {
21      this.peer = peer
22    }
23  
24    async start(): Promise<void> {}
25  
26    async send(message: JSONRPCMessage): Promise<void> {
27      if (this.closed) {
28        throw new Error('Transport is closed')
29      }
30      // Deliver to the other side asynchronously to avoid stack depth issues
31      // with synchronous request/response cycles
32      queueMicrotask(() => {
33        this.peer?.onmessage?.(message)
34      })
35    }
36  
37    async close(): Promise<void> {
38      if (this.closed) {
39        return
40      }
41      this.closed = true
42      this.onclose?.()
43      // Close the peer if it hasn't already closed
44      if (this.peer && !this.peer.closed) {
45        this.peer.closed = true
46        this.peer.onclose?.()
47      }
48    }
49  }
50  
51  /**
52   * Creates a pair of linked transports for in-process MCP communication.
53   * Messages sent on one transport are delivered to the other's `onmessage`.
54   *
55   * @returns [clientTransport, serverTransport]
56   */
57  export function createLinkedTransportPair(): [Transport, Transport] {
58    const a = new InProcessTransport()
59    const b = new InProcessTransport()
60    a._setPeer(b)
61    b._setPeer(a)
62    return [a, b]
63  }