feat(control-plane): embedded MCP server at /mcp (zero-setup harness integration)#817
Open
AbirAbbas wants to merge 5 commits into
Open
feat(control-plane): embedded MCP server at /mcp (zero-setup harness integration)#817AbirAbbas wants to merge 5 commits into
AbirAbbas wants to merge 5 commits into
Conversation
Introduce MCPConfig under features with an IsEnabled() default of true so the embedded MCP server ships on by default. AGENTFIELD_MCP_ENABLED=false flips it off via the existing env-override precedence path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a stateless streamable-HTTP JSON-RPC 2.0 handler that exposes AgentField discovery and execution as MCP tools, calling the existing service layer directly (no loopback HTTP). Supports initialize, notifications, ping, tools/list and tools/call; rejects batch arrays; unknown methods return -32601. Five tools: discover_agents, get_reasoner_schema, execute_reasoner (starts an async run), get_run, and wait_run (server-side poll with a hard timeout cap so a tool call can never hang a harness). Results are single compact-JSON text content blocks; validation/business failures come back as isError tool results rather than transport errors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Register the embedded MCP server on the same Gin router as the REST API: POST /mcp (JSON-RPC), GET /mcp -> 405, OPTIONS /mcp -> 204. The route is gated by AGENTFIELD_MCP_ENABLED and simply not registered (so /mcp 404s) when disabled. It lives behind the same global API-key auth and trust domain as /api/v1 — no extra process, no extra setup; harnesses connect with one command. Thread the build version through server.SetBuildVersion so the MCP serverInfo reports the real control-plane version. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add an "MCP (zero-setup)" section near the top of the agentfield-use skill (both the repo copy and the embedded skill_data copy, kept identical): the control plane serves MCP at <server>/mcp, with the one-liner claude mcp add command and a generic streamable-HTTP note for other clients. The CLI/REST flow remains the documented full-power path. Bump the skill version to 0.4.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add docs/mcp-integration.md covering the endpoint, the five tools, the security posture (same trust domain and API-key auth as the REST API), the disable flag, and an example tool-call flow. Link it from the README feature table. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
📊 Coverage gateThresholds from
✅ Gate passedNo surface regressed past the allowed threshold and the aggregate stayed above the floor. |
Contributor
📐 Patch coverage gateThreshold: 80% on lines this PR touches vs
✅ Patch gate passedEvery surface whose lines were touched by this PR has patch coverage at or above the threshold. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
AgentField had no MCP server — the only way for an AI harness to drive installed
agents was the
afCLI plus theagentfield-useskill. This PR ships anMCP server embedded in the control plane itself, served on the same port as
the REST API. Whether the control plane was started by the CLI (
af server)or the desktop app, MCP is just there — zero extra processes, zero setup. A
harness connects with one command:
It is on by default, with an env kill-switch:
AGENTFIELD_MCP_ENABLED=falsemakes
/mcpreturn404. The endpoint sits behind the same global API-key authand trust domain as
/api/v1, and the tools call the existing discovery /execution service layer directly (no loopback HTTP).
POST /mcp(stateless;Mcp-Session-Id/MCP-Protocol-Versionheaders tolerated and ignored).GET /mcp→ 405,OPTIONS /mcp→ 204.The five tools
discover_agentshealth:"all"includes unhealthy.get_reasoner_schemaexecute_reasonernode.reasonerexists, start an async run, return{run_id, status:"accepted"}.get_runwait_runtimed_outflag.Validation Contract → tests
initializereturns protocolVersion + capabilities.tools + serverInfo →TestMCP_InitializeAndToolsList(also asserts unknown protocol falls back to2025-06-18and serverInfo carries the build version).tools/listreturns exactly the 5 tools, each with a valid JSON Schema →TestMCP_InitializeAndToolsList.discover_agentsdefault returns only active agents;health:"all"includesdead ones with
health_status→TestMCP_DiscoverAgents.execute_reasonerbad/malformed target → tool error namingdiscover_agents;good target →
run_idand a created execution →TestMCP_ExecuteReasoner.get_runaggregates status/result/error + per-execution summaries →TestMCP_GetRun.wait_runrespects the timeout cap and returnstimed_outon a never-finishingrun (and returns immediately for a terminal run) →
TestMCP_WaitRun.-32601; unknown tool →-32602; batch arrays rejected →TestMCP_ProtocolMiscMethods.AGENTFIELD_MCP_ENABLED=false→/mcpis404; default → enabled;GET /mcp→ 405 →TestMCPRoutes_DisabledReturns404,TestMCPRoutes_EnabledByDefault.TestMCPConfig_IsEnabledDefault,TestApplyEnvOverrides_MCPEnabled.Test results
go build ./...— cleango vet ./internal/config/... ./internal/handlers/... ./internal/server/...— cleango testfor the config, handlers, server (MCP) and skillkit packages — all passgofmt -lon changed files — emptygolangci-lint— no issues in any changed/new fileOne pre-existing, environment-specific test (
TestStartAndStopCoverAdditionalBranches,admin gRPC listener bind) fails identically on clean
origin/mainin this sandboxand is unrelated to this change.
🤖 Generated with Claude Code