Cowork Agent 48904c7787
CI / Lint (ruff) (pull_request) Successful in 12s
CI / Tests (py3.12 / windows-latest) (pull_request) Failing after 17s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 10s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 14s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 39s
feat: MCP server catalog core -- signed, validated, resolvable (#10, #61)
Phase 1 of the MCP server catalog: pure, GUI-free core functions plus the
seed data/catalog.json (20 servers). No GUI wiring in this PR -- bcc.py is
untouched; a follow-up PR adds the picker dialog.

- load_catalog(): strict json.loads ONLY. The lenient repair pipeline
  (repair_json_text / parse_pasted_json*) is never used on catalog bytes,
  by design and by comment, so a signature always authenticates exactly
  what gets parsed.
- validate_catalog(): rejects the whole file (not per-entry) on: bad
  schema/version types, missing tier-appropriate fields (basic needs
  config.command+args, link-only needs docs_url and no config), a
  command allowlist (npx/uvx/docker/node/python/python3 only), -e/--eval/-c
  denial for node/python, --privileged and root/$HOME volume-mount denial
  for docker, non-empty env_required values (hard rejection -- secrets
  never ship in the catalog), secret-looking args (reuses
  _TOKEN_PREFIXES/_is_secret_value rather than reimplementing), non-https
  URL fields, and non-ASCII code points in id/command/args (homoglyph
  defence).
- verify_catalog_signature(): Ed25519 via the cryptography package,
  domain-separated message (the literal prefix "bcc-catalog-v1|" + raw
  bytes), accepts a match against any key in CATALOG_PUBKEYS
  (rotation-ready), never raises.
- resolve_catalog(): picks the highest version among bundled/cached/remote
  candidates that EACH independently pass verify + validate -- the bundled
  catalog gets no implicit trust, closing the hole where an unsigned
  payload merged to main would win on being local. Anti-rollback (never
  regress below the best verified candidate already in hand) and
  anti-freeze (reject a jump of more than 1000 versions) built in.
- catalog_entry_to_paste_json() / config_has_unfilled_placeholders(): small
  pure helpers the future GUI dialog will use to feed a catalog pick into
  the existing paste-import path and to gate Save on unfilled placeholder
  tokens.

data/catalog.json: the provided 20-server seed, with a signed_at field
added at the top level (lives inside the signed payload once real signing
lands in #62). Wired into bcc.spec's PyInstaller datas so it bundles into
the frozen app.

Security requirements from the issue, and where they landed:
- Catalog bytes never touch the lenient JSON repair path -- enforced by
  load_catalog()'s strict json.loads and a comment warning against wiring
  it in later.
- env_required values are a hard rejection when non-empty, not a warning.
- Secret-looking args are rejected at validation time, reusing the
  existing secret-detection helpers instead of duplicating them.
- Non-ASCII id/command/args rejected (typosquat/homoglyph defence).
- URL fields restricted to https://.
- Ed25519 signature verification is domain-separated and never raises.
- The bundled catalog is verified at runtime exactly like remote/cached --
  no implicit trust for being local.
- Anti-rollback and anti-freeze bounds on resolve_catalog's version
  comparison.

Tests: 42 new tests added to tests/test_core.py (full suite: 239 passed,
1 pre-existing unrelated skip). ruff check and ruff format --check both
clean.
2026-07-12 17:32:50 -04:00
2026-06-29 14:12:50 -04:00

Better Claude Config (BCC)

A small, cross-platform GUI for editing the mcpServers block of Claude Desktop and Claude Code installs — without ever hand-writing JSON.

BCC only ever touches mcpServers (and its own _disabledMcpServers parking key). Every other key in your config is preserved verbatim, in its original order. Each write is atomic and makes a timestamped backup first.

Download (no Python required)

Pre-built self-contained binaries are attached to every GitHub Release:

Platform Download Run
macOS BetterClaudeConfig-macOS.zip Unzip → drag BetterClaudeConfig.app to Applications
Windows BetterClaudeConfig-Windows.zip Unzip → double-click BetterClaudeConfig.exe
Linux BetterClaudeConfig-Linux.tar.gz Extract → run BetterClaudeConfig

macOS Gatekeeper note: the app is not notarized. On first launch, right-click → Open, or run xattr -cr /Applications/BetterClaudeConfig.app in a terminal.

Run from source

pip install -r requirements.txt
python bcc.py

(Python 3.10+, PySide6 6.6+.)

What it does

  • Auto-discovers installs — scans the platform's app-support folder for any Claude* directory (so Claude and Claude-Work both show up) and finds Claude Code's user-scope config at ~/.claude.json (the file claude mcp add writes). Use Add config… to point at any other file manually — e.g. a project's .mcp.json.

  • Form-based editing — name, command, args (one per line), env vars, or for remote servers: URL, transport, and headers. No raw JSON.

  • Paste JSON — even broken JSON — drop in any snippet from an MCP doc (full mcpServers block, inner map, or a single bare server object); it's parsed and merged. The paste box parses as you type and auto-repairs the stuff docs and chat windows love to break: markdown fences, surrounding prose, comments, trailing or missing commas, smart quotes, single quotes, unquoted keys, and unclosed braces — and tells you exactly what it fixed before you commit.

  • Drag & drop a .json file onto the window to import servers from it.

  • Copy to ▸ — copy the selected server straight into your other install.

  • Active / Disabled sections — servers are shown in two labelled lists with live counts, so a server that's switched off in the config is obvious at a glance. Toggle a server's checkbox to move it between sections (disabled servers are parked under _disabledMcpServers, which Claude ignores).

  • Dependency check + diagnostics — each server shows whether its command is actually found on PATH:

    • ● green — found on the normal PATH; will work anywhere.
    • ▲ amber (PATH-risk) — found, but only in a location BCC added on top of the inherited PATH. It'll work when you launch Claude from a terminal, but a double-clicked .app may not see it. This is the usual cause of "the tool says it's fine but Claude won't start the server." One click on Use full path ↳ rewrites the bare command (npx) to its absolute path so any launch finds it.
    • ● red (broken) — not found anywhere.
    • ◆ blue — remote (url) server. Test connection does a live reachability check on a background thread (any HTTP response = reachable).

    Each section header shows a broken / PATH-risk count badge, and selecting a flagged server auto-opens a Details panel with a full, copy-pasteable report: which command resolved to what, tailored install hints, and the exact PATH that was searched (with + marking the dirs BCC added). Re-check re-scans PATH after you install something; Copy diagnostics grabs the whole report for a bug report.

After saving, restart that Claude install for changes to take effect.

Config locations it scans

Claude Desktop

OS Base it scans for Claude*
macOS ~/Library/Application Support
Windows %APPDATA%
Linux ~/.config

Claude Code (all platforms): ~/.claude.json (user scope). If servers are found parked in ~/.claude/settings.json — where Claude Code ignores them — that file is also listed, marked legacy, so you can copy them over.

Files

  • bcc.py — the GUI.
  • bcc_core.py — all the file/JSON/validation/dependency logic (no GUI deps).
  • test_core.py — unit suite for the core (python test_core.py).
  • bcc.spec — PyInstaller build spec (cross-platform).
  • scripts/build_icons.py — regenerates icons/app.icns and icons/app.ico from source PNGs.

Building from source

pip install -r requirements-dev.txt
python scripts/build_icons.py   # regenerate icons if needed
pyinstaller bcc.spec
# macOS  → dist/BetterClaudeConfig.app
# Windows → dist/BetterClaudeConfig.exe
# Linux  → dist/BetterClaudeConfig

Releases are built automatically by GitHub Actions (.github/workflows/release.yml) when a version tag is pushed:

git tag v1.0.0 && git push --tags

Rebrand

The accent color is one constant (ACCENT) at the top of bcc.py.

License

MIT — see LICENSE.

S
Description
No description provided
Readme MIT 4.8 MiB
2026-07-12 14:06:40 -04:00
Languages
Python 100%