Summary
darnit install --client claude writes the MCP server config to ~/.claude/settings.json, which is Claude Desktop's config file. Claude Code reads from ~/.claude.json (different filename, different schema).
Net effect: a user runs darnit install, gets a success message saying the MCP server is configured, restarts Claude Code, and the darnit server doesn't appear. claude mcp list confirms it's not registered.
Discovered during the demo dry-run for feature 014 (#262) — multiple rounds of debug were needed because the install command's success message implies things are wired up.
Reproducer
# Fresh machine
darnit install --client claude
# → INFO: ✓ Installed darnit MCP server config in /Users/<you>/.claude/settings.json
# In any directory, ask Claude Code which MCP servers are available:
claude mcp list
# → no darnit entry; only the claude.ai-hosted servers (Slack, Notion, …)
# Where the config actually went:
cat ~/.claude/settings.json | jq '.mcpServers.darnit'
# → present, but Claude Code never reads this file
Root cause
packages/darnit/src/darnit/cli.py:492:
if args.client == "claude":
settings_path = Path.home() / ".claude" / "settings.json"
else:
settings_path = Path.home() / ".cursor" / "mcp.json"
The ~/.claude/settings.json path is what Claude Desktop uses on macOS for global settings (mcpServers block is the Desktop convention). Claude Code instead uses ~/.claude.json (different file, similar-but-not-identical schema).
The --client claude arg conflates two different clients with different config locations.
Proposed fix
Two layers:
1. Distinguish the clients
Split --client claude into --client claude-code (default) and --client claude-desktop. Or detect which is installed (heuristic: ~/.claude.json exists ⇒ Code; ~/Library/Application Support/Claude/ exists ⇒ Desktop) and write to the right one. Or write to BOTH if both clients are detected.
2. For Claude Code: use the right config path
if args.client == "claude-code":
settings_path = Path.home() / ".claude.json"
Or, more robust: invoke claude mcp add --scope user darnit -- <command> <args…> as a subprocess. That delegates the file-format question to the Claude Code CLI itself, which already handles config-schema drift. Tradeoff: requires claude to be on PATH.
3. Project-local mode
darnit install --project currently writes skills to .claude/skills/ but MCP config still goes global (regardless of --project). For Claude Code, project-local MCP config lives in .mcp.json at the project root. The --project flag should also wire MCP config there for symmetry.
Acceptance
darnit install --client claude-code configures the MCP server in ~/.claude.json (or .mcp.json if --project).
- After
darnit install, claude mcp list shows the darnit server as ✓ Connected.
- The previous
--client claude is either renamed or aliased with a deprecation warning.
darnit install --client claude-desktop preserves the old behaviour for Desktop users (writes to ~/.claude/settings.json).
Workaround (for now)
Skip darnit install's MCP-config side and use Claude Code's own CLI:
claude mcp add --scope user darnit -- /Users/<you>/.local/bin/darnit serve --framework openssf-baseline
darnit install --mcp-only is essentially worthless against Claude Code without this fix; --project only gets the skills installed locally (which is still useful).
Related
Summary
darnit install --client claudewrites the MCP server config to~/.claude/settings.json, which is Claude Desktop's config file. Claude Code reads from~/.claude.json(different filename, different schema).Net effect: a user runs
darnit install, gets a success message saying the MCP server is configured, restarts Claude Code, and the darnit server doesn't appear.claude mcp listconfirms it's not registered.Discovered during the demo dry-run for feature 014 (#262) — multiple rounds of debug were needed because the install command's success message implies things are wired up.
Reproducer
Root cause
packages/darnit/src/darnit/cli.py:492:The
~/.claude/settings.jsonpath is what Claude Desktop uses on macOS for global settings (mcpServersblock is the Desktop convention). Claude Code instead uses~/.claude.json(different file, similar-but-not-identical schema).The
--client claudearg conflates two different clients with different config locations.Proposed fix
Two layers:
1. Distinguish the clients
Split
--client claudeinto--client claude-code(default) and--client claude-desktop. Or detect which is installed (heuristic:~/.claude.jsonexists ⇒ Code;~/Library/Application Support/Claude/exists ⇒ Desktop) and write to the right one. Or write to BOTH if both clients are detected.2. For Claude Code: use the right config path
Or, more robust: invoke
claude mcp add --scope user darnit -- <command> <args…>as a subprocess. That delegates the file-format question to the Claude Code CLI itself, which already handles config-schema drift. Tradeoff: requiresclaudeto be on PATH.3. Project-local mode
darnit install --projectcurrently writes skills to.claude/skills/but MCP config still goes global (regardless of--project). For Claude Code, project-local MCP config lives in.mcp.jsonat the project root. The--projectflag should also wire MCP config there for symmetry.Acceptance
darnit install --client claude-codeconfigures the MCP server in~/.claude.json(or.mcp.jsonif--project).darnit install,claude mcp listshows the darnit server as✓ Connected.--client claudeis either renamed or aliased with a deprecation warning.darnit install --client claude-desktoppreserves the old behaviour for Desktop users (writes to~/.claude/settings.json).Workaround (for now)
Skip
darnit install's MCP-config side and use Claude Code's own CLI:darnit install --mcp-onlyis essentially worthless against Claude Code without this fix;--projectonly gets the skills installed locally (which is still useful).Related
parsing.pyAPI mismatch (Support tree-sitter-language-pack >= 1.8 (new binding API) #268) and thisdarnit installlocation bug both compounded into "MCP server doesn't load" symptoms with the same diagnostic shape.uvx --from darnit darnit serve) also doesn't fit dev-loop usage — it always pulls from PyPI even when an editable workspace install exists. Worth tracking separately but probably as a follow-up to this fix.