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

Method start

src/mcp/index.ts:217–258  ·  view source on GitHub ↗

* Start the MCP server. * * Decision order: * 1. `CODEGRAPH_NO_DAEMON=1` → direct mode (unchanged pre-#411 behavior). * 2. `CODEGRAPH_DAEMON_INTERNAL=1` → we ARE the detached daemon; listen. * 3. No `.codegraph/` reachable → direct mode (the daemon's lockfile and * socke

()

Source from the content-addressed store, hash-verified

215 * mode — a misbehaving daemon must never block a session from starting.
216 */
217 async start(): Promise<void> {
218 // Long-lived process (direct / proxy / daemon alike): flush buffered
219 // telemetry opportunistically. Fire-and-forget + unref'd — adds nothing
220 // to the handshake path and never keeps the process alive.
221 getTelemetry().startInterval();
222
223 // The detached daemon process itself. Checked before the opt-out so the
224 // daemon honors the same env it was spawned with (it never sets NO_DAEMON).
225 if (daemonInternalSet()) {
226 return this.startDaemonProcess();
227 }
228
229 // Direct mode if the user opted out. Setting the env var is sufficient to
230 // get the pre-#411 single-process behavior.
231 if (daemonOptOutSet()) {
232 return this.startDirect('CODEGRAPH_NO_DAEMON set');
233 }
234
235 const root = resolveDaemonRoot(this.projectPath);
236 if (!root) {
237 // No initialized project found — daemon mode has nowhere to put its
238 // socket. The fresh-checkout / outside-project case; behave as before.
239 return this.startDirect('no .codegraph/ root found');
240 }
241
242 try {
243 // Answer the MCP handshake LOCALLY (instant tool registration — no waiting
244 // ~600ms for the daemon to spawn+bind, which produced the cold-start race)
245 // and forward tool CALLS to the shared daemon, connected in the background.
246 // Runs until the host disconnects; the proxy installs its own watchdog and
247 // falls back to an in-process engine if the daemon never comes up.
248 this.mode = 'proxy';
249 await this.runProxyWithLocalHandshake(root);
250 return;
251 } catch (err) {
252 // Belt-and-braces: a throw during proxy SETUP (before the client was served)
253 // is still safe to recover from with a direct-mode session.
254 const msg = err instanceof Error ? err.message : String(err);
255 process.stderr.write(`[CodeGraph MCP] Proxy path failed (${msg}); falling back to direct mode.\n`);
256 return this.startDirect('proxy path threw');
257 }
258 }
259
260 /**
261 * Stop the server. In daemon mode this triggers graceful shutdown of every

Callers 1

mainFunction · 0.95

Calls 9

startDaemonProcessMethod · 0.95
startDirectMethod · 0.95
getTelemetryFunction · 0.90
daemonInternalSetFunction · 0.85
daemonOptOutSetFunction · 0.85
resolveDaemonRootFunction · 0.85
startIntervalMethod · 0.80
writeMethod · 0.45

Tested by

no test coverage detected