lead-agent-mcp
by JiHungLin
README.md
# Lead Agent MCP Server
A lightweight MCP server that lets distributed AI agent teams query a designated project lead before making design decisions — preventing divergence before it happens.
## Problem
When multiple developers each use their own AI coding agent, every agent builds its own understanding of the project. Without a shared source of truth, agents silently make incompatible design decisions. By the time a code review catches it, the divergence is already expensive to fix.
## How it works
```
Developer's Claude Code (any machine)
│
│ call ask_lead("Should bt-engine be a separate container?", ...)
▼
Lead Agent MCP Server ──────────────────────────────────────────┐
│ │
├── Matching standing decision found → answer immediately │
│ │
└── No match → queue for human review │
│ │
│ Developer's agent polls check_answer(question_id) │
│ and blocks progress until answered │
▼ │
Lead's Web UI (http://localhost:8080) ◄────────────────────────┘
│
├── Review pending questions
├── Write answer → agent unblocks
└── Save as standing decision → future similar questions answered automatically
```
## Installation
```bash
git clone <repo>
cd lead-agent-mcp
pip install -e .
```
## Running the server
```bash
lead-agent \
--workspace /path/to/design-docs \
--name "my-project-lead" \
--mcp-port 8765 \
--ui-port 8080
```
| Flag | Default | Description |
|------|---------|-------------|
| `--workspace` | *(required)* | Primary folder — design docs, specs, any files agents should be able to read |
| `--memory` | — | Extra path to include, namespaced by directory name. Repeatable. See [Syncing Claude memory](#syncing-claude-code-memory) |
| `--name` | `lead-agent` | MCP server name visible to connecting agents |
| `--description` | `Design alignment oracle` | Short description shown in MCP tool discovery |
| `--mcp-port` | `8765` | Port for MCP SSE — agents connect here |
| `--ui-port` | `8080` | Port for Web UI — lead reviews questions here (localhost only) |
| `--host` | `0.0.0.0` | Host to bind the MCP server |
| `--data` | `.data/` | Folder to store the SQLite database |
On startup the server prints the exact config string team members need:
```
────────────────────────────────────────────────────────
my-project-lead
────────────────────────────────────────────────────────
Workspace : /Users/you/design-docs
MCP (SSE) : http://0.0.0.0:8765/sse
Web UI : http://localhost:8080/
────────────────────────────────────────────────────────
Claude Code config for team members:
"url": "http://<your-ip>:8765/sse"
```
## Team member setup
Each developer adds one entry to their `~/.claude/settings.json`:
```json
{
"mcpServers": {
"lead-agent": {
"url": "http://<lead-ip>:8765/sse"
}
}
}
```
The server is then available as an MCP tool in every Claude Code session.
## MCP tools (available to agents)
| Tool | Description |
|------|-------------|
| `ask_lead(question, context, from_agent)` | Ask a design question. Returns an immediate answer if a matching decision exists, otherwise returns `{status: "pending", question_id}` |
| `check_answer(question_id)` | Poll until the lead has answered. Returns `{status: "answered", answer}` or `{status: "pending"}` |
| `list_workspace_docs()` | List all files in the workspace |
| `read_workspace_doc(path)` | Read a workspace file by relative path |
| `search_workspace(query)` | Keyword search across workspace files — returns snippets |
| `list_decisions()` | List all standing decisions (useful for agents to understand existing policy before asking) |
### Recommended agent behavior
```
1. Call list_decisions() and search_workspace(topic) first
→ often the answer is already in a design doc
2. If still uncertain, call ask_lead(...)
→ if status == "answered": proceed with the answer
→ if status == "pending": stop work on this decision,
record the question_id, poll check_answer() periodically
3. Never guess on decisions that cross component boundaries
```
## Web UI
Open `http://localhost:8080` on the lead's machine.
**Queue** — pending questions from agents, sorted by arrival time. Each shows the asking agent's ID, the question, and any context they provided. Click **Reply** to answer.
When answering, you can optionally **Save as standing decision** with a topic label. The next agent asking a similar question will receive the answer automatically without waiting for human review.
**Decisions** — browse and manage all standing decisions. Add new ones manually to pre-answer known policy without waiting for a question to arrive.
## Syncing Claude Code memory
Claude Code stores its cross-session memory in `~/.claude/projects/<encoded-path>/memory/`. These files capture project direction, design decisions, and context built up through your conversations — exactly what team agents should align with.
Pass this path via `--memory` and it becomes available under the `memory/` namespace:
```bash
lead-agent \
--workspace ~/projects/design-docs \
--memory ~/.claude/projects/-home-you-projects-myproject/memory \
--name "my-project-lead"
```
Find your encoded path:
```bash
ls ~/.claude/projects/
```
With this flag active, `list_workspace_docs()` includes `memory/user-preferences.md`, `memory/project-decisions.md`, etc., and `search_workspace("bt-engine")` searches them alongside your design docs.
You can mount multiple extra paths:
```bash
lead-agent \
--workspace ~/design-docs \
--memory ~/.claude/projects/.../memory \
--memory ~/personal-notes/project
```
> **Note**: Memory files contain your personal conversation history with Claude. Only mount paths you're comfortable sharing with the team.
## Architecture
```
lead-agent-mcp/
├── lead_agent/
│ ├── store.py # SQLite — questions & decisions
│ ├── workspace.py # file reader / keyword search
│ ├── mcp_server.py # FastMCP tools (factory pattern, no hardcoded names)
│ ├── web_ui.py # FastAPI web UI
│ ├── main.py # CLI entry point, runs both servers via asyncio
│ └── templates/ # Jinja2 + Bootstrap UI
└── pyproject.toml
```
Both servers (MCP SSE + Web UI) run in the same process via `asyncio.gather`. The MCP server binds to all interfaces by default; the Web UI binds to `127.0.0.1` only.
## Requirements
- Python 3.11+
- Dependencies: `mcp[cli]`, `fastapi`, `uvicorn[standard]`, `jinja2`, `python-multipart`
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues