Single-process stdio MCP session — the pre-issue-#411 code path.
(reason: string)
| 291 | |
| 292 | /** Single-process stdio MCP session — the pre-issue-#411 code path. */ |
| 293 | private async startDirect(reason: string): Promise<void> { |
| 294 | if (reason && process.env.CODEGRAPH_MCP_DEBUG) { |
| 295 | process.stderr.write(`[CodeGraph MCP] Direct mode: ${reason}.\n`); |
| 296 | } |
| 297 | this.engine = new MCPEngine(); |
| 298 | const transport = new StdioTransport(); |
| 299 | this.session = new MCPSession(transport, this.engine, { |
| 300 | explicitProjectPath: this.projectPath, |
| 301 | }); |
| 302 | |
| 303 | if (this.projectPath) { |
| 304 | // Background init so the initialize response stays fast (#172). |
| 305 | void this.engine.ensureInitialized(this.projectPath); |
| 306 | } |
| 307 | |
| 308 | this.session.start(); |
| 309 | |
| 310 | // Detect parent-process death — same logic as pre-refactor. When stdin |
| 311 | // closes we go through StdioTransport's `process.exit(0)` already, but |
| 312 | // SIGKILL of the parent doesn't reliably close stdin on Linux (#277). |
| 313 | // Also treat a stdin `'error'` (a socket-backed stdin can fail with |
| 314 | // ECONNRESET/hangup instead of a clean close) as shutdown, and destroy the |
| 315 | // stream so a hung fd can't busy-spin the event loop (#799). |
| 316 | treatStdinFailureAsShutdown(() => this.stop()); |
| 317 | |
| 318 | this.mode = 'direct'; |
| 319 | this.installSignalHandlers(); |
| 320 | this.installPpidWatchdog(); |
| 321 | this.livenessWatchdog = installMainThreadWatchdog(); |
| 322 | } |
| 323 | |
| 324 | /** |
| 325 | * Run as the detached shared daemon (process spawned with |
no test coverage detected