diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 6ef1ca2..3be7b42 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -5,6 +5,8 @@ ARG AGENT_PLATFORM_CLAUDE_CODE_VERSION ARG AGENT_PLATFORM_CODEX_VERSION ARG AGENT_PLATFORM_OPENCODE_VERSION ARG AGENT_PLATFORM_BACKLOG_MD_VERSION +ARG AGENT_PLATFORM_BACKLOG_MD_MCP_VERSION +ARG AGENT_PLATFORM_BEADS_VERSION ARG AGENT_PLATFORM_CONTEXT7_VERSION ARG AGENT_PLATFORM_PLAYWRIGHT_MCP_VERSION ARG AGENT_PLATFORM_ZSH_IN_DOCKER_VERSION @@ -22,7 +24,8 @@ ENV \ LANGUAGE='en_US:en' \ LC_ALL='en_US.UTF-8' \ PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD="1" \ - PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH="/usr/bin/chromium" + PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH="/usr/bin/chromium" \ + OPENCODE_CONFIG="/etc/opencode/managed_config.json" COPY --chmod=0555 "init-firewall.sh" "/usr/local/bin/init-firewall.sh" COPY --chmod=0555 "access.sh" "/usr/local/bin/access.sh" @@ -64,10 +67,11 @@ RUN \ chown --recursive node:node "/usr/local/share" "/workspace" "/commandhistory" "/home/node/.claude" "/home/node/.codex" "/home/node/.opencode" && \ chown --recursive root:root "/etc/claude-code/" "/etc/codex" "/etc/opencode" && \ mv "/home/node/.claude/managed-settings.json" "/etc/claude-code/" && \ + mv "/home/node/.claude/managed-mcp.json" "/etc/claude-code/" && \ mv "/home/node/.codex/managed_config.toml" "/etc/codex/" && \ mv "/home/node/.opencode/managed_config.json" "/etc/opencode/" && \ - chmod 0664 "/etc/claude-code/managed-settings.json" "/etc/codex/managed_config.toml" "/etc/opencode/managed_config.json" && \ - chown root:root "/etc/claude-code/managed-settings.json" "/etc/codex/managed_config.toml" "/etc/opencode/managed_config.json" && \ + chmod 0664 "/etc/claude-code/managed-settings.json" "/etc/claude-code/managed-mcp.json" "/etc/codex/managed_config.toml" "/etc/opencode/managed_config.json" && \ + chown root:root "/etc/claude-code/managed-settings.json" "/etc/claude-code/managed-mcp.json" "/etc/codex/managed_config.toml" "/etc/opencode/managed_config.json" && \ ln --symbolic "/etc/opencode/managed_config.json" "/home/node/.opencode/managed_config.json" USER node @@ -92,6 +96,8 @@ RUN \ npm install --global "@openai/codex@${AGENT_PLATFORM_CODEX_VERSION}" && \ npm install --global "opencode-ai@${AGENT_PLATFORM_OPENCODE_VERSION}" && \ npm install --global "backlog.md@${AGENT_PLATFORM_BACKLOG_MD_VERSION}" && \ + npm install --global "@radleta/backlog-md-mcp@${AGENT_PLATFORM_BACKLOG_MD_MCP_VERSION}" && \ + npm install --global "@beads/bd@${AGENT_PLATFORM_BEADS_VERSION}" && \ npm install --global "@upstash/context7-mcp@${AGENT_PLATFORM_CONTEXT7_VERSION}" && \ npm install --global "@playwright/mcp@${AGENT_PLATFORM_PLAYWRIGHT_MCP_VERSION}" && \ rm --recursive --force "/home/node/.claude/plugins" && \ diff --git a/.devcontainer/capability-check.sh b/.devcontainer/capability-check.sh index a1d722b..5b0ab59 100755 --- a/.devcontainer/capability-check.sh +++ b/.devcontainer/capability-check.sh @@ -2,7 +2,7 @@ set -o pipefail -expected_mcp_claude="$(jq -r '.mcpServers // {} | keys | join(" ")' /etc/claude-code/managed-settings.json)" +expected_mcp_claude="$(jq -r '.mcpServers // {} | keys | join(" ")' /etc/claude-code/managed-mcp.json 2>/dev/null)" expected_plugins_claude="$(jq -r '(.enabledPlugins // .plugins // {}) | keys | join(" ")' /etc/claude-code/managed-settings.json)" expected_mcp_codex="$(grep -oE '^\[mcp_servers\.[^]]+\]' /etc/codex/managed_config.toml | sed -E 's/^\[mcp_servers\.(.+)\]$/\1/' | paste -sd' ')" expected_mcp_opencode="$(jq -r '.mcp // {} | keys | join(" ")' /etc/opencode/managed_config.json)" diff --git a/.devcontainer/config/claude/managed-mcp.json b/.devcontainer/config/claude/managed-mcp.json new file mode 100644 index 0000000..09295fb --- /dev/null +++ b/.devcontainer/config/claude/managed-mcp.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "backlog-md": { + "command": "backlog-mcp", + "args": ["start"] + } + } +} diff --git a/.devcontainer/config/claude/managed-settings.json b/.devcontainer/config/claude/managed-settings.json index 62109fb..de49a86 100644 --- a/.devcontainer/config/claude/managed-settings.json +++ b/.devcontainer/config/claude/managed-settings.json @@ -54,7 +54,6 @@ "defaultMode": "bypassPermissions" }, "forceLoginMethod": "claudeai", - "mcpServers": {}, "enabledPlugins": { "frontend-design@claude-plugins-official": true, "playwright@claude-plugins-official": true, diff --git a/.devcontainer/config/codex/managed_config.toml b/.devcontainer/config/codex/managed_config.toml index 65c6f42..72accfd 100644 --- a/.devcontainer/config/codex/managed_config.toml +++ b/.devcontainer/config/codex/managed_config.toml @@ -21,3 +21,7 @@ set = { CODEX_HOME = "/home/node/.codex" } [mcp_servers.context7] command = "context7-mcp" args = [] + +[mcp_servers.backlog-md] +command = "backlog-mcp" +args = ["start"] diff --git a/.devcontainer/config/opencode/managed_config.json b/.devcontainer/config/opencode/managed_config.json index 883d60d..26e7f6c 100644 --- a/.devcontainer/config/opencode/managed_config.json +++ b/.devcontainer/config/opencode/managed_config.json @@ -8,6 +8,10 @@ "context7": { "type": "local", "command": ["context7-mcp"] + }, + "backlog-md": { + "type": "local", + "command": ["backlog-mcp", "start"] } }, "permission": { diff --git a/.devcontainer/config/shared/skills/public/instructions/SKILL.md b/.devcontainer/config/shared/skills/public/instructions/SKILL.md index 981973a..554eaee 100644 --- a/.devcontainer/config/shared/skills/public/instructions/SKILL.md +++ b/.devcontainer/config/shared/skills/public/instructions/SKILL.md @@ -25,6 +25,13 @@ Generate the rest of the content ensuring user get's up to date information: | MCP | Description | How to invoke | |-----|-------------|---------------| | `context7` | Upstash Context7 — live, version-specific library documentation lookup (https://github.com/upstash/context7). On Claude, surfaced via the `context7` plugin (see table below). On Codex and Opencode, surfaced via the standalone `@upstash/context7-mcp` MCP server. | Read how to use it from https://github.com/upstash/context7, summarize. | +| `backlog-md` | Backlog.md task management via MCP (https://github.com/radleta/Backlog.md-mcp). Replaces the prior CLI + embedded-docs approach; exposes `task_create`, `task_list`, `task_edit`, `board_show`, `overview`, etc. as typed tools. | Call the MCP tools directly from any agent (e.g., `task_create`, `task_list`); no need for embedded instructions. | + +## CLIs available for each agent + +| CLI | Description | How to invoke | +|-----|-------------|---------------| +| `bd` | Beads graph issue tracker / agentic memory system (https://github.com/gastownhall/beads). Per upstream guidance, shell-capable agents (Claude Code, Codex, Opencode) use the CLI directly rather than an MCP wrapper — lower token cost and latency. | From a shell in the devcontainer: `bd init`, `bd create "Title"`, `bd ready`, `bd update --claim`, `bd show `. | ## Plugins available for Claude Code diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 6bb939d..0790745 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,6 +7,8 @@ "AGENT_PLATFORM_CODEX_VERSION": "${localEnv:AGENT_PLATFORM_CODEX_VERSION:latest}", "AGENT_PLATFORM_OPENCODE_VERSION": "${localEnv:AGENT_PLATFORM_OPENCODE_VERSION:latest}", "AGENT_PLATFORM_BACKLOG_MD_VERSION": "${localEnv:AGENT_PLATFORM_BACKLOG_MD_VERSION:latest}", + "AGENT_PLATFORM_BACKLOG_MD_MCP_VERSION": "${localEnv:AGENT_PLATFORM_BACKLOG_MD_MCP_VERSION:latest}", + "AGENT_PLATFORM_BEADS_VERSION": "${localEnv:AGENT_PLATFORM_BEADS_VERSION:latest}", "AGENT_PLATFORM_CONTEXT7_VERSION": "${localEnv:AGENT_PLATFORM_CONTEXT7_VERSION:latest}", "AGENT_PLATFORM_PLAYWRIGHT_MCP_VERSION": "${localEnv:AGENT_PLATFORM_PLAYWRIGHT_MCP_VERSION:latest}", "AGENT_PLATFORM_ZSH_IN_DOCKER_VERSION": "${localEnv:AGENT_PLATFORM_ZSH_IN_DOCKER_VERSION:1.2.0}", diff --git a/CHANGELOG.md b/CHANGELOG.md index 1090f28..6d9f960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `instructions` public skill documenting installed plugins, MCP servers, and skills with invocation guidance. - Five curated Claude plugins from the `claude-plugins-official` marketplace, pre-enabled via managed settings: `frontend-design`, `playwright`, `feature-dev`, `ralph-loop`, `context7`. - System-wide Chromium (via apt) and `@playwright/mcp` (pinned by new `AGENT_PLATFORM_PLAYWRIGHT_MCP_VERSION` build arg) so the Playwright plugin has a usable browser. Dockerfile exports `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium` and `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1` to skip runtime browser downloads. +- `@radleta/backlog-md-mcp` MCP server (`backlog-md`) registered for Claude, Codex, and Opencode — exposes Backlog.md task/draft/doc/decision/board tools via typed MCP schemas so embedded CLI docs are no longer needed. +- `@beads/bd` CLI installed globally for all three agents (graph issue tracker / agentic memory system from https://github.com/gastownhall/beads); shell-capable agents use it directly per upstream guidance. New build args `AGENT_PLATFORM_BACKLOG_MD_MCP_VERSION` and `AGENT_PLATFORM_BEADS_VERSION`. +- `/etc/claude-code/managed-mcp.json` managed MCP config for Claude (the documented location for enterprise-deployed MCP servers). `claude mcp list` reads from this file, not from `mcpServers` in `managed-settings.json`. +- `OPENCODE_CONFIG=/etc/opencode/managed_config.json` exported as a container-wide environment variable so the managed Opencode config is picked up under bash (capability-check) as well as zsh (interactive sessions). ### Changed @@ -23,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `deployment.yml` now resolves `EXPECTED_SKILLS` from the canonical catalog. - Slimmed the always-loaded agent root files to a short numbered behavioral preamble modeled on [forrestchang/andrej-karpathy-skills](https://github.com/forrestchang/andrej-karpathy-skills/blob/main/CLAUDE.md) and deduplicated them into a single canonical `AGENTS.md` (plus canonical `TOOLS.md` and `SECURITY.md`) under `.devcontainer/config/shared/`, distributed to all three agents by the Dockerfile via symlinks. Inline security sections previously embedded in Codex and Opencode `AGENTS.md` were extracted into the canonical `SECURITY.md`. - Claude receives Context7 via the `context7` plugin instead of the standalone `@upstash/context7-mcp` MCP server. Codex and Opencode continue to use the standalone MCP. +- Backlog.md integration moved from per-agent CLI + embedded markdown instructions to a dedicated `backlog-md` MCP server. ### Removed diff --git a/README.md b/README.md index 4090e22..e663f06 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ Configuration is managed through environment variables. | `AGENT_PLATFORM_CODEX_VERSION` | `latest` | Devcontainer build arg that selects the Codex version. | No | String (version tag, e.g. `latest` or `1.2.3`) | | `AGENT_PLATFORM_OPENCODE_VERSION` | `latest` | Devcontainer build arg that selects the Opencode version. | No | String (version tag, e.g. `latest` or `1.3.0`) | | `AGENT_PLATFORM_BACKLOG_MD_VERSION` | `latest` | Devcontainer build arg that selects the Backlog.md CLI version. | No | String (version tag, e.g. `latest` or `1.40.0`) | +| `AGENT_PLATFORM_BACKLOG_MD_MCP_VERSION` | `latest` | Devcontainer build arg that selects the `@radleta/backlog-md-mcp` MCP server version. | No | String (version tag, e.g. `latest` or `0.1.10`) | +| `AGENT_PLATFORM_BEADS_VERSION` | `latest` | Devcontainer build arg that selects the `@beads/bd` CLI version. | No | String (version tag, e.g. `latest` or `1.0.2`) | | `AGENT_PLATFORM_CONTEXT7_VERSION` | `latest` | Devcontainer build arg that selects the Context7 MCP server version (used by Codex and Opencode; Claude now gets Context7 via the `context7` plugin). | No | String (version tag, e.g. `latest` or `1.0.0`) | | `AGENT_PLATFORM_PLAYWRIGHT_MCP_VERSION` | `latest` | Devcontainer build arg that selects the `@playwright/mcp` server version backing the `playwright` Claude plugin. | No | String (version tag, e.g. `latest` or `0.0.43`) | | `AGENT_PLATFORM_ZSH_IN_DOCKER_VERSION` | `1.2.0` | Devcontainer build arg that selects the zsh-in-docker version. | No | String (version tag, e.g. `1.2.0`) | diff --git a/docs/architecture.md b/docs/architecture.md index 706be29..e68f938 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -18,7 +18,8 @@ Agent Platform is a devcontainer-first runtime for configuring and running AI ag | |-- access.sh -> Runtime access test setup for the container. | |-- config | | |-- claude -| | | `-- managed-settings.json -> Managed (immutable) settings applied to Claude. +| | | |-- managed-settings.json -> Managed (immutable) settings applied to Claude. +| | | `-- managed-mcp.json -> Managed (immutable) MCP server definitions for Claude (deployed to /etc/claude-code/). | | |-- codex | | | `-- managed_config.toml -> Managed (immutable) Codex configuration. | | |-- opencode