Summary
When no .codegraph/ is reachable, the CLI and the MCP server disagree about how loudly to fail.
From the same directory:
$ codegraph sync
[ERR] CodeGraph not initialized in <cwd>
$ codegraph status
[i] Project: <cwd>
[!] Not initialized
[i] Run "codegraph init" to initialize
codegraph serve --mcp in that same directory starts normally, completes the MCP handshake, and advertises its full tool set, while holding no database, no default project, and no file watcher. It emits nothing to say so. From the host's side the server looks healthy; from the user's side the tools simply do not work, with no message anywhere pointing at the cause.
Why this is worth a message
The silent state is not rare. It is reached whenever the host's cwd is one directory above the indexed project: a workspace container, a repo opened from its parent, an agent started from the wrong folder. In that shape the indexes exist, the CLI works when run from the right directory, and only the long-lived server is quietly inert, which reads as "CodeGraph is broken" rather than "CodeGraph is looking in the wrong place".
Diagnosing it currently means knowing to look at ~/.codegraph/daemons/ for a missing entry, or noticing that no daemon.log was ever created. Neither is discoverable.
Where
MCPEngine.doInitialize() (src/mcp/engine.ts:201) already has the exact branch:
const resolvedRoot = findNearestCodeGraphRoot(searchFrom);
if (!resolvedRoot) {
// No .codegraph/ above searchFrom. Sessions may still discover one later via roots/list
this.projectPath = searchFrom;
return;
}
The failure path below it already writes to stderr on an open error:
process.stderr.write(`[CodeGraph MCP] Failed to open project at ${resolvedRoot}: ${msg}\n`);
so the channel and the precedent both exist. The no-root case is the one branch that returns quietly.
Suggested change
-
One stderr line in that branch, naming what was searched and, when a bounded scan finds them, which sub-directories are indexed:
[CodeGraph MCP] No .codegraph/ at or above <searchFrom>: no default project, live sync disabled.
[CodeGraph MCP] Indexed sub-projects found: service-a, service-b. Pass `projectPath` per call, or launch with --path.
The second line only when something was actually found, so the common "not a CodeGraph project" case stays a single line.
-
Make the same fact reachable through the protocol rather than only the host's stderr log: a tool call that needs the default project should fail with a message that says the project was never resolved and how to fix it, instead of behaving as if the project were merely empty. Users see tool output; almost nobody reads the MCP host's stderr capture.
Both are additive and independent of whether the down-scan is ever wired into the server's root resolution (companion issue). If it is, this message becomes the fallback for the several-candidates case. If it is not, it is the only thing standing between the user and a silent no-op.
Environment
CodeGraph 1.5.0, Windows 11, native filesystem (no WSL). Line numbers are against main at the time of writing.
Summary
When no
.codegraph/is reachable, the CLI and the MCP server disagree about how loudly to fail.From the same directory:
codegraph serve --mcpin that same directory starts normally, completes the MCP handshake, and advertises its full tool set, while holding no database, no default project, and no file watcher. It emits nothing to say so. From the host's side the server looks healthy; from the user's side the tools simply do not work, with no message anywhere pointing at the cause.Why this is worth a message
The silent state is not rare. It is reached whenever the host's cwd is one directory above the indexed project: a workspace container, a repo opened from its parent, an agent started from the wrong folder. In that shape the indexes exist, the CLI works when run from the right directory, and only the long-lived server is quietly inert, which reads as "CodeGraph is broken" rather than "CodeGraph is looking in the wrong place".
Diagnosing it currently means knowing to look at
~/.codegraph/daemons/for a missing entry, or noticing that nodaemon.logwas ever created. Neither is discoverable.Where
MCPEngine.doInitialize()(src/mcp/engine.ts:201) already has the exact branch:The failure path below it already writes to stderr on an open error:
so the channel and the precedent both exist. The no-root case is the one branch that returns quietly.
Suggested change
One stderr line in that branch, naming what was searched and, when a bounded scan finds them, which sub-directories are indexed:
The second line only when something was actually found, so the common "not a CodeGraph project" case stays a single line.
Make the same fact reachable through the protocol rather than only the host's stderr log: a tool call that needs the default project should fail with a message that says the project was never resolved and how to fix it, instead of behaving as if the project were merely empty. Users see tool output; almost nobody reads the MCP host's stderr capture.
Both are additive and independent of whether the down-scan is ever wired into the server's root resolution (companion issue). If it is, this message becomes the fallback for the several-candidates case. If it is not, it is the only thing standing between the user and a silent no-op.
Environment
CodeGraph 1.5.0, Windows 11, native filesystem (no WSL). Line numbers are against
mainat the time of writing.