Skip to content

fix(mcp): boot when cwd is outside a git repo (#105)#106

Merged
5uck1ess merged 1 commit into
mainfrom
fix/mcp-no-git-repo
May 22, 2026
Merged

fix(mcp): boot when cwd is outside a git repo (#105)#106
5uck1ess merged 1 commit into
mainfrom
fix/mcp-no-git-repo

Conversation

@5uck1ess

Copy link
Copy Markdown
Owner

Summary

Fixes #105 — devkit MCP server failed with opaque -32000 whenever Claude Code's working directory wasn't inside a git repo.

Root cause: rootCmd.PersistentPreRunE (src/cmd/root.go) ran a git-repo check before every subcommand, including mcp. The error went to stderr, which CC doesn't surface — the user only saw Failed to reconnect to plugin:devkit:devkit-engine: -32000.

Fix (issue's Option 1 — defer the git check):

  • Add an allow_no_git cobra annotation. Subcommands set it to opt out of the persistent git check.
  • mcpCmd opts out — the MCP server doesn't structurally need git state to complete the JSON-RPC initialize handshake.
  • MCP data dir resolves in priority order: CLAUDE_PLUGIN_DATA<repoRoot>/.devkit<user cache dir>/devkit. The last branch is new and handles the non-git case.
  • mcp.NewServer relaxed: only dataDir is required. Empty repoRoot / workflowDir are tolerated so the handshake completes; individual tool calls that need git or workflow defs return structured errors at call time instead of exiting at boot.

In production CC always sets CLAUDE_PLUGIN_ROOT, so workflows still resolve regardless of cwd — the user just needs the boot path not to fatal on a missing .git.

Test plan

  • New regression test TestMCPInitializeOutsideGitRepo (src/cmd/mcp_test.go) — builds the real binary, runs devkit mcp from a tempdir with no .git, sends a real initialize JSON-RPC request, asserts the response lands on stdout and the boot doesn't error with not inside a git repo.
  • Existing TestMCPStdoutIsCleanJSONRPC still passes (no stdout pollution introduced).
  • Full suite: go test ./... → 441 passed in 6 packages.
  • Manual: Windows user (issue reporter) confirms /mcp connects from a non-git cwd.

Out of scope

  • The mcpb/manifest.json version drift vs. .claude-plugin/plugin.json — separate follow-up to teach release.yml to bump both. The Makefile's sync-version step touched it on local build; reverted before committing so this PR stays scoped.

Before this change `devkit mcp` ran the root command's git-repo check at
startup and exited with `Error: not inside a git repo — run devkit from
a project directory` whenever Claude Code's working directory wasn't
inside a git checkout. That message went to the engine's stderr, which
CC doesn't surface to the user, so the only visible signal was the
opaque JSON-RPC server error `-32000`.

The MCP server doesn't structurally need git state to complete the
initialize handshake — only individual tool calls do (and they own that
check). So:

- Add an `allow_no_git` cobra annotation that subcommands can set to
  opt out of the persistent git check. `mcpCmd` sets it.
- When the annotation is set and there's no git repo, leave `repoRoot`
  empty rather than aborting.
- Pick the MCP data dir in priority order: `CLAUDE_PLUGIN_DATA` env
  → `<repoRoot>/.devkit` → `<user cache dir>/devkit`. The last branch
  is the new one — it handles the non-git case so the DB still has a
  home.
- Relax `mcp.NewServer` to require only `dataDir`; empty `repoRoot` and
  empty `workflowDir` are tolerated so the handshake can complete.
  Tools that need git or workflow definitions return structured errors
  at call time instead of exiting at boot.
- Add a regression test that runs `devkit mcp` from a non-git tempdir
  and asserts the JSON-RPC initialize response lands on stdout.

Closes #105.
@5uck1ess
5uck1ess merged commit e4c7678 into main May 22, 2026
6 checks passed
@5uck1ess
5uck1ess deleted the fix/mcp-no-git-repo branch May 22, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP server fails opaquely with -32000 when launched outside a git repo

1 participant