Accept story 40: MCP Server Obeys STORYKIT_PORT

Agent worktrees now get a .mcp.json written with the correct port from
the running server. AgentPool receives the port at construction and
passes it through to create_worktree, which writes .mcp.json on both
new creation and reuse.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dave
2026-02-20 13:24:35 +00:00
parent ce37a70f9a
commit a3c20eb4d4
5 changed files with 78 additions and 34 deletions

View File

@@ -111,12 +111,14 @@ fn agent_info_from_entry(story_id: &str, agent: &StoryAgent) -> AgentInfo {
/// Manages concurrent story agents, each in its own worktree.
pub struct AgentPool {
agents: Arc<Mutex<HashMap<String, StoryAgent>>>,
port: u16,
}
impl AgentPool {
pub fn new() -> Self {
pub fn new(port: u16) -> Self {
Self {
agents: Arc::new(Mutex::new(HashMap::new())),
port,
}
}
@@ -188,7 +190,7 @@ impl AgentPool {
});
// Create worktree
let wt_info = worktree::create_worktree(project_root, story_id, &config).await?;
let wt_info = worktree::create_worktree(project_root, story_id, &config, self.port).await?;
// Update with worktree info
{
@@ -696,7 +698,7 @@ mod tests {
#[tokio::test]
async fn wait_for_agent_returns_immediately_if_completed() {
let pool = AgentPool::new();
let pool = AgentPool::new(3001);
pool.inject_test_agent("s1", "bot", AgentStatus::Completed);
let info = pool.wait_for_agent("s1", "bot", 1000).await.unwrap();
@@ -707,7 +709,7 @@ mod tests {
#[tokio::test]
async fn wait_for_agent_returns_immediately_if_failed() {
let pool = AgentPool::new();
let pool = AgentPool::new(3001);
pool.inject_test_agent("s2", "bot", AgentStatus::Failed);
let info = pool.wait_for_agent("s2", "bot", 1000).await.unwrap();
@@ -716,7 +718,7 @@ mod tests {
#[tokio::test]
async fn wait_for_agent_completes_on_done_event() {
let pool = AgentPool::new();
let pool = AgentPool::new(3001);
let tx = pool.inject_test_agent("s3", "bot", AgentStatus::Running);
// Send Done event after a short delay
@@ -741,7 +743,7 @@ mod tests {
#[tokio::test]
async fn wait_for_agent_times_out() {
let pool = AgentPool::new();
let pool = AgentPool::new(3001);
pool.inject_test_agent("s4", "bot", AgentStatus::Running);
let result = pool.wait_for_agent("s4", "bot", 50).await;
@@ -752,14 +754,14 @@ mod tests {
#[tokio::test]
async fn wait_for_agent_errors_for_nonexistent() {
let pool = AgentPool::new();
let pool = AgentPool::new(3001);
let result = pool.wait_for_agent("no_story", "no_bot", 100).await;
assert!(result.is_err());
}
#[tokio::test]
async fn wait_for_agent_completes_on_stopped_status_event() {
let pool = AgentPool::new();
let pool = AgentPool::new(3001);
let tx = pool.inject_test_agent("s5", "bot", AgentStatus::Running);
let tx_clone = tx.clone();