# Skill: Configure MCP Tool Servers

Use when you want agents to call external services via MCP — GitHub, Notion, Slack,
custom MCP servers, or any other MCP-compatible tool provider.

## What this does

arccrew agents normally use `web_search` and workspace tools. With MCP support,
any MCP server becomes a tool your agents can call during their ReAct loop.

```python
# Before: agents limited to built-in tools
tools = get_research_tools()

# After: agents can call any MCP server
tools = get_research_tools() + await get_mcp_tools({
    "github": {
        "transport": "sse",
        "url": "https://api.githubcopilot.com/mcp/",
        "headers": {"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}"},
    }
})
```

## Install

```bash
pip install "arccrew[mcp]"
```

Add to `requirements.txt`:
```
arccrew[mcp]
```

## The `get_mcp_tools()` function

```python
from arccrew.tools import get_mcp_tools

tools = await get_mcp_tools(
    servers={
        "server_name": {
            "transport": "sse" | "http" | "stdio",
            # ... connection details
        }
    },
    prefix_tool_names=True,  # default: True — avoids naming conflicts
)
```

Returns a `list[BaseTool]` — add to any `run_react()` call.

## Transport types

### SSE (Server-Sent Events) — most common for remote servers

```python
{
    "transport": "sse",
    "url": "https://mcp.example.com/sse",
    "headers": {"Authorization": "Bearer your-token"},
}
```

Use for: hosted MCP services (GitHub, Notion, Slack, etc.)

### HTTP (Streamable HTTP) — modern remote servers

```python
{
    "transport": "http",
    "url": "http://localhost:8000/mcp",
}
```

Use for: servers that implement the MCP HTTP transport spec.

### Stdio — local processes

```python
{
    "transport": "stdio",
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"],
}
```

Use for: local MCP servers running as subprocesses (dev, testing).

## Full agent example

```python
# agents/github_agent.py
import os
from pathlib import Path
from langgraph.types import Command
from arccrew import BaseAgent, track_timing
from arccrew.tools import get_mcp_tools

GITHUB_MCP = {
    "transport": "sse",
    "url": "https://api.githubcopilot.com/mcp/",
    "headers": {"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}"},
}

class GitHubAgent(BaseAgent):
    def __init__(self):
        super().__init__(name="github_agent", prompts_dir=Path("prompts"))

    @property
    def system_prompt(self) -> str:
        return self.get_prompt_manager().assemble_prompt("github_agent")

    @track_timing
    async def execute(self, state: dict) -> Command:
        tasks = state.get("tasks", [])
        idx = state.get("current_task_index", 0)
        task = tasks[idx].get("description", "") if idx < len(tasks) else ""

        tools = await get_mcp_tools({"github": GITHUB_MCP})

        result = await self.run_react(task=task, tools=tools)
        data = self.extract_json(result) or {"raw": result}
        return Command(goto="__end__", update={
            "result": data,
            "results": [{"task_index": idx, **data}],
        })
```

## Multiple MCP servers

```python
tools = await get_mcp_tools({
    "github": {
        "transport": "sse",
        "url": "https://api.githubcopilot.com/mcp/",
        "headers": {"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}"},
    },
    "notion": {
        "transport": "sse",
        "url": "https://mcp.notion.com/sse",
        "headers": {"Authorization": f"Bearer {os.getenv('NOTION_TOKEN')}"},
    },
    "slack": {
        "transport": "sse",
        "url": "https://mcp.slack.com/sse",
        "headers": {"Authorization": f"Bearer {os.getenv('SLACK_BOT_TOKEN')}"},
    },
})
```

`prefix_tool_names=True` (default) prevents naming conflicts: tools will be named
`github_search`, `notion_query`, `slack_post` instead of just `search`, `query`, `post`.

## Combining with built-in tools

```python
from arccrew.tools import get_research_tools, create_workspace_tools, get_mcp_tools

tools = (
    get_research_tools()                        # web_search
    + create_workspace_tools(workspace_path)    # file/shell
    + await get_mcp_tools({"github": GITHUB_MCP})  # MCP tools
)
result = await self.run_react(task=task, tools=tools)
```

## Agent prompt — reference MCP tools explicitly

Tools not mentioned in the prompt will be ignored by the LLM.
Always name each MCP tool and describe when to use it:

```markdown
# GitHub Agent

Search and analyze GitHub repositories.

## Instructions

1. Use `github_search_repositories` to find relevant repos by topic
2. Use `github_get_file_contents` to read specific files
3. Use `github_list_issues` to check open issues

## Output Format

{"repos": [...], "analysis": "..."}
Output ONLY the JSON object.
```

## API keys — add to .env

MCP tool auth tokens belong in `.env`, not in code:

```bash
# .env
GITHUB_TOKEN=github_pat_...
NOTION_TOKEN=secret_...
SLACK_BOT_TOKEN=xoxb-...
```

Access in agent code via `os.getenv()`:
```python
import os
headers = {"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}"}
```

## Stateless vs stateful sessions

`get_mcp_tools()` uses **stateless sessions** — each tool call opens a fresh connection.
This is correct for most use cases and required for concurrent agent execution.

For servers that need to maintain state across multiple tool calls within a single
agent run (e.g. a database connection that tracks a transaction), use
`MultiServerMCPClient` directly:

```python
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain_mcp_adapters.tools import load_mcp_tools

client = MultiServerMCPClient(connections={"db": DB_CONFIG})
async with client.session("db") as session:
    tools = await load_mcp_tools(session)
    result = await self.run_react(task=task, tools=tools)
```

## Common MCP servers

| Service | Transport | URL pattern |
|---------|-----------|-------------|
| GitHub Copilot | SSE | `https://api.githubcopilot.com/mcp/` |
| Notion | SSE | `https://mcp.notion.com/sse` |
| Slack | SSE | varies by deployment |
| Filesystem (local) | stdio | `npx @modelcontextprotocol/server-filesystem` |
| Postgres (local) | stdio | `npx @modelcontextprotocol/server-postgres` |
| Custom arccrew server | HTTP | `http://localhost:8000/mcp` |

Check the [MCP servers directory](https://github.com/modelcontextprotocol/servers) for more.
