MCP-native LLM councils for debates, juries, blind panels, refinement, and custom deliberation.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
We haven't yet run this listing's install command through our automated sandbox check. This isn't a red flag β we're steadily working through the catalog.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
"I am Legion, for we are many."
An MCP-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 proxy), and configure the entire council through hot-reloadable files.
Claude β
claude). Each accepts a prompt plus optional context, role, system,
temperature, and maxTokens.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 for the
orchestration options.structuredContent, not the answer text.
Logging goes to stderr (safe for stdio).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.store: false. Nothing is
persisted, so there is no database and no conversation state to manage.From npm β no clone, no build:
From a clone:
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:
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.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.jsonmodel 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 oneconfig/models/<name>.jsonnext 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.
config/models/*.jsonAt 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):
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:
config/roles/*.mdOptional 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.
config/presets/*.jsonOptional 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:
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:
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/legion)<a href="https://allmcps.com/mcp/legion"><img src="https://allmcps.com/api/badge/legion?style=directory" alt="Legion on AllMCPs" /></a>