MCPcopy
hub / github.com/colbymchenry/codegraph / SocketTransport

Class SocketTransport

src/mcp/transport.ts:336–419  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

334 * ending must not bring down the whole daemon.
335 */
336export class SocketTransport extends LineBasedJsonRpcTransport {
337 private buffer = '';
338 private closeHandlers: Array<() => void> = [];
339
340 constructor(private socket: Socket, private prefix: string = 'cg-sock') {
341 super();
342 }
343
344 /**
345 * Register a callback fired exactly once when the socket closes (from either
346 * side). Used by the daemon to decrement its connected-clients refcount.
347 */
348 onClose(handler: () => void): void {
349 this.closeHandlers.push(handler);
350 }
351
352 start(handler: MessageHandler): void {
353 this.messageHandler = handler;
354
355 this.socket.setEncoding('utf8');
356 this.socket.on('data', (chunk: string) => {
357 this.buffer += chunk;
358 let idx;
359 // Drain every complete line; tail-fragment stays in the buffer for the
360 // next chunk. The handler is async but we don't await it here — JSON-RPC
361 // permits out-of-order responses, and serializing here would deadlock if
362 // a handler issued a server-initiated request that needed a *later* line
363 // to arrive (e.g. roots/list mid-tools-call).
364 while ((idx = this.buffer.indexOf('\n')) !== -1) {
365 const line = this.buffer.slice(0, idx);
366 this.buffer = this.buffer.slice(idx + 1);
367 void this.handleLine(line);
368 }
369 });
370
371 this.socket.on('close', () => this.handleSocketClose());
372 this.socket.on('error', (err) => {
373 // Don't crash the daemon over a broken pipe; just shut this connection.
374 process.stderr.write(`[CodeGraph daemon] socket error: ${err.message}\n`);
375 this.handleSocketClose();
376 });
377 }
378
379 stop(): void {
380 if (this.stopped) return;
381 this.stopped = true;
382 this.rejectPending('Transport stopped');
383 if (!this.socket.destroyed) {
384 this.socket.end();
385 this.socket.destroy();
386 }
387 }
388
389 /**
390 * Write a one-shot line directly to the socket (no JSON-RPC framing applied
391 * by this class — caller produces the line). The daemon uses this for the
392 * hello/handshake line that precedes the JSON-RPC stream.
393 */

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected