MCPcopy Create free account
hub / github.com/colbymchenry/codegraph / runLocalHandshakeProxy

Function runLocalHandshakeProxy

src/mcp/proxy.ts:216–412  ·  view source on GitHub ↗
(deps: LocalHandshakeDeps)

Source from the content-addressed store, hash-verified

214 * never costs the old fall-back-to-direct robustness.
215 */
216export async function runLocalHandshakeProxy(deps: LocalHandshakeDeps): Promise<void> {
217 let daemonStatus: 'connecting' | 'ready' | 'failed' = 'connecting';
218 let daemonSocket: net.Socket | null = null;
219 let clientInitId: unknown = undefined; // suppress the daemon's reply to the forwarded initialize
220 // Telemetry attribution for the in-process fallback only — calls routed to
221 // the daemon are counted by the daemon's own session (which receives the
222 // forwarded initialize, clientInfo included), never double-counted here.
223 let telemetryClient: ClientInfo | undefined;
224 const pending: string[] = []; // client lines buffered until the daemon resolves
225 let engine: MCPEngine | null = null;
226 let engineReady: Promise<void> | null = null;
227 let shuttingDown = false;
228 // Requests forwarded to the daemon and not yet answered, keyed by JSON-RPC id.
229 // If the daemon dies mid-session (#662 — e.g. an MCP host SIGTERM's it when a
230 // new session starts), these would otherwise hang forever; we re-serve them
231 // in-process so the host always gets a reply.
232 const inflight = new Map<unknown, string>();
233 const trackInflight = (line: string): void => {
234 try {
235 const m = JSON.parse(line) as JsonRpc;
236 if (m && m.id !== undefined && typeof m.method === 'string' && m.method !== 'initialize') {
237 inflight.set(m.id, line);
238 }
239 } catch { /* unparseable — nothing we could re-serve anyway */ }
240 };
241
242 const writeClient = (obj: JsonRpc | string): void => {
243 try { process.stdout.write((typeof obj === 'string' ? obj : JSON.stringify(obj)) + '\n'); } catch { /* host gone */ }
244 };
245 const shutdown = (): void => {
246 if (shuttingDown) return; shuttingDown = true;
247 try { daemonSocket?.destroy(); } catch { /* ignore */ }
248 try { engine?.stop(); } catch { /* ignore */ }
249 process.exit(0);
250 };
251 const ensureEngine = (): Promise<void> => {
252 if (!engine) engine = deps.makeEngine();
253 if (!engineReady) engineReady = engine.ensureInitialized(deps.root).catch(() => { /* degraded */ });
254 return engineReady;
255 };
256 // Daemon-unavailable fallback: serve a client message in-process.
257 const handleLocally = async (line: string): Promise<void> => {
258 let msg: JsonRpc; try { msg = JSON.parse(line) as JsonRpc; } catch { return; }
259 const id = msg.id;
260 if (msg.method === 'tools/call' && id !== undefined) {
261 try {
262 await ensureEngine();
263 const params = (msg.params || {}) as { name: string; arguments?: Record<string, unknown> };
264 const result = await engine!.getToolHandler().execute(params.name, params.arguments || {});
265 writeClient({ jsonrpc: '2.0', id, result });
266 getTelemetry().recordUsage('mcp_tool', params.name, !result.isError, telemetryClient);
267 } catch (err) {
268 writeClient({ jsonrpc: '2.0', id, error: { code: -32603, message: err instanceof Error ? err.message : String(err) } });
269 }
270 } else if (msg.method === 'ping' && id !== undefined) {
271 writeClient({ jsonrpc: '2.0', id, result: {} });
272 } else if (id !== undefined && msg.method !== 'initialize') {
273 // A request we can't serve in-process (and the daemon is gone) — answer

Callers 1

Calls 13

initializeInstructionsFunction · 0.90
getStaticToolsFunction · 0.90
routeToDaemonFunction · 0.85
writeClientFunction · 0.85
shutdownFunction · 0.85
trackInflightFunction · 0.85
handleLocallyFunction · 0.85
onMethod · 0.65
getDaemonSocketMethod · 0.65

Tested by

no test coverage detected