# Model Council (pypi · model-council-mcp)

Consult other LLMs as tools — ask them, compare their answers, synthesize a conclusion.

- Trust score: 63/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-20

## Components

- pypi · `model-council-mcp`: 63/100 (this document), [markdown](https://verifymcp.io/servers/totti0135-model-council/model-council-mcp.md), [page](https://verifymcp.io/servers/totti0135-model-council/model-council-mcp)

## Channel facts

- Registry: `pypi`
- Package: `model-council-mcp`
- Version: `0.13.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-20.

- **Supply Chain Security**: 100/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - Runs hatchling.build at install time, a recognised native-build step with no shell scripting around it.
  - 2 of 33 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 32/100
  - Source repository is publicly reachable at the declared URL.
  - Provenance check failed: no build-provenance attestation is published.
  - License check failed: no license is declared.
  - Actively maintained (last published 0 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 56/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 2725 tokens (~454/item across 6 items; 6 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 20/100
  - Stability observed for 6 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

## Install

### Claude

```bash
claude mcp add totti0135-model-council -- uvx model-council-mcp
```

### Codex

```bash
codex mcp add totti0135-model-council -- uvx model-council-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "totti0135-model-council": {
      "type": "local",
      "command": [
        "uvx",
        "model-council-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add totti0135-model-council --command uvx --arg model-council-mcp
```

### Hermes

```yaml
mcp_servers:
  totti0135-model-council:
    command: "uvx"
    args: ["model-council-mcp"]
```

### Other

```json
{
  "mcpServers": {
    "totti0135-model-council": {
      "command": "uvx",
      "args": [
        "model-council-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-20 (score 63, +15)

- [security regression] Stability: 0.17 → unverified
- [security improvement] Malware scan: unverified → pass
- [functional regression] Schema quality: 372 → 454
- [functional regression] Schema quality: 372 → 432
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional] First check of Schema quality: unverified
- [functional] Package version: 0.11.0 → 0.13.0
- [functional] Package version: 0.11.0 → 0.12.0

### 2026-08-19 (score 48, +1)

- [functional regression] Schema quality: 231 → 372
- [functional] Schema quality: good → excellent
- [functional] Package version: 0.9.0 → 0.11.0

### 2026-08-18 (score 47, −1)

- [functional regression] Schema quality: 162 → 231
- [functional] Package version: 0.5.0 → 0.9.0
- [functional] Package version: 0.5.0 → 0.8.0

### 2026-08-17 (score 48, −15)

- [security regression] Malware scan: pass → unverified
- [functional regression] Schema quality: pass → fail
- [functional improvement] Stability: unverified → 0.10
- [functional] Package version: 0.3.0 → 0.5.0
- [functional] Package version: 0.3.0 → 0.4.1

### 2026-08-14 (score 63)

First indexed and scored.

## MCP tools (6)

### `ask` (~286 tokens)

Ask ONE member of the council a question and return its answer.

\`model` is the member's short id; the schema lists the ones this council has, and
\`list_council` describes them.

The member is stateless and cannot see this conversation, so `prompt` must carry
everything it needs — including any other model's answer you want it to critique.
Optionally set `system` to steer its role or output format.

\`materials` hands the council the thing the question is about — a spec, a log, a diff, a screenshot — instead of you pasting it into `prompt`. Give `{path, label}` for a file, or `{text, label}` for something with no file behind it. Prefer a path: the members are then handed the file's exact bytes rather than your reproduction of them, you do not spend a copy of the whole document writing this call, and every member and every round get an identical copy, which is both what makes their answers comparable and what an endpoint's cache can match. Images go this way too, and are the case that matters most: describe a screenshot in prose and every member inherits the same description, so anything you misread is misread by the whole council at once.

Input parameters:

- `materials`
- `model` (string, required)
- `prompt` (string, required)
- `system`

Output parameters:

- `result` (string)

### `ask_all` (~1161 tokens)

Ask several members the SAME prompt in parallel, returning
their answers side by side and labeled by model.

By default every configured member answers. Pass `models` to ask only some of
them; the schema lists the valid ids.

\`rounds` (1-3, default 1) runs a real discussion. With `rounds=2` the members
first answer independently, then each is asked again — this time carrying the
question plus every answer from round 1, its own and the others', verbatim — and
asked to revise. Members are stateless, so carrying the previous round back to
them is the whole mechanism: without it a second round is just the same question
asked twice. The transcript returns round by round, so you can see who moved and
who held their ground.

One round is a survey of opinion. Two is worth the extra latency and tokens when
the answers are likely to disagree and the disagreement is the interesting part.

\`rounds` is chosen before anything has been asked, which is the one thing wrong
with it: you commit to a second round without having read the first, and a
council that turns out to agree costs exactly what one still arguing would. When
you would rather look first, ask with `rounds=1` and then call `revise` with the
answers — it runs one more round on demand, as many times as you judge it worth,
and it has no ceiling. Reading before you buy is usually the cheaper of the two:
one more round is another full call per member, while `revise` costs you only the
answers written back into it.

\`guests` seats answers you already have. If you spawned a subagent on this same
question, or formed your own view first, pass it here as {label, text} and it
joins the table: it appears in round 1 beside the members, and from round 2 the
members are shown it verbatim and argue with it. This is the difference between
an answer that is in the discussion and one that is merely next to it — without
it, the models never learn your subagent had an opinion. Pass the text verbatim,
not a summary; a summary is not what…

Input parameters:

- `guests`
- `materials`
- `models`
- `prompt` (string, required)
- `rounds` (integer)
- `steelman`
- `system`

Output parameters:

- `result` (string)

### `revise` (~503 tokens)

Run ONE more round of an existing discussion: show every
member what was said last round and ask it to revise.

This is `ask_all`'s rounds turned inside out, so that you can drive them. Two
reasons to want that.

\**You would rather decide after reading.** `ask_all(rounds=2)` commits to the
second round before the first one exists. Ask with `rounds=1`, read what comes
back, and call this only if the disagreement is worth another call per member —
or call it three more times if they are still moving. There is no round ceiling
here, unlike `ask_all`, because every round is one you chose to pay for.

\**A voice in the discussion is one only you can produce** — a subagent you
spawned, or your own answer — and you want it to be a full member rather than a
one-off: something that answers, reads the others, and revises alongside them.

The loop, in the second case:

  1\. `ask_all(prompt)`               — the members answer round 1
     ...and you produce your subagent's round-1 answer yourself
  2\. `revise(prompt, answers=[...])` — pass EVERY round-1 answer, the members'
     and your subagent's; the members come back revised
     ...and you re-run your subagent on the same material
  3\. repeat as long as it is still moving

Each entry in `answers` is `{text, model}` for a member's own answer, or
\`{text, label}` for an outside one. Naming the member matters: that is what lets
it see its previous answer as its own and revise, instead of answering fresh.

\`round` is which round the answers you are passing came from, so the members are
told where they are. Pass answers verbatim, never summarised.

Pass the same `materials` you passed to `ask_all`, every round. The members are
stateless: a document they were shown last round does not exist for them in this
one, and a council revising from memory it does not have will revise from the
other answers alone.

Input parameters:

- `answers` (array, required)
- `materials`
- `models`
- `prompt` (string, required)
- `round` (integer)
- `system`

Output parameters:

- `result` (string)

### `revision_prompt` (~305 tokens)

Build the exact prompt a seat should be given for the next
round — for the one seat this server cannot ask itself: yours.

\`revise` asks the members. Your subagent is yours to re-run, and how you prompt it
decides whether it revises at all: handed the original question again, it will
reproduce its previous answer, and nothing in the transcript will show that the
seat stopped participating. Handed this, it revises on exactly the terms the
members did — same framing, same instruction to hold a position it still believes
against the majority, which is the sentence that keeps a council from collapsing
into agreement.

Pass the same `prompt`, `answers`, `round` and `materials` you are passing to
\`revise`, plus `seat`: the label (or member id) of the seat to write for. Cheap
and local — makes no network calls, so run it alongside `revise` rather than
after it.

Material is named in the prompt rather than pasted into it, at the position the
members were given it. Open those files for your seat before you hand it the
rest: a seat that revises without the document is arguing about something it has
not read, and the transcript will not show it.

Input parameters:

- `answers` (array, required)
- `materials`
- `prompt` (string, required)
- `round` (integer)
- `seat` (string, required)

Output parameters:

- `result` (string)

### `list_council` (~393 tokens)

List the council's members: their ids, labels, target models, weights, wire
format, endpoint, call budget, and whether each one is ready to answer.

\`weight` is how much this council trusts each member, relative to the others;
everyone is 1 unless the roster says otherwise, and `ask_all` reports it
alongside the answers whenever they differ.

\`tries` is how many attempts a call gets and how long each may take, so a
member that is slow or that keeps being retried is visible here.

\`sees` is whether this member may be shown an image in `materials`. The line
above the table says whether this server will read `materials` paths at all,
which depends on how its operator runs it.

\`route` is how this member reaches its endpoint — `env` follows the proxy in
the server's environment, `direct` ignores it, and a URL is a proxy set for
that member alone. It appears only when the members can differ; passwords in
a proxy URL are masked.

A member may have `backups`: further endpoints for the same seat, indented
under it as `↳ backup 1`, `↳ backup 2` and tried in that order when the one
above does not answer. They are the same member — same id, same label, one
vote — so you never address a backup directly; the seat's id reaches
whichever of them is up. Read their `model` column: a backup is often the
same model under a different id, and sometimes not the same model at all,
and `ask_all` names the one that actually answered above each answer.

Cheap and local — makes no network calls. Use this to find out which ids you
may pass to `ask` and `ask_all`, or to explain a configuration problem.

Output parameters:

- `result` (string)

### `probe_models` (~77 tokens)

Ask a member's endpoint which model ids it actually exposes,
by calling its /models route.

Pass `model` to probe one member, or omit it to probe every configured member.

Use this when a call fails with an unknown-model error, or to discover what else
a provider offers — model ids move fast.

Input parameters:

- `model`

Output parameters:

- `result` (string)

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/totti0135-model-council/model-council-mcp#diagnostics

## Score history

- 2026-08-20: 63
- 2026-08-19: 48
- 2026-08-18: 47
- 2026-08-17: 48
- 2026-08-16: 63
- 2026-08-15: 63
- 2026-08-14: 63

## Links

- PyPI project: https://pypi.org/project/model-council-mcp/
- Socket report: https://socket.dev/pypi/package/model-council-mcp
- Repository: https://github.com/Totti0135/model-council
- Changelog RSS feed: https://verifymcp.io/servers/totti0135-model-council/model-council-mcp.xml
- Changelog JSON feed: https://verifymcp.io/servers/totti0135-model-council/model-council-mcp.json
- HTML version of this page: https://verifymcp.io/servers/totti0135-model-council/model-council-mcp
