From e3e104c064097e9fb8dd8ca9010a36b6e0156e9a Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Sun, 8 Mar 2026 20:57:13 -0600 Subject: [PATCH 1/2] fix: defer heavy imports in MCP server to improve first-connection reliability The MCP server was importing queries.js and better-sqlite3 before connecting the stdio transport, causing the client's `initialize` request to arrive before the server was listening on stdin. Now the transport connects immediately after the MCP SDK loads, and heavy modules are lazy-loaded on the first tool call (cached thereafter). Impact: 3 functions changed, 2 affected --- src/mcp.js | 56 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/src/mcp.js b/src/mcp.js index f688aa03..afcbc053 100644 --- a/src/mcp.js +++ b/src/mcp.js @@ -836,26 +836,27 @@ export async function startMCPServer(customDbPath, options = {}) { process.exit(1); } - // Lazy import query functions to avoid circular deps at module load - const { - impactAnalysisData, - moduleMapData, - fileDepsData, - exportsData, - fnDepsData, - fnImpactData, - pathData, - contextData, - childrenData, - explainData, - whereData, - diffImpactData, - listFunctionsData, - rolesData, - } = await import('./queries.js'); + // Connect transport FIRST so the server can receive the client's + // `initialize` request while heavy modules (queries, better-sqlite3) + // are still loading. These are lazy-loaded on the first tool call + // and cached for subsequent calls. + let _queries; + let _Database; - const require = createRequire(import.meta.url); - const Database = require('better-sqlite3'); + async function getQueries() { + if (!_queries) { + _queries = await import('./queries.js'); + } + return _queries; + } + + function getDatabase() { + if (!_Database) { + const require = createRequire(import.meta.url); + _Database = require('better-sqlite3'); + } + return _Database; + } const server = new Server( { name: 'codegraph', version: '1.0.0' }, @@ -868,6 +869,23 @@ export async function startMCPServer(customDbPath, options = {}) { server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; + const { + impactAnalysisData, + moduleMapData, + fileDepsData, + exportsData, + fnDepsData, + fnImpactData, + pathData, + contextData, + childrenData, + explainData, + whereData, + diffImpactData, + listFunctionsData, + rolesData, + } = await getQueries(); + const Database = getDatabase(); try { if (!multiRepo && args.repo) { From 92503412cbb5373c637418fe55e2bb99c6bdb0f9 Mon Sep 17 00:00:00 2001 From: carlos-alm <127798846+carlos-alm@users.noreply.github.com> Date: Sun, 8 Mar 2026 21:34:02 -0600 Subject: [PATCH 2/2] fix: move lazy-load calls inside try-catch for proper MCP error handling Impact: 1 functions changed, 0 affected --- src/mcp.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/mcp.js b/src/mcp.js index afcbc053..b72c2a83 100644 --- a/src/mcp.js +++ b/src/mcp.js @@ -869,25 +869,24 @@ export async function startMCPServer(customDbPath, options = {}) { server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; - const { - impactAnalysisData, - moduleMapData, - fileDepsData, - exportsData, - fnDepsData, - fnImpactData, - pathData, - contextData, - childrenData, - explainData, - whereData, - diffImpactData, - listFunctionsData, - rolesData, - } = await getQueries(); - const Database = getDatabase(); - try { + const { + impactAnalysisData, + moduleMapData, + fileDepsData, + exportsData, + fnDepsData, + fnImpactData, + pathData, + contextData, + childrenData, + explainData, + whereData, + diffImpactData, + listFunctionsData, + rolesData, + } = await getQueries(); + const Database = getDatabase(); if (!multiRepo && args.repo) { throw new Error( 'Multi-repo access is disabled. Restart with `codegraph mcp --multi-repo` to access other repositories.',