autogen-mcp
by theodieu
README.md
# autogen-mcp
AutoGen multi-agent conversations as an MCP server for Claude Code. Two
surfaces:
1. **Swarm hierarchy** — persistent sub-agents, each owning one task's
context, with tiered conversation permissions (heavy agents converse
freely; cheap agents route requests through the manager).
2. **Group debates** — ad-hoc autonomous round-robin conversations between
fresh agents.
Transcripts and per-agent logs are stored **per project**: in
`.autogen-swarm/` inside whatever directory the Claude Code session runs in
(override with the `AUTOGEN_MCP_DATA_DIR` env var; falls back to this
project's directory if the cwd isn't writable).
## The hierarchy model
- The **manager** is your `claude-manager` (heavy / GLM-5.2) Claude Code
session — it drives the MCP tools and follows
`~/agent-swarm/manager_prompt.md`.
- **Sub-agents** are persistent AutoGen agents in this server. Each is
registered with a `role` (the task it owns) and keeps its conversation
memory for the whole server session; every exchange is appended to
`.autogen-swarm/agents/<name>.jsonl` in the session's project.
- **Tiers**: `heavy` agents get a server-side `converse` tool and can talk
to any other agent directly. `cheap` agents get no such tool — the server
instructs them to emit `NEED_INFO(<task-or-agent>): <question>` lines,
which `send_message` surfaces as `info_requests` for the manager to relay.
Circular conversations and deep relay chains are blocked server-side.
If `tier` is omitted at registration, the `cheap` model alias defaults to
the cheap tier and everything else to heavy.
## Setup
```bash
cd ~/Documents/projects/claude_code+autogen
uv sync
```
Required environment variables (in the shell that launches Claude Code):
- `ANTHROPIC_API_KEY` — for `anthropic:*` / `opus` participants
- `DEEPINFRA_API_KEY` — for `deepinfra:*` / `heavy` / `cheap` participants
## Registration
The project-scoped `.mcp.json` is already in place — any `claude` session
started in this directory picks up the `autogen-chat` server automatically
(you'll be asked to approve it once).
It is also registered **user-scope (global)** in all three Claude Code
profiles, so it's available from any directory. User-scope config lives in
the profile's config dir, so each profile needs its own registration:
```bash
MCPDIR=~/Documents/projects/claude_code+autogen
# default profile
claude mcp add --scope user autogen-chat -- \
uv run --project "$MCPDIR" python "$MCPDIR/server.py"
# manager / worker profiles (separate CLAUDE_CONFIG_DIR)
CLAUDE_CONFIG_DIR=~/.claude-manager claude mcp add --scope user autogen-chat -- \
uv run --project "$MCPDIR" python "$MCPDIR/server.py"
CLAUDE_CONFIG_DIR=~/.claude-worker claude mcp add --scope user autogen-chat -- \
uv run --project "$MCPDIR" python "$MCPDIR/server.py"
```
Note: `--project` (not `--directory`) matters — it selects this project's
Python environment while preserving the working directory Claude Code
launches the server with, which is what makes per-project log storage work.
## Usage from Claude Code
Just ask in natural language.
Swarm workflow (the manager session does this per its prompt):
> Register a cheap sub-agent `api_task` owning the REST endpoints and a cheap
> sub-agent `db_task` owning the schema. Brief each with its scope and
> acceptance test, then relay any NEED_INFO requests between them.
Group debate:
> Start a conversation between opus and heavy about whether we should migrate
> this repo to a monorepo. 8 rounds. Check on it and summarize when done.
Claude Code will call the tools:
**Swarm hierarchy (persistent sub-agents):**
| Tool | Purpose |
|---|---|
| `register_agent` | Create a persistent sub-agent owning one task (`name`, `model`, `role`, optional `system`/`tier`) |
| `send_message` | Converse with a sub-agent; result includes `info_requests` (NEED_INFO lines to relay) |
| `agent_log` | Read an agent's exchange history (`since` for incremental reads) |
| `list_agents` | Roster with tiers, roles, exchange counts |
| `remove_agent` | Retire an agent (log file survives) |
**Group debates (ad-hoc conversations):**
| Tool | Purpose |
|---|---|
| `start_conversation` | Kick off a background group chat, returns an ID |
| `get_transcript` | Poll new turns (`since_turn` for incremental reads) |
| `inject_message` | Queue a steering message, delivered at the next round boundary |
| `stop_conversation` | Cancel a running chat |
| `list_conversations` | Show all chats in this session |
MCP resources: `conversation://<id>` and `agent://<name>` expose full
transcripts as readable text.
### Model specs
Participants take `"model"` as `<provider>:<model>` or a shorthand alias:
| Alias | Resolves to |
|---|---|
| `opus` | `anthropic:claude-opus-4-8` |
| `heavy` | `deepinfra:zai-org/GLM-5.2` |
| `cheap` | `deepinfra:deepseek-ai/DeepSeek-V4-Flash` |
Any DeepInfra model works via `deepinfra:<org>/<model>` (uses their
OpenAI-compatible endpoint at `api.deepinfra.com/v1/openai`).
## Notes and caveats
- **Which shell you launch from decides which providers work.** The
`claude-cheap`/`claude-heavy`/`claude-manager` aliases blank
`ANTHROPIC_API_KEY`, so from those sessions only DeepInfra participants
(`heavy`, `cheap`, `deepinfra:*`) work — which is all the swarm hierarchy
needs. `opus` / `anthropic:*` participants require a shell with
`ANTHROPIC_API_KEY` set (your plain `claude`). Note the *debate* default
pair includes `opus`, so from an alias shell pass explicit agents to
`start_conversation`. The server pins its base URLs
(`api.anthropic.com` / DeepInfra), so the aliases' `ANTHROPIC_BASE_URL`
override can't misroute requests either way. The server is registered
user-scope in all three profiles, so any session in any directory gets
the tools — and its swarm data lands in that session's own
`.autogen-swarm/`.
- **Conversations and agent memory die with the session.** stdio servers
live as long as the Claude Code session that spawned them. Transcripts
(`.autogen-swarm/transcripts/*.jsonl`) and agent logs
(`.autogen-swarm/agents/*.jsonl`) survive on disk in the session's
project, but in-flight chats and sub-agent conversation memory don't —
after a restart, re-register agents and re-brief them (e.g. paste the
relevant log back as the first message). If you want a long-lived daemon,
switch `mcp.run()` to the streamable-HTTP transport and register the URL
instead.
- **Sub-agents are chat-only.** They think and produce code as text; they
don't touch files. Execution stays with the manager or headless
`claude-cheap-yolo` workers — report outcomes back into the owning
agent's context so it remains the source of truth.
- **Steering granularity is one round.** `inject_message` is delivered at the
next round-robin boundary, not mid-turn.
- **Cost**: `max_rounds` is the guardrail. Two eager models can burn tokens
fast — keep rounds modest and use `cheap` participants for experiments.
TDQS
A3.9/5.0
Scored across 7 tools
Disambiguation5/5
Each tool has a clearly distinct purpose: sending messages, removing agents, starting/stopping conversations, retrieving transcripts, injecting messages, and listing conversations. No overlapping functionality.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern (e.g., send_message, start_conversation, get_transcript) using snake_case throughout.
Tool Count5/5
With 7 tools, the server is well-scoped for multi-agent conversation management. Each tool serves a specific purpose without redundancy or being too thin.
Completeness4/5
Core conversation lifecycle (start, get transcript, inject message, stop) and agent management (remove) are covered. Minor gaps include lacking an explicit 'list agents' tool or ability to modify agent configurations.
Maintenance
ActivityStale
ResponsivenessNo issues