Accept spike 2: MCP HTTP endpoint for workflow and agent tools
Adds POST /mcp endpoint speaking MCP Streamable HTTP (JSON-RPC 2.0) with 12 tools for workflow management and agent orchestration. Supports both JSON and SSE response modes. Includes real-time agent output streaming over SSE, Content-Type validation, and 15 integration tests (134 total). Tools: create_story, validate_stories, list_upcoming, get_story_todos, record_tests, ensure_acceptance, start_agent, stop_agent, list_agents, get_agent_config, reload_agent_config, get_agent_output. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
115
.story_kit/spikes/archive/spike-2-mcp-workflow-tools.md
Normal file
115
.story_kit/spikes/archive/spike-2-mcp-workflow-tools.md
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
name: MCP Server for Workflow API
|
||||
---
|
||||
|
||||
# Spike 1: MCP Server for Workflow API
|
||||
|
||||
## Question
|
||||
|
||||
Can we expose the Story Kit workflow API as MCP tools so that agents call enforced endpoints instead of manipulating files directly?
|
||||
|
||||
## Hypothesis
|
||||
|
||||
A thin stdio MCP server that proxies to the existing Rust HTTP API will let Claude Code agents use `create_story`, `validate_stories`, `record_tests`, and `ensure_acceptance` as native tools — with zero changes to the existing server.
|
||||
|
||||
## Timebox
|
||||
|
||||
2 hours
|
||||
|
||||
## Investigation Plan
|
||||
|
||||
1. Understand the MCP stdio protocol (JSON-RPC over stdin/stdout)
|
||||
2. Identify which workflow endpoints should become MCP tools
|
||||
3. Determine the best language/approach for the MCP server (Rust binary vs Node script vs Rust integrated into existing server)
|
||||
4. Prototype a minimal MCP server with one tool (`create_story`) and test it with `claude mcp add`
|
||||
5. Verify spawned agents (via `claude -p`) inherit MCP tools
|
||||
6. Evaluate whether we can restrict agents from writing to `.story_kit/stories/` directly
|
||||
|
||||
## Findings
|
||||
|
||||
### 1. MCP stdio protocol is simple
|
||||
JSON-RPC 2.0 over stdin/stdout. Three-phase: initialize handshake → tools/list → tools/call. A minimal server needs to handle ~3 message types. No HTTP, no sockets.
|
||||
|
||||
### 2. The `rmcp` Rust crate makes this trivial
|
||||
The official Rust SDK (`rmcp` 0.3) provides `#[tool]` and `#[tool_router]` macros that eliminate boilerplate. A tool is just an async function with typed parameters:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Deserialize, schemars::JsonSchema)]
|
||||
pub struct CreateStoryRequest {
|
||||
#[schemars(description = "Human-readable story name")]
|
||||
pub name: String,
|
||||
#[schemars(description = "User story text")]
|
||||
pub user_story: Option<String>,
|
||||
#[schemars(description = "List of acceptance criteria")]
|
||||
pub acceptance_criteria: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[tool(description = "Create a new story with correct front matter in upcoming/")]
|
||||
async fn create_story(
|
||||
&self,
|
||||
Parameters(req): Parameters<CreateStoryRequest>,
|
||||
) -> Result<CallToolResult, McpError> {
|
||||
let resp = self.client.post(&format!("{}/workflow/stories/create", self.api_url))
|
||||
.json(&req).send().await...;
|
||||
Ok(CallToolResult::success(vec![Content::text(resp.story_id)]))
|
||||
}
|
||||
```
|
||||
|
||||
Dependencies needed: `rmcp` (server, transport-io), `schemars`, `reqwest`, `tokio`, `serde`. We already use most of these in the existing server.
|
||||
|
||||
### 3. Architecture: separate binary, same workspace
|
||||
Best approach is a new binary crate (`story-kit-mcp`) in the workspace that:
|
||||
- Reads the API URL from env or CLI arg (default `http://localhost:3000/api`)
|
||||
- Proxies each MCP tool call to the corresponding HTTP endpoint
|
||||
- Returns the API response as tool output
|
||||
|
||||
This keeps the MCP layer thin and the enforcement logic in the existing server. No code duplication — the MCP binary is just a translation layer.
|
||||
|
||||
### 4. Which endpoints become tools
|
||||
|
||||
| MCP Tool | HTTP Endpoint | Why |
|
||||
|---|---|---|
|
||||
| `create_story` | POST /workflow/stories/create | Enforce front matter |
|
||||
| `validate_stories` | GET /workflow/stories/validate | Check all stories |
|
||||
| `record_tests` | POST /workflow/tests/record | Record test results |
|
||||
| `ensure_acceptance` | POST /workflow/acceptance/ensure | Gate story acceptance |
|
||||
| `collect_coverage` | POST /workflow/coverage/collect | Run + record coverage |
|
||||
| `get_story_todos` | GET /workflow/todos | See remaining work |
|
||||
| `list_upcoming` | GET /workflow/upcoming | See backlog |
|
||||
|
||||
### 5. Configuration via `.mcp.json` (project-scoped)
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"story-kit": {
|
||||
"type": "stdio",
|
||||
"command": "./target/release/story-kit-mcp",
|
||||
"args": ["--api-url", "http://localhost:${STORYKIT_PORT:-3000}/api"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This gets checked into the repo. Every Claude Code session and every spawned agent inherits it automatically.
|
||||
|
||||
### 6. Agent restrictions
|
||||
Claude Code's `.claude/settings.local.json` can restrict which tools agents have access to. We could:
|
||||
- Give agents the MCP tools (`story-kit:create_story`, etc.)
|
||||
- Restrict or remove Write access to `.story_kit/stories/` paths
|
||||
- This forces agents through the API for all workflow actions
|
||||
|
||||
Caveat: tool restrictions are advisory in `settings.local.json` — agents with Bash access could still `echo > file`. Full enforcement requires removing Bash or scoping it (which is story 35's problem).
|
||||
|
||||
### 7. Effort estimate
|
||||
The MCP binary itself is ~200-300 lines of Rust. One afternoon of work. Most of the time would be testing the integration with agent spawning and worktrees.
|
||||
|
||||
## Recommendation
|
||||
|
||||
**Proceed with a story.** The spike confirms this is straightforward and high-value. The `rmcp` crate handles the protocol complexity, and our existing HTTP API already does the enforcement. The MCP server is just plumbing.
|
||||
|
||||
Suggested story scope:
|
||||
1. New `story-kit-mcp` binary crate in the workspace
|
||||
2. Expose the 7 tools listed above
|
||||
3. Add `.mcp.json` to the project
|
||||
4. Update agent spawn to ensure MCP tools are available in worktrees
|
||||
5. Test: spawn agent, verify it uses MCP tools instead of file writes
|
||||
Reference in New Issue
Block a user