model-council-mcp
The model-council-mcp server routes questions to a council of diverse AI models and synthesizes their answers using configurable analytical modes.
Core tools:
ask_council— Send a question to all council members and receive a structured response.configure_council— Set member models, judge model, response mode, and deconfliction rounds at runtime (all fields optional, changes persist for the session). You can also override mode/rounds per individualask_councilcall.list_models— Discover all available models across configured providers, with optional provider filtering.get_council_config— Inspect the current council settings.
Supported model providers:
Local: Ollama (auto-discovered), vLLM, TRT-LLM, SGLang
Cloud: OpenAI, Anthropic, Groq
Subscription-backed (no API key): Claude Pro/Max or ChatGPT via local CLI
Response synthesis modes:
individual— Raw per-model answers side by side.categorized— A judge AI groups responses into common agreement, complementary insights, and conflicting positions.deconflicted— Iterative re-questioning to resolve conflicts, returning a deconfliction score (0–100%).pooled(Delphi-style) — Judge distills answers into a neutral, anonymous pool for members to reconsider.dialectic(thesis → antithesis → synthesis) — Adversarial debate with a pros/cons dossier and ranked top-3.
Key design goal: Surface systematic biases and blind spots by querying independent models from different families and providers, then resolving disagreements through structured synthesis.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@model-council-mcpAnalyze the ethical implications of AI from different philosophical perspectives"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
model-council-mcp
An MCP server that routes a question to a council of AI models — local (Ollama, vLLM, TRT-LLM, SGLang) and cloud (OpenAI, Anthropic, Groq) — and synthesizes their answers in five configurable modes:
Mode | What you get |
| Each model's raw answer, side by side |
| Judge groups responses into common agreement, complementary insights, and conflicting positions |
| Iterative loop — judge re-questions the council on each conflict until resolved or rounds exhausted; returns a deconfliction score (0–100 %) |
| Delphi-style — judge distils all answers into a neutral, deduplicated pool (no counts, no attribution, no ranking); members reconsider against it and answer freshly. No winner is forced, so genuine divergence is preserved rather than collapsed by social proof |
| Thesis → antithesis → synthesis — members defend their initial pick and argue why the alternatives aren't better; the judge compiles a balanced pros/cons dossier per option; members then re-select a ranked top-3 having weighed both sides |
Install as a Claude Code plugin (recommended)
This repo is a self-contained Claude Code plugin — the server is bundled into a single zero-dependency file (bundle/server.cjs), so it runs offline against local models with no npm install step.
# 1. Add this repo as a marketplace (from GitHub)
/plugin marketplace add tsarihan/model-council-mcp
# 2. Install the plugin
/plugin install model-council@model-councilZero-config — it just works. On first run the plugin detects your environment and auto-populates the council with everything usable: every local Ollama chat model, your top curated Ollama :cloud models, and — if you're logged into them — Claude (via the local claude CLI) and ChatGPT (via the local codex CLI). It tells you what it found, warns that cloud/subscription members use your own quotas, and lets you delete any you don't want. Deletions and setup persist across reloads. Ask a question immediately — no setup required.
On a new session the plugin prints a one-line status (council size, Ollama up/down, which CLIs are installed).
Run
/model-council:statusany time for the full readout — detected models, CLI login state, per-provider concurrency, and quota usage.Run
/model-council:setupto pick your subscription tiers with an interactive menu.
Everything is optional and adjustable from /plugin → Configure. API keys are stored in your system keychain.
Local development / test install:
# Validate the manifest
claude plugin validate .
# Load without installing (dev loop)
claude --plugin-dir /path/to/model-council-mcpConfigurable options (prompted at install)
Option | Purpose | Default |
Ollama address | Base URL of your Ollama server |
|
Council models | Pin specific models, or leave blank to auto-use all Ollama models | (empty → auto) |
Auto-discover council | Use all Ollama chat models (local + |
|
Claude tier |
|
|
ChatGPT tier |
|
|
Ollama tier |
|
|
Judge model | Categorizer/deconflicter, or |
|
Default response mode |
|
|
Max deconfliction rounds | 1–10 |
|
OpenAI / Anthropic / Groq API key | Enable cloud models (stored in keychain) | — |
vLLM / TRT-LLM / SGLang servers |
| — |
Max response tokens | Tokens per completion |
|
Cloud concurrency (override) | Optional; caps all cloud pools, overriding the per-tier limits | (unset → tiers) |
Local concurrency | Simultaneous local requests (0 = unlimited) |
|
Completion retries | Retries on an empty/failed response |
|
Related MCP server: Delia
Subscription tiers, auto-population & detection
The council mixes three kinds of member, each gated by a subscription tier so it never quietly burns quota you don't have:
Provider | Tiers |
| Reference file |
Ollama |
| local models only (no | |
Claude (via |
| no Claude members | ″ |
ChatGPT (via |
| no ChatGPT/Codex members | ″ |
Per-provider concurrency. Each subscription gets its own concurrency ceiling (e.g. ChatGPT 6, Claude 2, Ollama-cloud 3 on Pro / 10 on Max), so one slow, tightly-rate-limited provider can't starve another. Tier→limit mappings, curated cloud models, and provider model names all live in
config/subscriptions.json— edit it and pull to pick up new plans/models.Detection. On boot (and on
council_status) the server checks: is Ollama reachable, does your plan reach:cloud, is theclaudeCLI installed and logged in (a locked-down probe), is thecodexCLI signed in (codex login status). Only usable providers are auto-added; the rest get a hint (e.g. "Codex CLI installed but not signed in — runcodex login").It persists. Your tier choices and member edits are saved to
~/.config/model-council/state.json(override withMODEL_COUNCIL_STATE), so they survive plugin reloads.Works standalone too. The auto-config,
council_status, andsetup_counciltools all work for a plainclaude mcp add/ MCP-store install; only the SessionStart welcome line and the/model-council:*slash commands are Claude-Code-plugin-only sugar.
Cloud and subscription members run under your own subscription quotas via the sanctioned first-party CLIs.
council_statusalways shows a quota warning listing which paid providers are in the council. Reusing a subscription token against a raw vendor API from a third-party app is a separate, prohibited thing — this plugin does not do that.
Install as a standalone MCP server (npm)
# Quick try
npx model-council-mcp
# Add to Claude Code
claude mcp add model-council-mcp -s user -- npx -y model-council-mcpOr add to ~/.claude.json → mcpServers:
{
"mcpServers": {
"model-council": {
"command": "npx",
"args": ["-y", "model-council-mcp"],
"env": {
"OLLAMA_ADDRESS": "http://localhost:11434",
"COUNCIL_MODELS": "ollama:llama3,ollama:mistral",
"RESPONSE_MODE": "categorized"
}
}
}
}Configuration (environment variables)
Provider connections
Variable | Description | Default |
| Ollama server URL |
|
| Enables OpenAI models | — |
| Enables Anthropic Claude models | — |
| Enables Groq models | — |
| vLLM servers (see below) | — |
| TRT-LLM servers | — |
| SGLang servers | — |
|
|
|
| Model aliases for the CLI member |
|
| Path to the |
|
|
|
|
| Model names for the Codex member ( |
|
| Path to the |
|
Claude via your subscription (first-party CLI)
Set CLAUDE_CLI=true to add council members that run through the locally-installed Claude Code CLI (claude -p) instead of the Anthropic API. Inference runs under whatever your claude CLI is logged in with — typically your own Claude Pro/Max subscription — so these members don't consume API credits. They appear as claude-cli:opus, claude-cli:sonnet, etc.
Behavior & requirements
The
claudeCLI must be installed and logged in (claude→/login, orclaude setup-token). SetCLAUDE_CLI_PATHif it isn't onPATH.Each call shells out to
claude -pwith all tools disabled (--tools ""), MCP disabled (--strict-mcp-config, so it can't recurse into this plugin), and sessions not persisted — a clean single text answer.ANTHROPIC_API_KEY/ANTHROPIC_AUTH_TOKENare stripped from the nested call, because the CLI silently prefers an API key over the subscription. So these members stay subscription-billed even if you also set an API key for the regularanthropic:provider.They are not auto-discovered — add them explicitly via
configure_councilorCOUNCIL_MODELS(e.g.claude-cli:opus), so they don't quietly draw down your subscription.
Where it works: anywhere the claude CLI actually executes — the Claude Code CLI, or the Claude Desktop app on a machine that also has the CLI. With /remote-control on your CLI, driving it from the Claude web/mobile code tab still runs claude -p on your machine, so it works there too. It does not work for a remotely-hosted copy of this server (no local CLI), and it can't borrow the Claude app's subscription directly (no client supports MCP sampling yet).
This uses the sanctioned first-party CLI under your own subscription, for your own use. High-volume automated fan-out can hit your subscription's rate limits — keep
CLOUD_CONCURRENCYmodest (these members use the cloud pool). Reusing a subscription token against the raw Anthropic API from a third-party app is a separate thing and is prohibited; this feature does not do that.
ChatGPT via your subscription (first-party Codex CLI)
Set CODEX_CLI=true to add a council member that runs through the locally-installed Codex CLI (codex exec) instead of the OpenAI API. Inference runs under whatever your codex CLI is signed in with — typically your own ChatGPT subscription (codex login → Sign in with ChatGPT) — so this member doesn't consume API credits. It appears as codex-cli:default (or codex-cli:<model>).
Behavior & requirements
The
codexCLI must be installed and signed in (codex login). SetCODEX_CLI_PATHif it isn't onPATH.Each call shells out to
codex execin a read-only sandbox (--sandbox read-only) with no approval prompts (approval_policy=never), run in an empty ephemeral working dir so the agent has nothing to explore, and reads the final answer from-o <file>— a clean single text answer, no file changes.OPENAI_API_KEY/CODEX_API_KEYare stripped from the nested call, because the CLI silently prefers an API key over the ChatGPT login. So this member stays subscription-billed even if you also set an API key for the regularopenai:provider.Use
CODEX_CLI_MODELS=defaultto let Codex pick its configured model, or name specific ones (e.g.gpt-5-codex). It is not auto-discovered — addcodex-cli:defaultexplicitly viaconfigure_councilorCOUNCIL_MODELS.Codex is a coding agent, so answers carry a coding-agent flavor (concise, implementation-oriented) even on general questions — useful as a distinct voice in the council, but not a neutral generalist.
Where it works: same as the Claude CLI above — anywhere the codex binary actually executes (this machine, or a /remote-control-driven CLI running on your machine). It does not work for a remotely-hosted copy of this server.
Same rules as the Claude CLI: sanctioned first-party surface under your own subscription. Reusing a subscription token against the raw OpenAI API from a third-party app is a separate, prohibited thing; this feature does not do that.
OpenAI-compatible server format
Comma-separated list of name:host:port entries.
You can run multiple servers on different ports (e.g. different models on the same GPU host):
VLLM_SERVERS=gpu1:192.168.1.10:8000,gpu2:192.168.1.10:8001
TRTLLM_SERVERS=trt-main:192.168.1.20:8000
SGLANG_SERVERS=sgl1:192.168.1.30:30000Full URLs also work: gpu3:http://10.0.0.5:9000
Default ports: vLLM → 8000, TRT-LLM → 8000, SGLang → 30000
Council defaults
Variable | Description | Default |
| Comma-separated model IDs | (empty — use |
| Judge model ID or |
|
|
|
|
| Max deconfliction iterations |
|
Performance & output
Variable | Description | Default |
| Max tokens requested per model completion |
|
| Max simultaneous requests to cloud members (Ollama cloud |
|
| Max simultaneous requests to local models; |
|
| Attempts per completion before giving up on an empty/failed response |
|
|
|
|
The council queries members in parallel but respects these concurrency limits — cloud members share one pool and local members another, so a large council never exceeds your Ollama cloud plan's concurrent-request cap, and local models can be run sequentially to avoid GPU contention.
Model ID format
provider:model
provider/serverId:model ← for named multi-server setupsExamples:
ollama:llama3
ollama:mistral:7b-instruct-q4_K_M
openai:gpt-4o
openai:o1-mini
anthropic:claude-opus-4-5
groq:llama-3.3-70b-versatile
vllm/gpu1:meta-llama/Meta-Llama-3-8B-Instruct
trtllm/trt-main:mistralai/Mistral-7B-v0.1
sglang/sgl1:deepseek-ai/DeepSeek-R1MCP Tools
list_models
Discover all models across every configured provider.
{ "filter_provider": "ollama" }Returns model IDs, parameter size, family, disk size — everything you need to fill configure_council.
configure_council
Update the council at runtime (changes persist for the session).
{
"models": ["ollama:llama3", "ollama:mistral", "openai:gpt-4o"],
"judge_model": "openai:gpt-4o",
"response_mode": "deconflicted",
"max_deconflict_rounds": 4
}All fields are optional — only supplied fields are updated.
ask_council
Send a question to the full council.
{
"question": "What is the best way to handle errors in a distributed system?",
"mode": "deconflicted",
"max_deconflict_rounds": 3
}mode and max_deconflict_rounds override the configured defaults for this call only. In deconflicted mode, set "verbose": true to include the initial categorization, every member's per-round responses, and the round-by-round re-categorization alongside the final synthesis. In pooled mode, "verbose": true adds the initial (round-0) raw member responses.
Individual result
{
"mode": "individual",
"question": "...",
"responses": [
{ "label": "ollama:llama3", "response": "...", "latencyMs": 1240 },
{ "label": "openai:gpt-4o", "response": "...", "latencyMs": 843 }
]
}Categorized result
{
"mode": "categorized",
"question": "...",
"commonAgreement": "All models agree that ...",
"complementary": [
{ "aspect": "performance", "models": ["ollama:llama3"], "insight": "..." }
],
"conflicting": [
{
"id": "conflict-1",
"topic": "retry strategy",
"positions": [
{ "models": ["ollama:llama3"], "position": "exponential backoff" },
{ "models": ["openai:gpt-4o"], "position": "circuit breaker preferred" }
]
}
],
"judgeModel": "openai:gpt-4o"
}Deconflicted result
{
"mode": "deconflicted",
"question": "...",
"roundsTaken": 2,
"maxRounds": 3,
"deconflictionScore": 75,
"resolved": 3,
"totalConflicts": 4,
"finalSynthesis": "The council recommends ...",
"unresolvedConflicts": [ { "id": "conflict-3", "topic": "...", "positions": [...] } ],
"roundHistory": [
{ "round": 1, "conflictsEntering": 4, "conflictsResolved": 2, "conflictsRemaining": 2 },
{ "round": 2, "conflictsEntering": 2, "conflictsResolved": 1, "conflictsRemaining": 1 }
],
"judgeModel": "openai:gpt-4o"
}Deconfliction score: resolved / totalConflicts × 100.
100 % means all conflicts resolved; n/m means n conflicts resolved out of m found.
Pooled result (Delphi)
{
"mode": "pooled",
"question": "...",
"judgeModel": "openai:gpt-4o",
"initialPool": {
"options": [
{ "answer": "Exponential backoff", "rationale": "<reasons merged from everyone who said it>", "models": ["ollama:llama3", "openai:gpt-4o"] }
]
},
"reconsidered": [
{ "label": "ollama:llama3", "response": "<fresh answer after seeing the neutral pool>", "latencyMs": 1120 }
],
"finalPool": { "options": [ { "answer": "...", "rationale": "...", "models": ["..."] } ] }
}Why pooled exists: the deconflicted loop shows each member the labelled factions ([modelA, modelB]: X) and asks them to "agree with one of the existing positions" — that is social proof, and minority views tend to collapse toward the visible plurality in a single round, erasing the decorrelation the council exists to surface. pooled follows the Delphi method instead: the judge distils all answers into a neutral digest — one entry per distinct answer, rationale merged from everyone who gave it, but with no counts, no attribution, and no ranking — then re-asks members the original question against that digest ("in no particular order, here is what others said — what do you think?"). Members reconsider on substance, not popularity. The models field on each option is recorded for your analysis and is never shown back to members. No final winner is declared: compare initialPool vs. finalPool to see whether — and how much — opinion actually moved.
Dialectic result (thesis → antithesis → synthesis)
{
"mode": "dialectic",
"question": "...",
"judgeModel": "openai:gpt-4o",
"defenses": [
{ "label": "ollama:llama3", "response": "<defends its pick, argues the others are weaker>", "latencyMs": 3900 }
],
"prosCons": [
{
"answer": "Exponential backoff",
"pros": ["adapts to load", "avoids overwhelming a struggling dependency"],
"cons": ["more complex", "longer worst-case latency"],
"championedBy": ["ollama:llama3", "openai:gpt-4o"]
}
],
"selections": [
{ "label": "ollama:llama3", "response": "#1 ... #2 ... #3 ... (with the trade-off accepted)", "latencyMs": 4100 }
]
}Where pooled is deliberately neutral, dialectic is deliberately adversarial. Step 1 (antithesis) shows every member the full option set and asks it to defend its own initial pick and argue why each alternative is not better — personalised per member. The judge then distils those defenses and critiques into a balanced pros/cons dossier (prosCons), one entry per option with arguments for and against. Step 2 (synthesis) shows that dossier to every member and asks for a fresh ranked top-3, accepting the main trade-off of each choice. championedBy records who originally proposed each option (for your analysis). Use it when you want each option stress-tested from both sides before anyone commits — the opposite of the social-proof collapse deconflicted can produce. Add "verbose": true to include the thesis (round-0) responses.
get_council_config
Returns current council settings plus all configured provider connections and the full env-var reference.
council_status
The welcome/status readout (works in every client and install method). Returns the detected environment (local Ollama models, Ollama-cloud reachability, whether the Claude/Codex CLIs are installed and logged in), the current council members, resolved subscription tiers, per-provider concurrency, a quota warning, and hints for anything not usable. Read-only.
setup_council
Set subscription tiers (chatgpt, claude, ollama), then re-detect and auto-populate the council with everything usable. Persists across reloads. Concurrency and newly-registered providers take full effect after a /reload-plugins.
Slash commands (Claude Code plugin only)
/model-council:setup— interactive tier selection (arrow-select menus) →setup_council./model-council:status— renderscouncil_status.
Standalone MCP installs call the setup_council / council_status tools directly for the same result.
Deconfliction algorithm
1. Query all council members in parallel → N raw responses
2. Judge model categorises → common / complementary / M conflicts
3. If M = 0 → synthesise final answer, score = 100 %
4. For each round r in 1..maxRounds:
a. Ask all members specifically about each open conflict
b. Judge re-categorises conflict responses
c. Conflicts where positions converge → marked resolved
d. If no conflicts remain → break
5. Score = resolvedCount / M × 100
6. Judge synthesises final answer, noting any unresolved conflictsExample: full multi-provider setup
{
"mcpServers": {
"model-council": {
"command": "npx",
"args": ["-y", "model-council-mcp"],
"env": {
"OLLAMA_ADDRESS": "http://localhost:11434",
"OPENAI_API_KEY": "sk-...",
"ANTHROPIC_API_KEY": "sk-ant-...",
"GROQ_API_KEY": "gsk_...",
"VLLM_SERVERS": "gpu1:192.168.1.10:8000,gpu2:192.168.1.10:8001",
"SGLANG_SERVERS": "sgl1:192.168.1.30:30000",
"COUNCIL_MODELS": "ollama:llama3,ollama:mistral,openai:gpt-4o,anthropic:claude-sonnet-4-5,groq:llama-3.3-70b-versatile",
"JUDGE_MODEL": "anthropic:claude-opus-4-5",
"RESPONSE_MODE": "deconflicted",
"MAX_DECONFLICT_ROUNDS": "3"
}
}
}
}Background
The council's value comes from decorrelation: routing a question to independent models from different families and providers surfaces systematic biases and blind spots that any single model — or a set of correlated ones — would hide. The categorized and deconflicted modes make that disagreement explicit and then work to resolve it.
This design is informed by The Mirror Law, which shows that a learner trained against a single reference reproduces that reference's error field — so the bias is invisible from the loss curve alone, and a decorrelated second reference is what makes the hidden bias observable.
Sarihan, Tom. The Mirror Law: Reference Quality and the Transfer of Systematic Bias in Imitation and Distillation. Preprint, 2026. DOI: 10.5281/zenodo.21282027. Code and materials: github.com/tsarihan/MirrorLaw.
@article{sarihan2026mirror,
title = {The Mirror Law: Reference Quality and the Transfer of Systematic Bias in Imitation and Distillation},
author = {Sarihan, Tom},
year = {2026},
doi = {10.5281/zenodo.21282027},
note = {Preprint}
}Privacy & data handling
model-council runs entirely locally and stores nothing off your machine.
Where your prompts go. A question is sent only to the model endpoints you configure: your local Ollama server, any self-hosted vLLM/TRT-LLM/SGLang servers, cloud API providers you supply keys for (OpenAI/Anthropic/Groq), and — for subscription members — your own local
claude/codexCLIs. There is no model-council backend and no telemetry; nothing is sent to the author.Credentials. API keys are stored in your client's secure storage (system keychain) and used only to call the provider you gave them for. Subscription members run under your own Claude/ChatGPT login via the first-party CLIs; the server strips
ANTHROPIC_*/OPENAI_*/CODEX_*keys from those child processes so inference is billed to your subscription, not an API key.On disk. The only file written is
~/.config/model-council/state.json(your selected tiers + council members), plus~/.codex/ Claude CLI session state owned by those tools. No conversation content is persisted by this server.Subprocesses. Detection and subscription inference shell out to the locally-installed
claudeandcodexbinaries (read-only sandbox for Codex; MCP/tools disabled for the Claude probe so it can't recurse or take actions).
Submitting to a directory
This plugin is distributed as a GitHub plugin marketplace (above). To also list it:
Community Plugin Marketplace (
anthropics/claude-plugins-community) — open a PR; it passes automated validation + safety screening.claude plugin validate .must pass (it does).Anthropic Connectors Directory — submit via the claude.ai admin portal. Checklist: tool annotations (present —
title+readOnlyHinton every tool), the Privacy section above (also linked from the manifest), clear docs, and an explicit disclosure that inference shells out to the user's own localclaude/codexCLIs under their subscription (keys stripped; no third-party backend).
License
Apache License 2.0 — Copyright (c) 2026 Tom Sarihan. See LICENSE and NOTICE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tsarihan/model-council-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server