Skip to content

feat(cli): wrap and unwrap the Claude Desktop config for one server - #213

Merged
kerlenton merged 3 commits into
kerlenton:mainfrom
hsdfat:feat/136-wrap-claude-desktop-config
Aug 8, 2026
Merged

feat(cli): wrap and unwrap the Claude Desktop config for one server#213
kerlenton merged 3 commits into
kerlenton:mainfrom
hsdfat:feat/136-wrap-claude-desktop-config

Conversation

@hsdfat

@hsdfat hsdfat commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Closes #136.

Pointing Claude Desktop at the proxy meant hand-editing its config — easy to get wrong, awkward to undo. Adds mcpsnoop wrap / unwrap for one named server.

  • backs the config up before touching it, and writes atomically (same pattern as internal/toolbaseline/baseline.go)
  • wrapping twice is a no-op rather than nesting; unwrap restores the entry byte for byte
  • --dry-run prints the change without writing
  • an unknown server or missing config is an error, never a silent rewrite

Scoped to Claude Desktop only, one config path per OS, as the issue asks. Client-specific details sit behind a small wrapClient value so a second client would be a data change — but none is added here.

Checklist

  • make check passes (gofmt, vet, staticcheck, race tests) — plus cross-compiled vet and build for windows and darwin
  • Added or updated tests for the change, where it makes sense
  • Updated the README / docs if user-facing behaviour changed

Add `mcpsnoop wrap <server>` and `mcpsnoop unwrap <server>`, which edit
Claude Desktop's claude_desktop_config.json so a named server starts
through mcpsnoop, and put it back.

Only the target server's byte range is rewritten. Decoding into a
json.RawMessage returns the value's original bytes and InputOffset gives
its exact span, so the user's indentation, key order, other servers and
trailing newline all survive; a decode-and-re-encode of the whole file
could not do that. wrap copies the config to <config>.mcpsnoop.bak
before touching it, and unwrap restores those bytes verbatim when the
rest of the file is still as wrap left it, so the round trip is byte for
byte. When the config changed in the meantime, unwrap rewrites only the
entry and keeps the backup, so an unrelated edit is never clobbered.

Both directions are idempotent, --dry-run writes nothing, and a missing
config, an unknown server, an unknown client and a non-stdio entry each
report what to do next. Clients live in a registry that a file registers
itself into from init, so a second client is a new file rather than an
edit to wrap.go.

Config path resolution goes through os.UserConfigDir, which already
resolves to the three directories Claude Desktop uses, so there is no
runtime.GOOS switch to get wrong.

Fixes kerlenton#136
@kerlenton

Copy link
Copy Markdown
Owner

Thank you!

@kerlenton
kerlenton merged commit cb10b40 into kerlenton:main Aug 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mcpsnoop wrap for Claude Desktop, so the config edit stops being manual

2 participants