model-council-mcp

model-council-mcp

Routes questions to multiple AI models (local and cloud) and synthesizes their answers in individual, categorized, or deconflicted modes.

Category
Visit Server

README

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 three configurable modes:

Mode What you get
individual Each model's raw answer, side by side
categorized Judge groups responses into common agreement, complementary insights, and conflicting positions
deconflicted Iterative loop — judge re-questions the council on each conflict until resolved or rounds exhausted; returns a deconfliction score (0–100 %)

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-council

Zero-config: accept the defaults and it just works. With no council models pinned, the council auto-uses every local Ollama model plus your Ollama :cloud models (embedding models like bge-m3 are skipped). The judge auto-selects your largest model. Ask a question immediately — no setup.

On install, Claude Code prompts you for the (all-optional) configurable options — Ollama address, whether to pin specific council models, API keys, default mode, deconfliction rounds. Nothing is required. API keys are stored in your system keychain. Change settings any time from /plugin → Configure.

Local development / test install:

# Validate the manifest
claude plugin validate .

# Load without installing (dev loop)
claude --plugin-dir /path/to/model-council-mcp

Configurable options (prompted at install)

Option Purpose Default
Ollama address Base URL of your Ollama server http://localhost:11434
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 + :cloud) when none pinned true
Judge model Categorizer/deconflicter, or auto (largest) auto
Default response mode individual / categorized / deconflicted categorized
Max deconfliction rounds 1–10 3
OpenAI / Anthropic / Groq API key Enable cloud models (stored in keychain)
vLLM / TRT-LLM / SGLang servers name:host:port entries
Max response tokens Tokens per completion 16000
Cloud / local concurrency Simultaneous requests (cloud pool / local pool) 3 / 1
Completion retries Retries on an empty/failed response 3
Verbose deconfliction Include per-round detail in deconflicted results false
Claude subscription (CLI) Use your Claude Pro/Max subscription via claude -p (no API key) false

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-mcp

Or add to ~/.claude.jsonmcpServers:

{
  "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_ADDRESS Ollama server URL http://localhost:11434
OPENAI_API_KEY Enables OpenAI models
ANTHROPIC_API_KEY Enables Anthropic Claude models
GROQ_API_KEY Enables Groq models
VLLM_SERVERS vLLM servers (see below)
TRTLLM_SERVERS TRT-LLM servers
SGLANG_SERVERS SGLang servers
CLAUDE_CLI true → add subscription-backed Claude members via the local claude CLI (no API key) false
CLAUDE_CLI_MODELS Model aliases for the CLI member opus,sonnet
CLAUDE_CLI_PATH Path to the claude binary claude

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 claude CLI must be installed and logged in (claude/login, or claude setup-token). Set CLAUDE_CLI_PATH if it isn't on PATH.
  • Each call shells out to claude -p with 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_TOKEN are 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 regular anthropic: provider.
  • They are not auto-discovered — add them explicitly via configure_council or COUNCIL_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_CONCURRENCY modest (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.

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:30000

Full URLs also work: gpu3:http://10.0.0.5:9000

Default ports: vLLM → 8000, TRT-LLM → 8000, SGLang → 30000

Council defaults

Variable Description Default
COUNCIL_MODELS Comma-separated model IDs (empty — use configure_council)
JUDGE_MODEL Judge model ID or auto auto (largest council member)
RESPONSE_MODE individual | categorized | deconflicted categorized
MAX_DECONFLICT_ROUNDS Max deconfliction iterations 3

Performance & output

Variable Description Default
MAX_TOKENS Max tokens requested per model completion 16000
CLOUD_CONCURRENCY Max simultaneous requests to cloud members (Ollama cloud :cloud/-cloud, OpenAI, Anthropic, Groq). Ollama cloud needs Pro (3 concurrent) or Max (10) 3
LOCAL_CONCURRENCY Max simultaneous requests to local models; 1 runs them one at a time to avoid contention, 0 = unlimited 1
COMPLETION_RETRIES Attempts per completion before giving up on an empty/failed response 3
DECONFLICT_VERBOSE true → deconflicted results include per-round detail by default false

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 setups

Examples:

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-R1

MCP 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.

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.


get_council_config

Returns current council settings plus all configured provider connections and the full env-var reference.


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 conflicts

Example: 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}
}

License

Apache License 2.0 — Copyright (c) 2026 Tom Sarihan. See LICENSE and NOTICE.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured