Content
# worktree-mcp
An MCP (Model Context Protocol) server that manages the full lifecycle of git worktrees for multi-agent development workflows.
## Why?
When multiple AI agents work on the same codebase, they need isolation. Git worktrees provide that—each agent gets its own working directory with its own branch. But worktrees alone aren't enough:
- Each worktree needs its own dev server on a unique port
- Environment variables need to be configured per-worktree
- Servers need to start/stop cleanly
- State needs to persist across sessions
**worktree-mcp** handles all of this automatically.
## Features
- **Isolated worktrees** — Each feature branch gets its own directory
- **Automatic port allocation** — No port conflicts between worktrees
- **Dev server management** — Start/stop with health checks
- **Environment generation** — `.env.local` created automatically
- **Lifecycle hooks** — Run setup/teardown commands
- **State persistence** — Survives MCP restarts
- **Workflow prompts** — Guide agents on when/how to use worktrees
## Installation
```bash
npm install -g worktree-mcp
```
Or run directly:
```bash
npx worktree-mcp
```
## Quick Start
### 1. Add to your MCP client
**Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"worktree": {
"command": "npx",
"args": ["worktree-mcp"]
}
}
}
```
**OpenCode** (`~/.config/opencode/config.json`):
```json
{
"mcp": {
"worktree": {
"command": "npx",
"args": ["worktree-mcp"]
}
}
}
```
### 2. Create a config file in your repo
Create `.worktree-agent.yaml` in your repository root:
```yaml
dev:
command: "npm run dev"
port_env: "PORT"
base_port: 3000
```
### 3. Use the tools
```
Agent: "I need to work on feature-x"
→ worktree_create(branch: "feature-x")
→ worktree_start()
# Work happens in .worktrees/feature-x with server on port 3000
Agent: "Done with feature-x"
→ worktree_remove(worktree: "feature-x", mode: "promote")
# Pushes to remote and cleans up
```
## Configuration
Create `.worktree-agent.yaml` in your repository root:
```yaml
# Where to create worktrees (default: .worktrees)
worktree_dir: ".worktrees"
# Main dev server (required)
dev:
command: "npm run dev"
port_env: "PORT" # Env var passed to the process
base_port: 3000 # Starting port for allocation
health_check: "http://localhost:${DEV_PORT}/api/health" # Optional
ready_timeout: 30 # Seconds to wait for health check
# Additional services (optional)
services:
backend:
command: "python manage.py runserver"
port_env: "PORT"
base_port: 8000
health_check: "http://localhost:${BACKEND_PORT}/health"
db:
command: "docker compose up db"
port_env: "DB_PORT"
base_port: 5432
# Environment variables for .env.local
# Available template vars: ${DEV_PORT}, ${BACKEND_PORT}, ${DB_PORT}, ${WORKTREE_NAME}
env:
DATABASE_URL: "postgresql://localhost:${DB_PORT}/app_${WORKTREE_NAME}"
API_URL: "http://localhost:${BACKEND_PORT}"
# Lifecycle hooks
hooks:
post_create: "npm install"
pre_remove: "docker compose down"
# Guidance for AI agents (appears in worktree-workflow prompt)
agent_guidance: |
Always create a worktree for feature work.
Run tests before removing: npm test
```
## MCP Tools
| Tool | Description |
|------|-------------|
| `worktree_create` | Create worktree, allocate ports, generate `.env.local`, run setup hooks |
| `worktree_start` | Start dev server(s) in background, wait for health check |
| `worktree_status` | List all worktrees, ports, and server status |
| `worktree_stop` | Stop servers (keeps worktree intact) |
| `worktree_remove` | Full cleanup with mode options |
### worktree_create
```typescript
worktree_create(branch: string, base?: string)
```
- Creates `.worktrees/<branch>` directory
- Allocates unique ports for each service (increments from `base_port`)
- Generates `.env.local` with port bindings
- Adds `.worktrees/` to `.gitignore` if needed
- Runs `post_create` hook
### worktree_start
```typescript
worktree_start(worktree?: string, service?: string)
```
- Spawns processes in background (detached)
- Injects port via `port_env` environment variable
- Waits for health check (if configured) or fixed timeout
- Tracks PIDs for later cleanup
### worktree_stop
```typescript
worktree_stop(worktree?: string, service?: string)
```
- Sends SIGTERM, then SIGKILL after 5s if needed
- Cleans up PID files
### worktree_remove
```typescript
worktree_remove(
worktree: string,
mode?: "keep_branch" | "delete_branch" | "promote",
force?: boolean
)
```
Modes:
- `keep_branch` (default): Remove worktree, keep branch for later
- `delete_branch`: Remove worktree AND delete the local branch
- `promote`: Push branch to remote first, then remove worktree
### worktree_status
Lists all managed worktrees with:
- Branch name and path
- Allocated ports
- Service status (running/stopped/stale)
- Health check results
## MCP Prompts
### worktree-workflow
Provides workflow guidelines for AI agents. Inject into your system prompt to help agents understand when and how to use worktrees.
Includes:
- When to create worktrees vs. work directly
- Step-by-step workflow
- Quick reference table
- Project-specific guidance from `agent_guidance` in config
## How It Works
### Port Allocation
Each service tracks its own port counter per repository:
```
Worktree 1: dev=3000, backend=8000, db=5432
Worktree 2: dev=3001, backend=8001, db=5433
Worktree 3: dev=3002, backend=8002, db=5434
```
Ports are verified free before assignment.
### State Persistence
State stored in `~/.worktree-mcp/state.json`:
```json
{
"version": 1,
"worktrees": {
"/path/to/repo:feature-x": {
"repoPath": "/path/to/repo",
"worktreePath": "/path/to/repo/.worktrees/feature-x",
"branch": "feature-x",
"ports": { "dev": 3001, "backend": 8001 },
"pids": { "dev": 12345, "backend": 12346 }
}
},
"nextPort": {
"/path/to/repo:dev": 3002,
"/path/to/repo:backend": 8002
}
}
```
File locking prevents race conditions with concurrent MCP instances.
### Environment Generation
`.env.local` is generated with canonical port names:
```bash
# Generated by worktree-mcp
# Worktree: feature-x
# Service ports
DEV_PORT=3001
BACKEND_PORT=8001
DB_PORT=5433
# Custom environment
DATABASE_URL=postgresql://localhost:5433/app_feature-x
API_URL=http://localhost:8001
```
The `port_env` in config controls what env var the **process** receives when spawning. The `.env.local` always uses canonical `SERVICE_PORT` names for consistency.
### Process Management
- Processes spawned detached (`stdio: ignore`, `unref()`)
- PIDs tracked in state and PID files
- Health checks poll until ready or timeout
- Stale processes detected on `worktree_status`
## Multi-Agent Example
```
┌─────────────────────────────────────────────────────────┐
│ Agent 1 (coordinator) │
│ │
│ "Start feature-x in isolation" │
│ → worktree_create(branch: "feature-x") │
│ → worktree_start() │
│ │
│ "Spawn Agent 2 to work on feature-x" │
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Agent 2 (worker) │
│ cwd: /repo/.worktrees/feature-x │
│ Server: http://localhost:3001 │
│ │
│ Makes changes, commits, tests... │
│ │
│ "Done with feature-x" │
│ → worktree_remove(worktree: "feature-x", mode: "promote")│
└─────────────────────────────────────────────────────────┘
```
## Development
```bash
git clone https://github.com/anthropics/worktree-mcp
cd worktree-mcp
# Install dependencies
npm install
# Build
npm run build
# Watch mode
npm run dev
```
## License
MIT