Skip to content

MCP server is silent when no project resolves #1607

Description

@nakisen

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

  1. 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.

  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions