claude-pool-server 0.3.0

MCP server binary for claude-pool
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
# claude-pool-server

MCP server binary for managing Claude slot pools

[![Crates.io](https://img.shields.io/crates/v/claude-pool-server.svg)](https://crates.io/crates/claude-pool-server)
[![Documentation](https://docs.rs/claude-pool-server/badge.svg)](https://docs.rs/claude-pool-server)
[![CI](https://github.com/joshrotenberg/claude-wrapper/actions/workflows/ci.yml/badge.svg)](https://github.com/joshrotenberg/claude-wrapper/actions/workflows/ci.yml)
[![License](https://img.shields.io/crates/l/claude-pool-server.svg)](LICENSE-MIT)

## Overview

`claude-pool-server` is a standalone binary that exposes `claude-pool` as an MCP server over stdio transport. Add it to your `.mcp.json` and interact with slot pools directly from interactive Claude sessions.

Perfect for:
- Delegating work to background Claude slots
- Scaling tasks in parallel
- Long-running analysis jobs
- Budget-aware task orchestration

## Installation

### From crates.io

```bash
cargo install claude-pool-server
```

### From source

```bash
git clone https://github.com/joshrotenberg/claude-wrapper
cargo install --path crates/claude-pool-server
```

Or run directly without installing:

```bash
cargo run -p claude-pool-server -- -n 4 --budget-usd 10.0
```

### Homebrew

```bash
brew tap joshrotenberg/brew
brew install claude-pool-server
```

## Quick Start

```bash
# Start server with 4 slots, $10 budget, Sonnet model
claude-pool-server -n 4 --budget-usd 10.0 --model sonnet
```

Add to `.mcp.json`:

```json
{
  "mcpServers": {
    "claude-pool": {
      "command": "claude-pool-server",
      "args": ["-n", "4", "--budget-usd", "10.0", "--model", "sonnet"]
    }
  }
}
```

Reload your Claude Code session to enable the server.

### Verify it works

After reloading, run a quick smoke test from your Claude session:

```
# Check the pool is running
@mcp pool_status

# Run a simple task
@mcp pool_run prompt: "say hello"
```

`pool_status` should show your slots in `idle` state. `pool_run` should return a response with output and spend information.

## CLI Flags

### Slot Configuration

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `-n, --slots` | `NUMBER` | 2 | Number of slots to spawn |
| `--model` | `STRING` | - | Default model for all slots (e.g. `sonnet`, `opus`) |

### Default Settings

| Flag | Type | Description |
|------|------|-------------|
| `--effort` | `LEVEL` | Default effort: min, low, medium, high, max |
| `--system-prompt` | `TEXT` | System prompt for all slots |
| `--permission-mode` | `MODE` | default, acceptEdits, bypassPermissions, plan, auto (default: plan) |

### Budget Control

| Flag | Type | Description |
|------|------|-------------|
| `--budget-usd` | `AMOUNT` | Total budget cap in USD (e.g. 10.0) |

### Scaling Bounds

| Flag | Type | Default | Description |
|------|------|---------|-------------|
| `--min-slots` | `NUMBER` | 1 | Minimum slots (floor for `pool_scale_down`) |
| `--max-slots` | `NUMBER` | 16 | Maximum slots (ceiling for `pool_scale_up`) |

### Advanced Options

| Flag | Type | Description |
|------|------|-------------|
| `-w, --worktree` | - | Enable Git worktree isolation per slot |
| `--no-builtins` | - | Disable built-in skills (code_review, refactor, etc.) |

### Examples

```bash
# 8 slots, $50 budget, high effort
claude-pool-server -n 8 --budget-usd 50 --effort high

# Lightweight setup with worktree isolation
claude-pool-server -n 2 --budget-usd 5.0 --worktree

# Custom system prompt
claude-pool-server -n 4 --system-prompt "You are a Rust expert. Focus on idiomatic code."

# Plan mode (no auto-execution, requires approval)
claude-pool-server -n 4 --permission-mode plan
```

## .mcp.json Configuration

Full example with all options:

```json
{
  "mcpServers": {
    "claude-pool": {
      "command": "claude-pool-server",
      "args": [
        "-n", "4",
        "--budget-usd", "20.0",
        "--model", "sonnet",
        "--effort", "high",
        "--permission-mode", "plan"
      ],
      "env": {
        "RUST_LOG": "info"
      }
    }
  }
}
```

## MCP Tools

All tools are async and return JSON results.

### Task Execution

#### pool_run

Execute a task synchronously (wait for completion):

```
Prompt: Execute this task and wait for result
@mcp pool_run prompt: "write a haiku about rust"

Returns: { output: "...", spend_usd: 0.15, tokens_used: { input: 50, output: 20 } }
```

Parameters:
- `prompt` (string, required) - The task to execute

Response includes:
- `output` - Claude's response
- `spend_usd` - Cost of this task
- `tokens_used` - Input and output tokens

#### pool_submit

Submit a task asynchronously (returns immediately with task ID):

```
@mcp pool_submit prompt: "long-running analysis"

Returns: { task_id: "task_abc123" }
```

Parameters:
- `prompt` (string, required) - The task to submit

#### pool_result

Retrieve result by task ID:

```
@mcp pool_result task_id: "task_abc123"

Returns: { output: "...", spend_usd: 0.15, status: "completed" }
```

Parameters:
- `task_id` (string, required) - Task ID from pool_submit

#### pool_cancel

Cancel a pending or running task:

```
@mcp pool_cancel task_id: "task_abc123"

Returns: { status: "cancelled" }
```

Parameters:
- `task_id` (string, required) - Task ID to cancel

### Parallel Execution

#### pool_fan_out

Execute multiple prompts in parallel:

```
@mcp pool_fan_out prompts: ["write a poem", "write a haiku", "write a limerick"]

Returns: [
  { output: "Roses are red...", spend_usd: 0.10 },
  { output: "A haiku here...", spend_usd: 0.08 },
  { output: "A limerick...", spend_usd: 0.12 }
]
```

Parameters:
- `prompts` (array of strings, required) - Tasks to execute in parallel

All tasks run concurrently. Returns when all complete.

### Sequential Chains

#### pool_chain

Execute a sequential pipeline synchronously:

```
@mcp pool_chain steps: [
  { prompt: "analyze the error" },
  { prompt: "write a fix" },
  { prompt: "write tests" }
]

Returns: { final_output: "...", steps: [...], total_spend: 0.45 }
```

Parameters:
- `steps` (array, required) - Steps to execute in order
  - `prompt` (string) - The step task
  - `failure_policy` (string, optional) - retry, skip, or abort (default: abort)

#### pool_submit_chain

Submit a chain for async execution:

```
@mcp pool_submit_chain steps: [...]

Returns: { chain_id: "chain_xyz789" }
```

#### pool_chain_result

Get chain progress and results:

```
@mcp pool_chain_result chain_id: "chain_xyz789"

Returns: {
  status: "in_progress",
  completed_steps: 1,
  total_steps: 3,
  current_step: { name: "write a fix", status: "running" },
  steps: [...]
}
```

### Context Management

Share key-value data with all slots (injected into system prompts).

#### context_set

Inject a key-value pair:

```
@mcp context_set key: "language" value: "rust"
@mcp context_set key: "framework" value: "tokio"

Returns: { key: "language", value: "rust" }
```

#### context_get

Retrieve a value:

```
@mcp context_get key: "language"

Returns: { value: "rust" }
```

#### context_list

List all context keys:

```
@mcp context_list

Returns: {
  language: "rust",
  framework: "tokio",
  style: "idiomatic"
}
```

#### context_delete

Remove a context key:

```
@mcp context_delete key: "framework"

Returns: { deleted: true }
```

### Slot Management

#### pool_status

Get current pool state:

```
@mcp pool_status

Returns: {
  slots: [
    { id: "slot-0", status: "idle", active_tasks: 0 },
    { id: "slot-1", status: "busy", active_tasks: 1 }
  ],
  active_tasks: 1,
  pending_tasks: 3,
  spend_usd: 2.50,
  budget_usd: 10.0,
  budget_remaining: 7.50
}
```

#### pool_drain

Graceful shutdown (cancel pending tasks, wait for active tasks):

```
@mcp pool_drain

Returns: {
  total_tasks: 15,
  completed: 12,
  errors: 1,
  total_spend: 3.45
}
```

### Dynamic Scaling

Grow or shrink the pool at runtime. Bounded by `--min-slots` and `--max-slots`.

#### pool_scale_up

Add slots to the pool:

```
@mcp pool_scale_up count: 2

Returns: { success: true, new_slot_count: 6, details: "Scaled up by 2 slots" }
```

Parameters:
- `count` (number, required) - Number of slots to add

Fails if the new total would exceed `--max-slots`.

#### pool_scale_down

Remove slots from the pool (idle slots first):

```
@mcp pool_scale_down count: 2

Returns: { success: true, new_slot_count: 2, details: "Scaled down by 2 slots" }
```

Parameters:
- `count` (number, required) - Number of slots to remove

Busy slots are given 30 seconds to finish before removal. Fails if the new total would drop below `--min-slots`.

#### pool_set_target_slots

Set the pool to an exact size, scaling up or down as needed:

```
@mcp pool_set_target_slots target: 8

Returns: { success: true, new_slot_count: 8, target: 8 }
```

Parameters:
- `target` (number, required) - Desired number of slots

### Skills

Skills are reusable task templates with argument validation.

#### pool_skill_run

Execute a named skill:

```
@mcp pool_skill_run skill: "code_review" arguments: { path: "src/main.rs", criteria: "bugs" }

Returns: { output: "Review findings...", spend_usd: 0.20 }
```

Parameters:
- `skill` (string, required) - Skill name
- `arguments` (object, optional) - Skill arguments by name

## MCP Resources

Access pool state and task details via resources.

| Resource | Description |
|----------|-------------|
| `pool://status` | Current pool state (slots, tasks, spend) |
| `pool://slots` | List of all slots |
| `pool://slots/{id}` | Single slot details by ID |
| `pool://budget` | Budget info (total, spent, remaining) |
| `pool://context` | All context key-value pairs |
| `pool://results/{task_id}` | Task result by ID |
| `pool://chains/{chain_id}` | Chain progress and results |

## Usage Patterns from Claude

### Example 1: Parallel Code Review

```
I need to review 3 files in parallel.

Use pool/fan-out to review them:
@mcp pool_fan_out prompts: [
  "Review src/main.rs for bugs",
  "Review src/lib.rs for style",
  "Review src/error.rs for clarity"
]

Then summarize:
@mcp pool_run prompt: "Summarize the reviews"
```

### Example 2: Sequential Workflow

```
Let's implement and test a feature:

@mcp pool_chain steps: [
  { prompt: "Implement login feature in src/auth.rs" },
  { prompt: "Write integration tests for authentication" },
  { prompt: "Review code for security issues" }
]
```

### Example 3: Async Long-Running Task

```
Start a long analysis:
@mcp pool_submit prompt: "Analyze entire codebase for refactoring opportunities"

# ... do other work ...

Check progress:
@mcp pool_status

Get result:
@mcp pool_result task_id: "task_abc123"
```

### Example 4: Budget-Aware Work

```
Set context for all slots:
@mcp context_set key: "budget_constraint" value: "optimize for cost"

Then submit work:
@mcp pool_run prompt: "Write a minimal test suite"
```

## Built-in Skills

Pre-registered skills available by default (unless `--no-builtins`):

- **code_review** - Review code for bugs, style, and clarity
- **write_tests** - Generate tests for code
- **refactor** - Refactor code for clarity and performance
- **summarize** - Summarize text or code

Use with `pool_skill_run`.

## Troubleshooting

### Server Won't Start

**"command not found: claude-pool-server"**
- Ensure installation: `cargo install claude-pool-server`
- Or run from source: `cargo run -p claude-pool-server -- ...`

**"claude: command not found"**
- Install Claude CLI: https://claude.ai/download
- Or specify path: needs investigation

### Slots Not Responding

Check slot status:
```
@mcp pool_status
```

If slots are offline, restart the server.

### Budget Exceeded

Tasks are rejected when budget cap is reached:
```
@mcp pool_status
# Check budget_remaining

# Increase budget:
# Restart server with larger --budget-usd
```

### High Latency

Consider:
- Reducing slot count (fewer concurrent tasks)
- Increasing timeout settings
- Using async submission for non-urgent tasks

## Performance Tuning

### Slot Count

- **2 slots** - Light tasks, minimal resource usage
- **4 slots** - Balanced for typical workflows
- **8+ slots** - Heavy parallelization, requires higher budget

### Effort Level

- `low` - Fast responses, fewer resources
- `medium` - Balanced speed and quality (default)
- `high` - Thorough analysis, higher cost

### Worktree Isolation

`--worktree` adds overhead but enables safe parallel file edits.

## Multi-Slot Coordination

When running parallel chains or multiple slots on the same repo, coordination prevents conflicts and ensures clean handoffs.

### Enable Worktree Isolation

For any workflow that chains multiple steps across different slots (e.g. plan → code → review → PR), **always use worktree isolation**:

```bash
claude-pool-server -n 4 --worktree
```

Each slot gets an isolated git worktree. Without this, concurrent `git checkout` and `git branch` operations interfere with each other, causing PRs to land on wrong branches and requiring manual cleanup.

### Branch Best Practices

When chains create PRs, follow these patterns:

1. **Fresh main** - Fetch `origin/main` at chain start, branch from it (not stale local main)
2. **Issue reference** - Include issue number in branch name: `feat/add-foo-#42`
3. **Clear scope** - One issue per chain. Parallel chains on different issues won't conflict

### Conflict Handling

When parallel PRs edit the same files, Git flags them as conflicting:
- Second PR to merge needs a rebase
- Recovery: Run `git rebase origin/main` and resolve conflicts
- Consider monitoring with `/loop 3m check PR conflicts` to surface issues early

For strategies beyond worktree isolation (conflict awareness, branch automation, recovery prompts), see issue [#34](https://github.com/joshrotenberg/claude-wrapper/issues/34).

## License

MIT OR Apache-2.0