From 21be80763e66c826abb5630ca1f0e088df351f1c Mon Sep 17 00:00:00 2001 From: Geoff Johnson Date: Mon, 23 Mar 2026 09:29:15 -0700 Subject: [PATCH 1/4] docs: add ADR 0001 (agentd-mcp stdio transport) and wire into nav From 9da77ba003b47ca92a79f372f43ae4a14bf96a1c Mon Sep 17 00:00:00 2001 From: Geoff Johnson Date: Mon, 23 Mar 2026 09:30:30 -0700 Subject: [PATCH 2/4] docs: add ADR 0001 (agentd-mcp stdio transport) and wire into nav MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Commit ADR 0001 from architect agent's untracked file - Create docs/planning/decisions/ directory structure - Add Architecture Decisions section to mkdocs.yml nav under Development - ADR status: Proposed — documents decision to use stdio/rmcp pass-through over HTTP server or CLI embedding, covering trade-offs, consequences, and implementation notes for the crates/mcp/ scaffold (#249) --- .../0001-agentd-mcp-stdio-transport.md | 149 ++++++++++++++++++ mkdocs.yml | 2 + 2 files changed, 151 insertions(+) create mode 100644 docs/planning/decisions/0001-agentd-mcp-stdio-transport.md diff --git a/docs/planning/decisions/0001-agentd-mcp-stdio-transport.md b/docs/planning/decisions/0001-agentd-mcp-stdio-transport.md new file mode 100644 index 00000000..6347b066 --- /dev/null +++ b/docs/planning/decisions/0001-agentd-mcp-stdio-transport.md @@ -0,0 +1,149 @@ +# 0001 — agentd-mcp: MCP Observability Server via stdio Transport + +**Date**: 2026-03-23 +**Status**: Proposed +**Deciders**: architect agent, project owner +**Related**: #248, #249–#259 + +## Context + +agentd needs an interface that allows MCP-capable clients (Claude Code, Claude +Desktop) to inspect, diagnose, and remediate issues across all agentd services. +The Model Context Protocol (MCP) is the natural fit — it provides structured +tool invocation over a standardized protocol. + +Every existing agentd service follows a common template: + +- HTTP server on an allocated port (170xx dev / 70xx prod) +- SeaORM + SQLite for persistence +- `agentd_common::server::init_tracing()` for structured logging +- `agentd_common::error::ApiError` for HTTP error responses + +agentd-mcp deviates from this template in several ways, making it the first +service to break the established pattern. This ADR records why those deviations +are intentional and appropriate. + +## Decision Drivers + +- **Client compatibility**: Claude Code and Claude Desktop register MCP servers + via stdio transport in their configuration files. An HTTP-based MCP server + would require a separate proxy or adapter. +- **No persistent state**: agentd-mcp is a pass-through aggregation layer — it + calls existing service REST APIs and returns structured results. There is + nothing to persist locally. +- **Minimal coupling**: agentd-mcp should depend only on `agentd-common` for + shared response types and `reqwest` for HTTP calls — the same dependency + pattern as the CLI. +- **Ecosystem alignment**: The `rmcp` crate is the primary Rust implementation + of the MCP protocol, providing server scaffolding, tool registration, and + schema generation. + +## Options Considered + +### Option A: stdio transport with `rmcp` (pass-through, no storage) + +agentd-mcp is a standalone binary that communicates with MCP clients over +stdin/stdout. It makes HTTP calls to agentd services using `reqwest` and returns +results as MCP tool responses. No port allocation, no database, no migrations. + +- **Pros**: + - Direct compatibility with Claude Code and Claude Desktop configuration + - No port conflicts or allocation bookkeeping + - No storage overhead for a stateless aggregation layer + - Clean separation — agentd-mcp is an external interface, not an internal + service + - Tracing output goes to stderr, keeping stdout clean for MCP protocol +- **Cons**: + - Breaks the standard service template (no port, no storage, no `ApiError`) + - Cannot be health-checked by the existing `agent status` mechanism + - `rmcp` is pre-1.0; API stability is not guaranteed + - Testing requires MCP protocol harness rather than HTTP requests + +### Option B: HTTP server exposing MCP-compatible endpoints + +agentd-mcp runs as a standard HTTP service on a port (e.g., 17007/7007) and +implements MCP tool dispatch over HTTP. An adapter layer translates between +MCP protocol and HTTP. + +- **Pros**: + - Follows the established service template exactly + - Can be health-checked via `GET /health` + - Testing uses standard HTTP client patterns +- **Cons**: + - Claude Code and Claude Desktop don't natively connect to HTTP MCP servers + without an adapter + - Adds an unnecessary network hop and port allocation for a client-side tool + - Would need a stdio wrapper anyway for MCP client registration + - Adds complexity without architectural benefit + +### Option C: Embed MCP tools directly in the CLI + +Instead of a separate crate, add MCP tool definitions to the existing `agent` +CLI binary with a `agent mcp-serve` subcommand. + +- **Pros**: + - No new crate; reuses existing CLI infrastructure + - CLI already has HTTP clients for all services +- **Cons**: + - Bloats the CLI binary with MCP SDK dependencies + - Mixes two distinct interfaces (human CLI and machine MCP) in one binary + - MCP server lifecycle is different from CLI command execution + - Harder to version and deploy independently + +## Decision + +**Chosen**: Option A — stdio transport with `rmcp`, pass-through architecture + +agentd-mcp is a pass-through MCP server that communicates via stdio and calls +existing service REST APIs over HTTP. It has no port allocation, no local +storage, and no database migrations. + +This satisfies the primary driver (Claude Code/Desktop compatibility) while +maintaining minimal coupling to internal services. The deviation from the +standard service template is justified because agentd-mcp is fundamentally a +different kind of component — an external client interface, not an internal +service. + +## Consequences + +**Positive**: +- Zero-config MCP registration in Claude Code (`claude mcp add agentd-mcp`) +- No port conflicts or allocation coordination +- Stateless design means no migration burden and no data consistency concerns +- Clean dependency graph: `agentd-common` + `reqwest` + `rmcp` + +**Negative / Trade-offs**: +- Cannot be monitored via the standard `agent status` health check flow +- `rmcp` pre-1.0 dependency introduces API stability risk; pin to a specific + minor version and track upstream releases +- Integration testing requires an MCP protocol test harness rather than HTTP + assertions +- New contributors must understand that agentd-mcp intentionally does not follow + the standard service template + +**Neutral**: +- 28-tool inventory is large but well-organized into phases; tools can be added + incrementally without architectural changes +- Self-healing tools (Phase 4) have write side-effects; tool descriptions should + include risk-level annotations so MCP clients present appropriate caution + +## Implementation Notes + +- **Crate location**: `crates/mcp/` +- **Binary name**: `agentd-mcp` +- **Dependencies**: `agentd-common` (shared types: `PaginatedResponse`, + `HealthResponse`), `reqwest` (HTTP client), `rmcp` (MCP SDK), `schemars` + (tool parameter schemas), `tokio`, `tracing` +- **Tracing**: Output to stderr via `tracing-subscriber` (stdout is reserved + for MCP protocol). Do NOT call `agentd_common::server::init_tracing()` — + configure a stderr-only subscriber directly. +- **Service URLs**: Resolve from environment variables (`AGENTD_*_SERVICE_URL`) + following the same convention as the CLI and agent configs. +- **Shared types**: Import `PaginatedResponse`, `HealthResponse`, and other + response types from `agentd-common`. Do NOT redefine them in the MCP crate. +- **`rmcp` version strategy**: Pin to `0.16.x` (or current stable minor). + Track the `rmcp` changelog for breaking changes. If `rmcp` proves unstable, + the stdio protocol is simple enough to implement directly as a fallback. +- **Documentation**: Update `docs/public/install.md` to list agentd-mcp + (noting stdio transport, no port). Add MCP client configuration guide as + part of #259. diff --git a/mkdocs.yml b/mkdocs.yml index d1c39acf..ddb34c79 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -117,6 +117,8 @@ nav: - Development: - Error Handling & Logging: public/error-handling.md - Storage Patterns: storage.md + - Architecture Decisions: + - 0001 — agentd-mcp stdio Transport: planning/decisions/0001-agentd-mcp-stdio-transport.md extra: social: From cd63acb6f38940933d55e19c5059fc66b4fa5cba Mon Sep 17 00:00:00 2001 From: Geoff Johnson Date: Mon, 23 Mar 2026 09:32:04 -0700 Subject: [PATCH 3/4] docs: add docker-backend.md to mkdocs nav and prepare for pty backend From 2829dfea880764ef78927056cec73329d41a0ea4 Mon Sep 17 00:00:00 2001 From: Geoff Johnson Date: Mon, 23 Mar 2026 09:32:21 -0700 Subject: [PATCH 4/4] docs: add Execution Backends nav section with docker-backend.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docker-backend.md has existed since the Docker backend shipped but was never added to the mkdocs.yml nav, making it undiscoverable via the docs site. Adds a top-level 'Execution Backends' section with the Docker entry as the first item — structured to receive Tmux and Pty entries when #673 (PtyBackend) lands. --- mkdocs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkdocs.yml b/mkdocs.yml index ddb34c79..fa3e05e4 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -114,6 +114,8 @@ nav: - Conductor Behavior: public/pipeline/conductor.md - Troubleshooting: public/pipeline/troubleshooting.md - Human Approval Gates: planning/autonomous-pipeline-gates.md + - Execution Backends: + - Docker: docker-backend.md - Development: - Error Handling & Logging: public/error-handling.md - Storage Patterns: storage.md