# Skill: Expose a Pipeline via MCP

Use when you want your pipeline accessible from Claude Desktop, Claude Code, or any
MCP-compatible client — without HTTP, without curl, via natural language tool calls.

## How MCP Works in This Framework

`arccrew/mcp_server.py` reads the `_PIPELINE_FACTORIES` dict and exposes:

1. **`run_pipeline`** — generic tool, takes `pipeline` name + `tasks` list
2. **`run_{pipeline_name}`** — one dedicated tool per registered pipeline (easier to discover)
3. **`list_pipelines`** — shows all registered pipelines

The server runs over stdio (standard MCP transport), which is how Claude Desktop and other
MCP clients communicate with local tools.

## Step 1 — Register in `pipeline.py`

When `arccrew serve-mcp` starts, it auto-loads `pipeline.py` from the project root.
Add `register_pipeline()` at the bottom of your `pipeline.py`:

```python
from arccrew.mcp_server import register_pipeline

register_pipeline("my_pipeline", create_my_pipeline)
```

Do NOT modify `arccrew/mcp_server.py` — it is a library file.

The name passed to `register_pipeline` becomes the tool name in MCP:
- `"my_pipeline"` → tool `run_my_pipeline` and available as value in `run_pipeline`

## Step 2 — Configure `mcp.json`

A template exists at `mcp.json.example`:

```json
{
  "_comment": "Copy this to .cursor/mcp.json or add to Claude Desktop config.",
  "mcpServers": {
    "my-agents": {
      "command": "arccrew",
      "args": ["serve-mcp"],
      "cwd": "/absolute/path/to/your/project",
      "env": {
        "ANTHROPIC_API_KEY": "your-key-here"
      }
    }
  }
}
```

For **Claude Desktop**: add the `mcpServers` block to your Claude Desktop config file
(location: `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS).

For **Cursor or other MCP clients**: copy to `.cursor/mcp.json` in your project:

```bash
cp mcp.json.example .cursor/mcp.json
# Then edit .cursor/mcp.json:
# - Replace /absolute/path/to/your/project with the actual path
# - Replace your-key-here with your actual API key
# - Or remove the env section if your key is already in .env / os.environ
```

## Step 3 — Start the MCP Server

```bash
arccrew serve-mcp
```

This starts the stdio MCP server. Claude Desktop and other MCP clients will restart it
automatically when needed — you do not need to keep this terminal open.

## How to Invoke from Claude Desktop

Once configured, you can ask Claude in natural language:

```
Run the my_pipeline pipeline with task: Research the latest trends in AI regulation

Run the researcher_writer pipeline with tasks: Research quantum computing breakthroughs

What pipelines are available?
```

Claude Desktop will call the appropriate MCP tool. The pipeline runs and returns results
directly in the chat.

You can also be explicit about tool calls:
```
Use the run_my_pipeline MCP tool with tasks: [{"description": "Analyze competitor pricing"}]
```

## Verifying It Works

### Check Tool List

1. Open Claude Desktop
2. Start a new conversation — MCP tools appear automatically if configured correctly
3. You should see `run_pipeline`, `run_my_pipeline`, `list_pipelines` available

If tools are not showing:
1. Check that the MCP config file is in the right location
2. Check that `cwd` in the config points to the correct project directory
3. Check that `arccrew serve-mcp` runs without errors in that directory
4. Restart Claude Desktop

### Test Manually

```bash
# Verify the MCP server starts and lists tools
arccrew serve-mcp &
sleep 1
# The server is running on stdio — MCP clients connect to it automatically
```

### Check Registered Pipelines

```bash
python -c "
from arccrew.mcp_server import _PIPELINE_FACTORIES
print('Registered:', list(_PIPELINE_FACTORIES.keys()))
"
```

## How Pipelines Are Invoked via MCP

`arccrew/mcp_server.py` builds the LangGraph initial state with the same shape as
`arccrew/api/app.py`:

```python
{
    "messages": [],
    "tasks": tasks,           # from MCP tool call arguments
    "current_task_index": 0,
    "context": {},
    "result": {},
    "results": [],
    ...
    "dry_run": options.get("dry_run", False),
    "workspace_dir": options.get("workspace_dir", settings.workspace_dir),
}
```

The pipeline runs `graph.ainvoke(state)` and returns:

```json
{
  "pipeline": "my_pipeline",
  "task_count": 1,
  "results": [{"task_index": 0, "summary": "...", "files_created": [...]}],
  "status": "completed"
}
```

## MCP vs API

| Feature | MCP (`serve-mcp`) | API (`serve`) |
|---------|-------------------|---------------|
| Transport | stdio | HTTP |
| Client | Claude Desktop / MCP clients | curl / any HTTP client |
| Authentication | OS-level (process launch) | Optional JWT |
| Streaming | No (returns when complete) | SSE / WebSocket |
| Use case | Interactive AI assistant use | Programmatic integration |

Use MCP for interactive use in Claude Desktop or other AI assistants. Use the API for production integrations.

## Environment Variables for MCP

The MCP server inherits the environment from its launch process. In `mcp.json`, you can
pass environment variables that the server needs:

```json
{
  "mcpServers": {
    "my-agents": {
      "command": "arccrew",
      "args": ["serve-mcp"],
      "cwd": "/path/to/project",
      "env": {
        "ANTHROPIC_API_KEY": "sk-ant-...",
        "AGENT_MODEL": "anthropic/claude-haiku-4-5-20251001",
        "WORKSPACE_DIR": "/tmp/mcp_workspace"
      }
    }
  }
}
```

Alternatively, if your `.env` file is in `cwd`, it will be loaded automatically by
`pydantic-settings` when `get_settings()` is called.
