Skip to content

feat(mcp): add MCP server mode for subagent composition#126

Merged
spachava753 merged 13 commits intomainfrom
issue-112
Jan 10, 2026
Merged

feat(mcp): add MCP server mode for subagent composition#126
spachava753 merged 13 commits intomainfrom
issue-112

Conversation

@spachava753
Copy link
Copy Markdown
Owner

Summary

This PR implements MCP Server Mode, enabling CPE to be exposed as an MCP server. This allows composition of AI agents where CPE subagents can be invoked as tools from parent agents, supporting patterns like context management, parallel execution, and focused task delegation.

Motivation

As agent environments accumulate more MCP servers and tools, context windows become crowded, leading to:

  • More frequent context compaction
  • Increased likelihood of tool call errors
  • Degraded model performance from long contexts

Subagents address this by aggregating tools behind a simpler interface. The parent agent invokes a single subagent tool instead of orchestrating many tools directly, saving context space and reducing complexity. Additionally, subagents enable "parallel intelligence" where multiple focused agents can execute concurrently.

MCP server mode was chosen over a simple CLI wrapper because:

  • Any MCP client can consume it (not just CPE)
  • Supports structured output via schemas
  • Leverages MCP protocol features (logging, notifications)
  • Enables proper rate limiting and retry handling in code mode

Features

  • New cpe mcp serve command: Starts CPE as a long-lived MCP server over stdio
  • Subagent configuration: New subagent config block with name, description, and optional outputSchemaPath
  • Structured output: When outputSchemaPath is set, subagent uses a final_answer tool to return validated JSON
  • Execution context inheritance: Subagents inherit CWD and environment from parent
  • Code mode support: Subagents can have code mode enabled/disabled via defaults.codeMode
  • Trace persistence: Subagent execution traces saved to .cpeconvo with unique run IDs
  • Stdout discipline: MCP protocol output only on stdout; diagnostics go to stderr

Usage

Create a subagent config:

# coder.cpe.yaml
version: "1.0"
subagent:
  name: implement_change
  description: Make code changes and run tests.
defaults:
  model: opus
  systemPromptPath: ./coder.prompt
  codeMode:
    enabled: true

Start as MCP server:

cpe mcp serve --config ./coder.cpe.yaml

Configure parent to use subagent:

# parent.cpe.yaml
mcpServers:
  coder:
    command: cpe
    args: ["mcp", "serve", "--config", "./coder.cpe.yaml"]
    type: stdio

Files Changed

  • cmd/mcp.go: New mcp serve command implementation
  • internal/mcp/server.go: MCP server with tool registration and stdio transport
  • internal/commands/subagent.go: Subagent execution logic with final_answer support
  • internal/config/: Extended config schema for subagent definition
  • internal/agent/input.go: Refactored input processing (extracted from cmd/root.go)
  • examples/subagent/: Example configs, prompts, and schemas
  • docs/specs/mcp_server_mode.md: Full specification document

Closes #112

This specification defines MCP Server Mode, a feature enabling CPE to be exposed as an MCP server for agent composition. The design addresses context window pressure from accumulating tools by allowing focused subagents to handle tool orchestration behind a simple interface.

The specification covers:

- Motivation for subagent patterns including context management, parallel execution, and separation of concerns between planning and execution
- Configuration schema with one subagent per config file for simplicity and version control
- CLI interface via `cpe mcp serve --config` with stdio transport
- Execution model where subagents inherit parent context (CWD, environment)
- Structured output support via optional JSON schemas and final_answer tool
- Conversation persistence with subagent traces annotated in .cpeconvo
- Example configurations for review, coding, and documentation workflows
- Detailed implementation task breakdown with dependencies and testing criteria

The design intentionally omits retry logic, recursion guards, and complex orchestration in favor of transparency and debuggability for the initial implementation.
Extend the configuration schema to support defining subagents that can be
exposed as MCP tools. This is the foundation for MCP server mode, which
allows CPE to run as an MCP server exposing a single focused subagent.

The SubagentConfig struct captures the essential identity of a subagent:
its name and description (both required), plus an optional path to a JSON
schema file for structured output. Validation ensures the output schema
file exists and contains valid JSON when specified.
This implements the MCP server transport layer for CPE, allowing it to be run as an MCP server that exposes a configured subagent as a tool.

The `cpe mcp serve` command starts a server that communicates via stdio transport, enabling CPE to be composed as a subagent within other MCP-compliant environments. The server validates that a subagent is configured and handles graceful shutdown on context cancellation.

Closes Task 2 and Task 3 from the MCP server mode spec.
Implements tool registration for the MCP server mode, allowing the configured subagent to be exposed as an MCP tool that clients can discover and invoke.

The tool is registered with the name and description from the subagent config, and uses a typed input schema with `prompt` (required) and `inputs` (optional file paths). When `outputSchemaPath` is configured, the JSON schema is loaded, validated, and set as the tool's output schema. Invalid schema files (missing or malformed JSON) cause server startup to fail with a clear error message.

The tool handler is a placeholder that returns a not-implemented error; actual subagent execution will be added in a subsequent task.
When the MCP server receives a tool call, it now executes the configured subagent using the same patterns as the root command. The server accepts a `SubagentExecutor` function that handles config resolution, system prompt loading, generator creation, and generation.

The input processing logic that converts file paths and URLs into gai.Blocks has been extracted from `cmd/root.go` into `agent.BuildUserBlocks` so it can be shared with subagent execution. A new `commands.ExecuteSubagent` function provides a simpler single-turn generation interface without conversation state management.

The `baseURLOverride` parameter was removed from `CreateToolCapableGenerator` since custom URLs can be set directly on the model config before calling the function.
Add support for structured output in MCP server mode subagents. When a
subagent configuration includes an outputSchemaPath, the system registers
a final_answer tool with the specified JSON schema as its input schema.
The tool uses a nil callback which causes gai.ToolGenerator to terminate
execution immediately when called, and the tool call parameters are
extracted and returned as the structured JSON result.

The output schema is loaded and validated at server startup to ensure
invalid schema files cause immediate failures rather than runtime errors.
This aligns with the Task 4 spec requirement for startup validation.

Closes Task 6 of the MCP Server Mode specification.
Update Task 6 to reflect actual files modified during implementation.
Remove Task 9 (CLI wiring) as it was completed as part of earlier tasks.
Mark Task 8 (logging notifications) as optional. Renumber remaining
tasks and update their dependencies accordingly.
Subagent invocations now save their execution traces to the shared .cpeconvo
database, enabling conversation history and debugging for MCP server mode.

Each invocation generates a unique 8-character run ID and labels all messages
with the format "subagent:<name>:<run_id>" in the title field. This allows
subagent traces to be distinguished from parent agent entries when viewing
conversation history.

The persistence is non-blocking—storage errors are logged to stderr but do not
fail the subagent execution, prioritizing the primary tool response over
observability.
Task 7 now reflects actual implementation: storage init in cmd/mcp.go,
persistence logic in commands/subagent.go with saveSubagentTrace().

Task 9 (E2E integration) now depends on Task 7 since persistence is part
of the complete execution flow.
Add example subagent configurations demonstrating both supported patterns: a
thinking-focused reviewer subagent with structured JSON output, and a code mode
subagent with filesystem access for making changes.

Create comprehensive documentation covering subagent authoring, configuration
reference, structured output via final_answer, troubleshooting, and usage
patterns for composing subagents with parent CPE sessions.

Closes task #9 in MCP server mode spec.
This implements Task #10 of the MCP server mode spec, adding comprehensive
error handling to ensure subagent execution failures are surfaced clearly
to MCP clients rather than crashing the server process.

The server now recovers from panics in tool call handlers and returns them
as structured MCP error responses. Input validation rejects empty prompts
early. Context cancellation is checked at blocking points to respect
timeouts and cancellation requests. Error messages include actionable
context like file paths, model references, and subagent names to aid
debugging.
MCP server mode uses stdio transport where stdout must contain only JSON-RPC messages. The streaming printer was writing response text to stdout, corrupting the protocol and causing parse errors.

Remove the streaming printer entirely and add a disablePrinting parameter to CreateToolCapableGenerator. MCP server mode passes true to suppress stdout output while interactive CLI retains response printing.

Consolidate MCP server mode documentation into README.md and AGENTS.md, removing the separate docs/subagents.md file. Mark Task 11 (documentation) as complete in the spec.

Fix code generation for tools with multiline descriptions by splitting on newlines and prefixing each line with a comment marker.
@spachava753 spachava753 merged commit a9a05c8 into main Jan 10, 2026
@spachava753 spachava753 deleted the issue-112 branch April 10, 2026 00:23
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.

[Enhancement]: Support running CPE as an MCP Server

1 participant