(line: string)
| 253 | }; |
| 254 | // Daemon-unavailable fallback: serve a client message in-process. |
| 255 | const handleLocally = async (line: string): Promise<void> => { |
| 256 | let msg: JsonRpc; try { msg = JSON.parse(line) as JsonRpc; } catch { return; } |
| 257 | const id = msg.id; |
| 258 | if (msg.method === 'tools/call' && id !== undefined) { |
| 259 | try { |
| 260 | await ensureEngine(); |
| 261 | const params = (msg.params || {}) as { name: string; arguments?: Record<string, unknown> }; |
| 262 | const result = await engine!.getToolHandler().execute(params.name, params.arguments || {}); |
| 263 | writeClient({ jsonrpc: '2.0', id, result }); |
| 264 | getTelemetry().recordUsage('mcp_tool', params.name, !result.isError, telemetryClient); |
| 265 | } catch (err) { |
| 266 | writeClient({ jsonrpc: '2.0', id, error: { code: -32603, message: err instanceof Error ? err.message : String(err) } }); |
| 267 | } |
| 268 | } else if (msg.method === 'ping' && id !== undefined) { |
| 269 | writeClient({ jsonrpc: '2.0', id, result: {} }); |
| 270 | } else if (id !== undefined && msg.method !== 'initialize') { |
| 271 | // A request we can't serve in-process (and the daemon is gone) — answer |
| 272 | // with an error rather than let the host hang on a reply that won't come. |
| 273 | writeClient({ jsonrpc: '2.0', id, error: { code: -32603, message: 'CodeGraph daemon unavailable' } }); |
| 274 | } |
| 275 | // initialize already answered locally; notifications (initialized) need no reply. |
| 276 | }; |
| 277 | const routeToDaemon = (line: string): void => { |
| 278 | if (daemonStatus === 'ready' && daemonSocket) { |
| 279 | trackInflight(line); |
no test coverage detected