MCP-native LLM councils for debates, juries, blind panels, voting, refinement, and custom multi-model deliberation.
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Documented (README)
- !Licence file present but not machine-readable
claude mcp add legion-mcp -- npx -y legion-mcp{
"mcpServers": {
"legion-mcp": {
"command": "npx",
"args": ["-y", "legion-mcp"]
}
}
}Resumen de MCP Servers
# Legion
> "I am Legion, for we are many."
An [MCP](https://modelcontextprotocol.io)-native model council. Legion exposes
LLMs as individual tools and orchestrates them into debates, juries, blind
panels, private refinement gauntlets, workshops, and custom multi-model
deliberations.
Every model is reached through the OpenAI **Responses API** wire format. Use
OpenAI or Azure directly, route other providers through a compatible gateway
(such as a [LiteLLM](https://docs.litellm.ai) proxy), and configure the entire
council through hot-reloadable files.
## Contents
- [How it works](#how-it-works)
- [Design decisions](#design-decisions)
- [Requirements](#requirements)
- [Setup](#setup)
- [Configuration](#configuration)
- [Logging](#logging)
- [Run](#run)
- [Try it](#try-it)
- [Use in VS Code](#use-in-vs-code)
- [Deploy](#deploy)
## How it works
```mermaid
flowchart LR
AI[Calling AI] -->|claude / gpt / gemini …| Legion
Legion -->|Responses API| GPT[OpenAI / Azure — direct]
Legion -->|Responses API| GW[Gateway e.g. LiteLLM]
GW --> Claude & Gemini & Llama
```
- **One tool per model**, named after the slugified model name (e.g. `Claude` →
`claude`). Each accepts a `prompt` plus optional `context`, `role`, `system`,
`temperature`, and `maxTokens`.
- **A `quorum` tool** fans one prompt out to several models — with roles,
multi-round discussion, visibility modes, and synthesis — and returns each
answer separately. See [Presets](#presets--configpresetsjson) for the
orchestration options.
- **Presets** are named, pre-staffed councils (debate, courtroom, code review, …),
each exposed as its own tool.
- Identity and telemetry ride in `structuredContent`, not the answer text.
Logging goes to **stderr** (safe for stdio).
## Design decisions
- **No provider adapters.** There is no provider-specific code and no built-in
model list. Legion speaks one wire format; models that don't speak it natively
go through a gateway. Supporting a new model requires no change here.
- **Models are config, not code.** Adding a model means adding a JSON file. The
directory is re-read per request, so no rebuild or restart.
- **One tool per model.** Each model appears to the calling AI as its own tool
with its own description, rather than a single tool with a model parameter.
The `quorum` tool covers the ad-hoc multi-model case, and each preset in
`config/presets/` is exposed as its own enforced, pre-staffed council tool.
- **Stateless.** Every call is one-shot with `store: false`. Nothing is
persisted, so there is no database and no conversation state to manage.
- **Small.** A few hundred lines of TypeScript, one bundled output file, six
dependencies.
## Requirements
- Node.js 24+
- At least one OpenAI-Responses-compatible endpoint (a provider API directly, or
a gateway such as LiteLLM for models that need bridging)
## Setup
From npm — no clone, no build:
```pwsh
npx legion-mcp
```
From a clone:
```pwsh
npm install
copy .env.example .env # then edit .env
```
## Configuration
All configuration lives in a `config/` directory. The bundled defaults are
**always the base layer**; a `config/` folder in the current working directory
is **overlaid on top of them, per file**:
- **Directory resources** (`models/`, `roles/`, `presets/`, `tools/`): a local
file overrides the bundled file of the same name; a local-only file is added;
every bundled file you don't touch stays. So dropping in one
`config/presets/refine.json` overrides just that preset — the other bundled
presets remain.
- **Single-file text** (`prompts.json`, `errors.json`, `schema.json`): merged
**per key** — bundled < local. A partial local file overrides only
the keys it sets.
- **`description.md`**: local wins whole if present, else bundled.
The overlay can **override or add**, but not delete a bundled entry. To turn off
bundled presets you don't want, use `DISABLE_PRESETS` (see below).
> **Installing from npm? You must supply your own model files.** The bundled
> config ships only key-free `*.example.json` model files, which the scanner
> deliberately ignores — so the bundle contributes **zero** real models. With no
> real model file the server **fails fast at startup** (`No model files found
> in ...`). Drop one `config/models/<name>.json` next to where you run the
> server (see below) — the rest falls back to the bundled defaults.
The layout below is identical either way, and everything hot-reloads per
request.
### Models — `config/models/*.json`
At least one model file is **required** — the server fails fast without one.
Each JSON file becomes a tool, named after the slugified file name
(`config/models/fable.json` → tool `fable`):
```json
{
"model": "claude-fable-5",
"description": "Claude Fable — fast, creative, general purpose.",
"baseUrl": "https://api.example.com",
"apiKey": "sk-optional-per-model-key"
}
```
- `model` (required) — the deployed model id the endpoint routes to.
- `description` — helps the calling AI pick the right model.
- `system` — optional baseline system instructions baked into every call to
this model.
- `baseUrl` / `apiKey` — optional; omitted values fall back to
`DEFAULT_BASE_URL` / `DEFAULT_API_KEY`.
- `omitParams` — optional list of request params to drop for this model, e.g.
`["temperature"]`. The server stays provider-agnostic: it never assumes which
models reject which params — you declare each model's quirks here. Useful for
reasoning models and some deployments that reject `temperature`.
**Hot-drop:** the directory is re-scanned per request — add or edit a model
file and it's live on the next call, no restart.
**Secrets & git:** model files can contain API keys, so `config/models/*.json`
is git-ignored. Copy a `*.example.json` (tracked, key-free, ignored by the
scanner) to get started:
```pwsh
copy config\models\gpt.example.json config\models\gpt.json # then add your key
```
### Roles — `config/roles/*.md`
Optional hot-droppable instruction files. Each `.md` file becomes a named role
(slugified from filename). Drop a file, it's live on the next call. This repo
ships `skeptic.md`, `builder.md`, `judge.md`, and `short.md` (a terse "answer
immediately, no deliberation" role useful for constrained-output turns) as
ready-to-use starters — edit or delete them freely (they hold no secrets).
Available selectors in tools become `roleName`, e.g. passing `role: "skeptic"`
or using `"model:skeptic"` in `quorum.models`.
### Presets — `config/presets/*.json`
Optional hot-droppable **council recipes**, one JSON file per preset (named
after the slugified file name, like models). **Each preset becomes its own
tool** — drop `config/presets/code_review.json` and a `code_review` tool appears
on the next request. Each preset has a `description`, a `roles` list, and
optional authoritative `mode` / `synthesizer` defaults. Each role defines its
behavior **inline** — a role's `description` *is* its instructions (the behavior
contract); a role with no `description` falls back to a matching
`config/roles/<role>.md` file:
```json
{
"description": [
"Free-for-all: pit several contestants against each other, then crown a winner.",
"",
"Staff `contestant` with as many models as you like; one `judge` decides."
],
"mode": "parallel",
"synthesizer": "judge",
"roles": [
{ "role": "contestant", "description": "Argue why your answer beats the others.", "min": 2, "max": null },
{ "role": "judge", "description": "Crown a single winner and justify it.", "min": 1, "max": 1 }
]
}
```
The calling AI invokes the preset tool directly (e.g. `code_review`) and still
writes the `models` selectors, assigning any model to any preset role. Presets
are **enforced**: every selector must use a preset role and every role must be
staffed within its cardinality, else the result is an error saying what to fix.
Keys:
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `description` | `string \| string[]` | required | MCP description for the preset tool. |
| `roles` | `PresetRole[]` | required | Roles accepted by the preset. |
| `mode` | `"sequential" \| "parallel" \| "private" \| "independent"` | `"sequential"` | Controls which prior turns each round speaker sees. |
| `defaultRounds` | positive integer | `1` | Rounds used when the call omits `rounds`. |
| `synthesizer` | `string` | none | Neutral role that produces synthesis turns. |
| `synthesizeEvery` | `"end" \| non-negative integer` | `"end"` | Runs synthesis at the end or every Nth round. |
| `framer` | `string` | none | Neutral role that opens and redirects the discussion. |
| `reframeEvery` | `"end" \| non-negative integer` | `"end"` | Reframes only at opening or every Nth round after opening. |
| `closingStatements` | `boolean` | `false` | Runs a closing phase before final synthesis. |
| `eliminateEvery` | non-negative integer | `0` | Lets the synthesizer remove one speaker every Nth round. Preset-only. |
| `eliminationsOptional` | `boolean` | `false` | Lets the synthesizer decline an elimination. Preset-only. |
| `enterEvery` | non-negative integer | `0` | Starts one speaker per team, then adds one benched speaker every Nth round. Preset-only. |
| `vote` | `string` | none | Ballot instructions; enables anonymous voting. |
| `voteEvery` | `"end" \| non-negative integer` | `"end"` | Votes at the end or every Nth round. |
| `voteVisibility` | `"aggregate" \| "ballots"` | `"aggregate"` | Includes only totals or also anonymized ballot choices in the transcript. |
| `allowSelfVote` | `boolean` | `true` | Includes each voter's own seat in its candidate menu. |
| `voteByTeam` | `boolean` | `false` | Presents one choice per `@team` and aggregates votes by team. |
Role object keys:
| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `role` | `string` | required | Role name used in `model:role` selectors. |
| `description` | `string \| string[]` | matching role fileLo que la gente pregunta sobre legion-mcp
¿Qué es faulkj/legion-mcp?
+
faulkj/legion-mcp es mcp servers para el ecosistema de Claude AI. MCP-native LLM councils for debates, juries, blind panels, voting, refinement, and custom multi-model deliberation. Tiene 1 estrellas en GitHub y su última actualización registrada es del 2026-08-28.
¿Cómo se instala legion-mcp?
+
Puedes instalar legion-mcp clonando el repositorio (https://github.com/faulkj/legion-mcp) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar faulkj/legion-mcp?
+
Nuestro agente de seguridad ha analizado faulkj/legion-mcp y le ha asignado un Trust Score de 80/100 (tier: Trusted). Revisa el desglose completo de comprobaciones superadas y flags en esta página.
¿Quién mantiene faulkj/legion-mcp?
+
faulkj/legion-mcp es mantenido por faulkj. La última actividad registrada en GitHub es del 2026-08-28, con 0 issues abiertos.
¿Hay alternativas a legion-mcp?
+
Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.
Despliega legion-mcp en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/faulkj-legion-mcp)<a href="https://claudewave.com/repo/faulkj-legion-mcp"><img src="https://claudewave.com/api/badge/faulkj-legion-mcp" alt="Featured on ClaudeWave: faulkj/legion-mcp" width="320" height="64" /></a>Más MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
The fastest path to AI-powered full stack observability, even for lean teams.
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!