Skip to content

feat!: remove the ACP adapter, bump the toolchain, add the cloudflare-docs MCP server - #20

Merged
intech merged 2 commits into
mainfrom
feat/remove-acp
Aug 21, 2026
Merged

feat!: remove the ACP adapter, bump the toolchain, add the cloudflare-docs MCP server#20
intech merged 2 commits into
mainfrom
feat/remove-acp

Conversation

@intech

@intech intech commented Aug 21, 2026

Copy link
Copy Markdown
Member

Summary

Removes the ACP (Agent Client Protocol) adapter and every constraint it imposed, bumps the pinned toolchain, and adds the cloudflare-docs MCP server. Docs are brought back in line with what the image actually does, including re-measured numbers.

Warning

Breaking: the project is now mounted at /workspace/project, not /workspace. Anything scripted against the old in-container path needs updating.

Remove the ACP adapter

run_acp.sh, the baked start-acp.sh entrypoint, the build-gate presence check, and ENV CLAUDE_CODE_EXECUTABLE (whose only consumer was the adapter) are gone, along with the @agentclientprotocol/claude-agent-acp dependency.

That also drops @agentclientprotocol/sdk and @anthropic-ai/claude-agent-sdk with its 8 per-platform Claude Code binaries, so the image no longer ships a second, separately-sourced Claude binary. The supply-chain residual documented in SECURITY.md is therefore closed, and the CLAUDE_CODE_EXECUTABLE pin that mitigated it is no longer needed.

Measured effect: the npm ci layer drops from ~1.47 GB to 1030.7 MB, and the image from 2.52 GB to 2.01 GB.

The Dev Container is kept — it never depended on ACP (its node-user removal and raised pids cap have their own reasons).

Mount the project one level down (breaking)

codebase-memory-mcp refuses to index any first-level path as a root since v0.10.0:

/workspace: path is too broad to index as one root; name a project directory below it

The rule comes from upstream PR #1464 (src/foundation/workspace.{c,h}, first shipped in v0.10.0), motivated by issue #1241 — an OOM from indexing ~. It cannot be lifted: allow-root /workspace answers refused, and --approve-sensitive does not apply to it (PR #1472 says so explicitly, and it was verified here).

Verified by measurement: /workspace and /proj are refused; /workspace/repo, /srv/x and /w/x index fine.

A fixed /workspace/project was chosen over a dynamic /workspace/$(basename $PWD) because claude-config.json and install-mcp-servers.sh write configuration under a static project key that Claude Code looks up by working directory. A fixed path keeps all baked configuration baked, needs no new entrypoint logic, and works identically in all four entrypoints — including the Dev Container and debug-shell.sh, where the image ENTRYPOINT never runs.

All four entrypoints (run_claude.sh, debug-shell.sh, the claude-box launcher generated by install.sh, and the Dev Container) move together with the project key in claude-config.json / install-mcp-servers.sh / diagnose-mcp.sh.

Dependency bumps

Component From To
@anthropic-ai/claude-code 2.1.221 2.1.238
@fission-ai/openspec 1.7.0 1.10.0
pnpm 11.18.0 11.22.0
eslint 10.8.0 10.8.1
RTK v0.44.2 v0.45.0
codebase-memory-mcp v0.9.0 v0.10.8

Lockfile regenerated inside node:22 (lockfileVersion 3); the previously patched form-data / hono / ip-address versions were verified to survive the regeneration. typescript stays at 6.0.3 — 7.x still breaks ts-node 10.9.2.

npm audit re-derived rather than carried over: 2 high, and both rows are the same single advisory GHSA-w48q-cv73-mx4w (<1.24.0) reached through perplexity-mcp — one row for the SDK, one for the dependent package. No fix available; still an accepted residual, and perplexity-mcp runs as a stdio server here with no listening socket. The previous wording (two distinct advisories, bound ≤1.25.1) did not match the current output and has been corrected.

caveman is deliberately held at v1.9.1

v2.2.0 adds a runtime dependency @caveman-ai/cli: ^1.1.0, which ships its own caveman bin. That bin shadows the installer's own bin under npx, so npx -y github:JuliusBrussee/caveman#v2.2.0 --non-interactive … never reaches bin/install.js — it runs the cloud CLI, which answers unknown command "--non-interactive". The installer script itself still accepts the old flags; it is simply unreachable that way.

Independently of the invocation, that dependency is a floating range in a build layer (against this image's exact-pin policy), and @caveman-ai/cli is an account/cloud CLI whose compression runs in "companion Go binaries" fetched by caveman setup — a runtime download this image forbids. v1.9.1 has no dependencies at all. The reasoning is recorded in the Dockerfile and CLAUDE.md so a future bump starts from evidence rather than from scratch.

codebase-memory-mcp hardening

  • CBM_ALLOWED_ROOT=/workspace is now baked in. This was previously impossible because the ACP adapter mounted the project at its host-absolute path. Verified as a live control, not a dead knob: indexing /home/agent is refused with is outside the allowed root, while /workspace/project indexes normally.
  • The graph UI is turned off at build time (config set ui_enabled false). Upstream defaults ui_enabled to true, so the coordination daemon otherwise binds 127.0.0.1:9749 on the first MCP session — contrary to the upstream README, which documents the UI as needing an explicit --ui=true --port=9749. A hardened image should not carry an undocumented listening socket, the less so because POST /api/index on it drives indexing. Verified: no listening socket in /proc/net/tcp and no ui.serving line in the daemon log.
  • v0.10.x runs a background daemon that cannot be disabled by configuration. Measured under the production profile: 2 processes (frontend + daemon) versus 1 on v0.9.0, comfortably inside --pids-limit=100, so auto_watch is left at its default. Idle CPU spikes to ~100% of one core at daemon start, then settles at 2.1–2.4% (v0.9.0: 0.01–0.03%) — see open upstream issue #1764, whose severe form is reported on Windows.

Add the cloudflare-docs MCP server

type: http, no API key, no headers, no npm package — nothing to pre-install and nothing to add to .env. Added to the third-party egress enumerations in both README.md ("Honest scope") and SECURITY.md ("Outbound network is allowed"), since those name every service that receives code context.

Documentation

README.md, CLAUDE.md and SECURITY.md updated throughout: the ACP sections removed, versions and paths corrected, and every measured number re-derived on the built image rather than carried over.

Two pre-existing drifts were fixed along the way:

  • CLAUDE.md claimed OpenSpec is initialized into the project mount; the Dockerfile initializes it into the build HOME (/home/claude).
  • The Dockerfile and CLAUDE.md claimed caveman merges SessionStart/UserPromptSubmit hooks into settings.json. Measured in the built image: those arrays are empty and PreToolUse holds only RTK's rtk hook claude — the hooks come from the plugin manifest, and the caveman layer does not clobber RTK's hook.

A dead permissions.additionalDirectories array pointing at /workspace/{input,output,data,temp} was dropped rather than carried forward to the new path — those directories have not existed since the container moved to single read-write mode.

Verification

Performed against the built image (--cap-drop=ALL, --security-opt=no-new-privileges, --pids-limit=100, tmpfs HOME, host uid), not by reading code:

  • Clean --no-cache build green; both sha256sum -c checks pass for RTK v0.45.0 and codebase-memory-mcp v0.10.8.
  • No /home/claude/start-acp.sh, no claude-agent-acp on PATH, no CLAUDE_CODE_EXECUTABLE, no @agentclientprotocol in /opt/toolchain.
  • claude mcp list → all six servers ✔ Connected in ~5.7 s under the default MCP_TIMEOUT=10000.
  • index_repository on /workspace/project → 231 nodes / 279 edges, 2.3 MB cache; on /home/agent → refused.
  • /proc/net/tcp and /proc/net/tcp6 → no listening sockets.
  • codebase-memory-mcp MCP surface measured via tools/list: 15 tools (up from 8 in v0.9.0).
  • Hooks intact: PreToolUse = rtk hook claude, statusLine present, no caveman-shrink MCP entry.
  • Entrypoint smoke test: starts in /workspace/project, claude --version → 2.1.238.
  • claude doctor on 2.1.238: "No installation issues found." (only the expected Remote Control full-scope-token note).
  • /app/diagnose-mcp.sh: 5 stdio binaries found, 6 mcpServers keys including cloudflare-docs.
  • Residual sweep over tracked files for \bacp\b|\bzed\b|agentclientprotocol|claude-agent-acp|claude-agent-sdk|start-acp|run_acp|CLAUDE_CODE_EXECUTABLE|ACP_PIDS_LIMIT → only the deliberate historical mentions in the SECURITY.md closure note and the CLAUDE.md explanation of why CBM_ALLOWED_ROOT became possible.

Not verified here: arm64. The second sha256 pair of each GitHub-release binary is only exercised by the arm64 CI job on this PR.

intech and others added 2 commits August 21, 2026 03:00
BREAKING CHANGE: the project is now mounted at /workspace/project, not /workspace.

Remove ACP
- Delete run_acp.sh, the baked start-acp.sh entrypoint, the build-gate presence
  check, and ENV CLAUDE_CODE_EXECUTABLE (its only consumer was the ACP adapter).
- Drop @agentclientprotocol/claude-agent-acp from the locked toolchain. That also
  removes @agentclientprotocol/sdk and @anthropic-ai/claude-agent-sdk with its 8
  per-platform Claude Code binaries, so the image no longer ships a second,
  separately-sourced Claude binary — the supply-chain residual documented in
  SECURITY.md is closed, and the CLAUDE_CODE_EXECUTABLE pin that mitigated it is
  no longer needed. The npm ci layer drops from ~1.47 GB to 1030.7 MB and the
  image from 2.52 GB to 2.01 GB.
- Dev Container is kept; it never depended on ACP.

Mount the project one level down (breaking)
- codebase-memory-mcp refuses to index any first-level path as a root since
  v0.10.0: index_repository on /workspace answers "path is too broad to index as
  one root". The rule comes from upstream PR #1464 (src/foundation/workspace.c),
  motivated by issue #1241 (OOM from indexing ~), and cannot be lifted —
  `allow-root /workspace` answers "refused" and --approve-sensitive does not
  apply. Verified: /workspace and /proj are refused; /workspace/repo, /srv/x and
  /w/x index fine.
- All four entrypoints (run_claude.sh, debug-shell.sh, the claude-box launcher
  from install.sh, the Dev Container) now mount at /workspace/project, and the
  project key in claude-config.json / install-mcp-servers.sh / diagnose-mcp.sh
  moves with them.

Dependencies
- claude-code 2.1.221 -> 2.1.238, openspec 1.7.0 -> 1.10.0, pnpm 11.18.0 ->
  11.22.0, eslint 10.8.0 -> 10.8.1; lockfile regenerated inside node:22
  (lockfileVersion 3). typescript stays at 6.0.3 — 7.x still breaks ts-node.
- RTK v0.44.2 -> v0.45.0, codebase-memory-mcp v0.9.0 -> v0.10.8, both sha256
  refreshed per arch.
- caveman stays at v1.9.1. v2.2.0 adds a floating dependency @caveman-ai/cli
  (^1.1.0) whose own `caveman` bin shadows the installer's under npx, so the
  documented invocation no longer reaches bin/install.js; that dependency is also
  an account/cloud CLI that fetches companion Go binaries at runtime, which this
  image forbids.
- npm audit re-derived: 2 high, both rows of the single advisory
  GHSA-w48q-cv73-mx4w (<1.24.0) via perplexity-mcp; no fix available, still an
  accepted residual. The previously patched form-data/hono/ip-address survived
  the regeneration.

codebase-memory-mcp hardening
- Bake CBM_ALLOWED_ROOT=/workspace, now possible because /workspace is the single
  entrypoint path. Verified as a live control: indexing /home/agent is refused.
- Turn the graph UI off at build time (config set ui_enabled false). Upstream
  defaults it to true, so the daemon otherwise binds 127.0.0.1:9749 — contrary to
  the upstream README, which documents the UI as opt-in. Verified: no listening
  socket in the built image.

Add cloudflare-docs MCP (type: http, no API key, no package to install).
claude mcp list shows all six servers connected in ~5.7s.

Docs: README/CLAUDE.md/SECURITY.md updated throughout, including re-measured
numbers (15 MCP tools vs 8, 231 nodes / 279 edges, 280 MB binary, layer sizes)
and two pre-existing drifts fixed — OpenSpec is initialized into /home/claude
(not the project mount), and caveman's hooks come from the plugin manifest rather
than settings.json.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXpQVijvq37fmKbLVWhgZC
The array granted access to /workspace/{input,output,data,temp}, which have not
existed since the container moved to single read-write mode — nothing creates
them and the README says as much. Carrying them forward to /workspace/project
would have preserved a knob that grants nothing. The project mount itself needs
no entry here.

Verified in the rebuilt image: the project key is /workspace/project, permissions
carry only the allow list, and all six MCP servers still connect.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AXpQVijvq37fmKbLVWhgZC
@intech intech self-assigned this Aug 21, 2026
@intech
intech merged commit 8af3cec into main Aug 21, 2026
3 checks passed
@intech
intech deleted the feat/remove-acp branch August 21, 2026 10:22
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