Skip to content

Feat/claude desktop#80

Merged
RonCodes88 merged 8 commits into
mainfrom
feat/claude-desktop
May 8, 2026
Merged

Feat/claude desktop#80
RonCodes88 merged 8 commits into
mainfrom
feat/claude-desktop

Conversation

@RonCodes88

@RonCodes88 RonCodes88 commented May 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Extends Claude Desktop gating to cover the Settings → Extensions install path — the dominant way users add MCP servers today. Each Desktop Extension's bundle manifest is rewritten in place using the schema-blessed
_meta.agentlock slot (MCPB v0.3+), routing every tools/call through agentlock mcp-proxy with daemon policy enforcement.

What changed

  • Wrap Desktop Extension bundle manifests at ~/Library/Application Support/Claude/Claude Extensions/<id>/manifest.json so MCP traffic is gated alongside the existing mcpServers path.
  • Stash original mcp_config + version fields under _meta.agentlock.original_* for byte-clean restore on uninstall.
  • Bump manifest_version 0.1/0.2/missing → "0.3" (and the deprecated dxt_version field in lockstep) so the validator accepts the wrap.
  • Rewrite mcp_config.command to the agentlock binary, defeating Claude Desktop's UtilityProcess shortcut and forcing the literal-spawn path.
  • CLI now enumerates each bundle's manifest.json and per-extension Claude Extensions Settings/<id>.json and includes them in install / uninstall payloads.
  • Disabled extensions (per the settings sidecar) get unwrapped rather than re-wrapped.
  • Detector notes + docs/status.md updated to reflect the new coverage and the auto-update caveat.

Test plan

  • bun test passes (cli)
  • cargo test passes (ledger)
  • go test -race ./... passes (control-plane)
  • Manual test:
    1. Install any Desktop Extension via Settings → Extensions (verified with Filesystem and Control Chrome).
    2. Run agentlock install — plan should include a write op for Claude Extensions/<id>/manifest.json.
    3. jq '{manifest_version, dxt_version, has_meta: has("_meta")}' <bundle>/manifest.json shows "0.3", "0.3", true.
    4. Restart Claude Desktop. ps -ef | grep "agentlock mcp-proxy --name <ext-id>" shows one live process per wrapped extension.
    5. Drive a tool call from the extension in a chat — ledger records mcp__<ext-id>__<tool> with verdict: "allow".
    6. Add a deny gate (tool_prefix: "mcp__<ext-id>__") and PATCH /v1/mode to firewall. Repeat the prompt — chat shows the synthesized deny error and ledger records verdict: "deny".
    7. Re-run agentlock install with claude-desktop deselected — bundle manifest restored to byte-equivalent original (no _meta, original version fields back).

Notes for reviewers

  • Schema choice (_meta.agentlock): picked because v0.1/v0.2 are additionalProperties: false everywhere with no tolerated marker slot — confirmed by hand-probing the live validator. v0.3 is a strict superset of v0.1/v0.2
    (additive only), so bumping is safe per the upstream modelcontextprotocol/mcpb schemas.
  • Why we bump dxt_version too: the v0.3 schema pins it as const: "0.3" if present. Anthropic's own Control Chrome extension still ships with the deprecated dxt_version: "0.1" and no manifest_version; without bumping
    both, the validator rejects the wrap. TestBundleManifest_BumpsLegacyDxtVersion pins this case.
  • Why rewriting mcp_config.command matters: type: "node" extensions normally short-circuit through Claude Desktop's UtilityProcess (Electron built-in Node), bypassing mcp_config.command entirely. Rewriting the command to
    a non-node binary fails the runtime's "is this a Node.js server" check and forces basic-execution spawn. Pinned by TestBundleManifest_*.
  • Auto-update gap: when Anthropic ships a new version of an extension, Claude Desktop replaces the bundle and the wrap is gone. Doc'd in docs/status.md; users re-run agentlock install. A filesystem watcher closes this; out
    of scope.
  • Tool-name format change: the Extensions path uses --name <ext-id>, so the daemon sees mcp__<ext-id>__<tool> instead of mcp__<server-name>__<tool>. Existing user gates pointing at the old mcpServers names won't match
    Extensions traffic — a tool_prefix gate covers both. Worth a release note.
  • Out of scope (unchanged): Connectors (cloud-mediated), Computer Use, integrated terminal, Cowork plugins, Anthropic-signed extensions if/when they ship, Windows.
  • Registry (extensions-installations.json): not edited by the install pipeline. The bundle manifest is the launch source; the registry is an audit record. The existing mergeExtensionRegistry / stripExtensionRegistry
    helpers stay as defensive cleanup but are not wired in.

Checklist

  • I read CONTRIBUTING.md
  • No secrets, real tokens, or .env content committed
  • Public docs updated if user-facing behavior changed

@RonCodes88 RonCodes88 merged commit af167f0 into main May 8, 2026
6 checks passed
@knhn1004 knhn1004 deleted the feat/claude-desktop branch May 9, 2026 01:36
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.

1 participant