feat(onboarding): auto-register MCP entry into Claude Desktop / Claude Code / Cursor configs (re-PR) - #147
Merged
Merged
Conversation
…e Code / Cursor configs Item 1.2 from HIGH-plan-broad-audience-onboarding.md. Stacks on top of PR #142 (zero-config RPC + udev + deep-link URLs). Eliminates the single biggest non-dev friction point — finding + editing `claude_desktop_config.json` (or per-OS equivalents) by hand. ## What ships `src/setup/register-clients.ts` — pure module, no console output, no prompts. Three exports the wizard composes: - `getClientConfigPaths()` — per-OS list of (Claude Desktop, Claude Code, Cursor) user-level config paths. - `detectClient(configPath)` — `configured` / `installed` / `absent`. `installed` = parent dir exists but config doesn't (Claude Desktop creates `~/Library/Application Support/Claude` on install whether or not any MCP servers are configured). - `patchClientConfig(client, configPath, opts?)` — additive + idempotent + atomic + reversible. Reads existing JSON, merges in `mcpServers.vaultpilot-mcp`, atomic-renames, leaves a `<file>.vaultpilot.bak` next to it. The MCP entry is `{ command: "node", args: ["<abs path>/dist/index.js"] }`, resolved via `import.meta.url`. Works whether the user `npm i -g`'d or cloned from source — absolute path doesn't depend on PATH and won't break under a reinstall under a different prefix. ## Wizard wiring `src/setup.ts` gains an `offerClientAutoRegister(p)` helper called at the end of `runFullWizard()`. Detects clients, prints which were found, asks `[Y/n]`, runs the patch sweep, prints a per-client summary (`✓ Added` / `✓ Already configured` / `· Not detected` / `✗ Error`). Auto-register is opt-in (default Y, but the user must press enter): even with backups, touching another app's config is the kind of thing to ask before doing. ## Per-project / per-workspace configs are NOT touched `<project>/.claude/settings.json` and `<workspace>/.cursor/mcp.json` are deliberately skipped. The wizard runs from an arbitrary CWD; the user might be in `~`, in a personal-finance repo, or anywhere. Patching the wrong project's config is worse than skipping. Documented in the module doc-comment + the README. ## Hardening - Atomic write via tmp + rename. A crashed wizard never leaves a half- written config. - 0o600 file mode preserved. MCP configs may carry API keys; tightening perms is cheap insurance. - Malformed-JSON-existing-config returns a structured `error` result rather than crashing or overwriting. - Empty-file existing config is treated as `{}` and patched normally. - `vaultpilot-mcp` already present → `already-present` result with no write. Re-running the wizard is safe. ## README "Use with Claude Desktop" section rewritten to mention auto-register first and surface the manual JSON snippet as a fallback for users who prefer to edit by hand. Lists every detected path so users know what the wizard is reaching for. ## Verification - `npm test` — **810/810** pass (+15 new register-clients tests covering: per-OS path detection, three detect states, six patch paths including idempotent + malformed-JSON + perms, integration test for partial-detection, and the summary formatter). - `npm run build` — clean TS. - Manual: ran `vaultpilot-mcp-setup` end-to-end on this Linux box, confirmed it added the vaultpilot-mcp entry to `~/.claude.json` alongside an existing entry, backed up the original, and reported Cursor as not-detected (no `~/.cursor/`). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Re-opening this against
maindirectly. Original PR #144 was stacked onfeat/broad-audience-onboarding-v1and merged into that feature branch instead ofmain; PR #142 was then squash-merged tomaindirectly, leaving #144's content unable to flow up. PR #146 reverted #144 on the feature branch. Net:mainhas #142, but the auto-register feature never landed there.This PR fixes that. The branch is rebased onto current
main(which already has #142 + #143 — Solana staking-portfolio integration); the diff is exactly the four files from the original #144.Item 1.2 from
claude-work/HIGH-plan-broad-audience-onboarding.md. Eliminates the single biggest non-dev friction point — finding + editingclaude_desktop_config.json(or per-OS equivalents) by hand.What ships
src/setup/register-clients.ts— pure module, no console output, no prompts. Three exports the wizard composes:getClientConfigPaths()— per-OS list of (Claude Desktop, Claude Code, Cursor) user-level config paths.detectClient(configPath)—configured/installed/absent.patchClientConfig(client, configPath, opts?)— additive + idempotent + atomic + reversible. Reads existing JSON, merges inmcpServers.vaultpilot-mcp, atomic-renames, leaves a<file>.vaultpilot.baknext to it.The MCP entry is
{ command: "node", args: ["<abs path>/dist/index.js"] }, resolved viaimport.meta.url. Works whether the usernpm i -g'd or cloned from source — absolute path doesn't depend on PATH and won't break under a reinstall under a different prefix.Wizard wiring
src/setup.tsgains anofferClientAutoRegister(p)helper called at the end ofrunFullWizard(). Detects clients, prints which were found, asks[Y/n], runs the patch sweep, prints a per-client summary (✓ Added/✓ Already configured/· Not detected/✗ Error).Auto-register is opt-in (default Y, but the user must press enter): even with backups, touching another app's config is the kind of thing to ask before doing.
Per-project / per-workspace configs are NOT touched
<project>/.claude/settings.jsonand<workspace>/.cursor/mcp.jsonare deliberately skipped. The wizard runs from an arbitrary CWD; the user might be in~, in a personal-finance repo, or anywhere. Patching the wrong project's config is worse than skipping. Documented in the module doc-comment + the README.Hardening
errorresult rather than crashing or overwriting.{}and patched normally.vaultpilot-mcpalready present →already-presentresult with no write. Re-running the wizard is safe.README
"Use with Claude Desktop" section rewritten to mention auto-register first and surface the manual JSON snippet as a fallback for users who prefer to edit by hand. Lists every detected path so users know what the wizard is reaching for.
Test plan
npm test— 821/821 pass (+15 new register-clients tests).npm run build— clean TS.🤖 Generated with Claude Code