Skip to main content
Glama
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`