内容
# LLM 委员会 — MCP服务器
MCP服务器(模型上下文协议),允许 Claude Code / Claude Desktop 查询的不是一个模型,而是**多个 LLM 组成的委员会**。问题会同时发送给多个模型,它们会匿名地对彼此的答案进行排名,而主席模型则会综合最终答案。
输出结果是一个经过充分验证的答案。同时,整个讨论过程(模型的答案、peer 排名、置信度信号)都可用于分析。
![llm-council 工作原理:问题发送给多个 LLM 委员会(阶段 1),模型匿名地对彼此的答案进行排名,如 Response A–F(阶段 2),如果出现分歧,则会发出低置信度信号,然后主席从另一个模型家族中综合最终答案,并附上属性 [A]/[B](阶段 3)](docs/demo.gif)
---
## 快速入门(约 3 分钟)
**要求:** [uv](https://docs.astral.sh/uv/) (`brew install uv`), Python ≥ 3.10, [OpenRouter](https://openrouter.ai/keys) 密钥。
```bash
# 1. 获取代码
git clone https://github.com/azalio/llm-council.git
cd llm-council
# 2. 安装依赖(MCP 服务器安装在这里)
uv sync
# 3. 配置访问权限
cp .env.example .env
# 然后编辑 .env 文件:设置密钥:
# OPENROUTER_API_KEY=...
# 4. 检查服务器是否启动(按 Ctrl-C 停止)
uv run mcp_server/server.py
```
接下来,在 MCP 客户端(如下)注册服务器并询问:
*「询问委员会:…」*。
> 服务器从项目根目录读取 `.env` 文件,因此在配置 MCP 客户端时无需重复令牌。
---
## 在 MCP 客户端注册
### Claude Code
使用单个命令(用户范围):
```bash
claude mcp add llm-council -- uv --directory /path/to/llm-council run mcp_server/server.py
```
… 或者手动在 `~/.claude.json` / 项目 `.mcp.json` 中:
```json
{
"mcpServers": {
"llm-council": {
"command": "uv",
"args": ["--directory", "/path/to/llm-council", "run", "mcp_server/server.py"]
}
}
}
```
### Claude Desktop
在 `claude_desktop_config.json` 中添加(设置 → 开发者 → 编辑配置):
```json
{
"mcpServers": {
"llm-council": {
"command": "uv",
"args": ["--directory", "/path/to/llm-council", "run", "mcp_server/server.py"]
}
}
}
```
如果不想使用 `.env` 文件,可以直接在配置中传递访问权限:
```json
{
"mcpServers": {
"llm-council": {
"command": "uv",
"args": ["--directory", "/path/to/llm-council", "run", "mcp_server/server.py"],
"env": { "OPENROUTER_API_KEY": "sk-or-v1-..." }
}
}
}
```
将 `/path/to/llm-council` 替换为克隆存储库的路径。
### Codex
在 `~/.codex/config.toml` 中添加:
```toml
[mcp_servers.llm-council]
command = "uv"
args = ["--directory", "/path/to/llm-council", "run", "mcp_server/server.py"]
startup_timeout_sec = 60
tool_timeout_sec = 3600 # 委员会需要较长时间 - 默认 Codex 超时时间不够
[mcp_servers.llm-council.env]
OPENROUTER_API_KEY = "sk-or-v1-..."
```
如果没有 `tool_timeout_sec`,Codex 将在委员会给出答案之前中断调用。超时时间的替代方案是不阻塞调用并通过 `start_council_async` + `poll_council_task` 查询结果(参见“工具”)。
### OpenCode
在 `~/.config/opencode/opencode.json` 文件的 `"mcp"` 块中添加记录:
```json
{
"mcp": {
"llm-council": {
"type": "local",
"command": ["uv", "--directory", "/path/to/llm-council", "run", "mcp_server/server.py"],
"enabled": true,
"environment": { "OPENROUTER_API_KEY": "sk-or-v1-..." }
}
}
}
```
OpenCode 中的 `command` 是一个数组(可执行文件 + 参数),访问权限通过 `environment` 传递。如果存储库中已填充 `.env` 文件,则可以在 `environment` 中不重复密钥。
---
## 工具
| 工具 | 描述 |
|------|-------------|
| `ask_council` | 提出问题,获取主席的综合答案。返回 `conversation_id` - 将其传回进行多轮对话。 |
| `start_council_async` / `poll_council_task` | 在后台启动委员会并查询结果 - 适用于调用超时时间较短的客户端(例如 Codex)。`start_council_async` 返回 `task_id`,然后每 15-30 秒调用 `poll_council_task(task_id)`,直到 `status` 变为 `done`/`error`。 |
| `list_conversations` | 委员会保存的讨论列表 |
| `get_conversation` | 特定 `conversation_id` 的完整讨论过程 |
| `get_available_models` | 当前配置中委员会和主席的模型列表 |
| `get_council_metrics` | 进程本地 KPI(成功率、降级、阶段延迟百分位)以 JSON 格式 |
### `ask_council` 参数
- `mode="auto"`(默认)- 协调器自动选择 **quick** (仅限简单问题的主席)、**standard** (3 阶段的常规委员会)或 **deep** (额外批评/编辑阶段)。`thorough=true` 是 deep 的过时别名。
- `conversation_id="..."` - 继续之前的对话(多轮)。
- `clarify_when_unclear=true` - 对于不明确的问题,返回一个澄清问题,而不是启动整个委员会。
- `include_debug=true` - 在答案中添加调试信息(阶段计时、失败模型数)。
- `bypass_cache=true` - 跳过第一轮答案缓存。
长时间调用 `ask_council` 会发送 MCP 进度 + 心跳,以便客户端可以看到活动,而不是“卡住”。如果客户端调用工具的超时时间较短(例如 Codex 默认值),请增加配置中的超时时间(`tool_timeout_sec`),或使用 `start_council_async` + `poll_council_task` 代替 `ask_council`。
---
## 配置
| 变量 | 必需 | 默认值 | 描述 |
|----------|----------|---------|---------|
| `API_PROVIDER` | 否 | `openrouter` | 唯一注册的提供商 |
| `OPENROUTER_API_KEY` | 是 | - | OpenRouter 密钥 |
| `COUNCIL_TIMEOUT_SECONDS` | 否 | `3600` | 完整委员会的时间预算 |
| `LLM_COUNCIL_ROOT` | 否 | 存储库根目录 | SQLite 存储 `data/` 的根目录 |
委员会模型和主席在 `backend/config.py` 中定义。主席必须来自与每个活动委员会成员不同的提供商家族 - 否则,配置导入将在启动时失败(快速失败)。
`API_PROVIDER` 通过小型提供商注册表 (`backend/providers/registry.py`) 解析,而不是通过硬编码的 `if`:目前仅注册了 `openrouter`。要添加新提供商,请按照 `Provider` 协议(`backend/providers/base.py`:`build_request`、`parse_response`、`resolve_auth`)实现 `backend/providers/<name>.py`,并在 `PROVIDER_REGISTRY` 中注册加载器。
---
## 可选:Web UI
FastAPI 后端 + React 前端显示相同的委员会,并进行详细的分析(模型答案、原始排名、置信度横幅):
```bash
./start.sh # 后端在 :8001,前端在 :5173
```
---
## 基于
[karpathy/llm-council](https://github.com/karpathy/llm-council) 的分支,添加了 MCP 服务器、多轮对话、quick/deep 模式、自适应路由和答案缓存。
## 许可证
[MIT](LICENSE)