OpenRouter · Groq · Cerebras · Sail · one comparable shape

Open Dashboard MCP

Pick the cheapest model that still does the job — across every provider you hold a key with, not one at a time.

Install

claude mcp add open-dashboard -- npx -y open-dashboard-mcp

Node 20 or newer. No API key is needed for any tool except the optional key inventory. Published on npm as open-dashboard-mcp.

How it stays current

It is consumed as an MCP server, not a snapshot. npx -y open-dashboard-mcp resolves the latest published version on every launch, so an upgrade reaches you with nothing to reinstall anywhere. A periodic snapshot would freeze pricing at build time — and a model that stopped being free yesterday would still read as free in a copy taken last week, which is the precise harm this exists to prevent.

Every tool reads a public, zero-credential API at query time. That host is a hobby-tier deployment with no uptime obligation, and it is a dependency of every answer. Two things follow, and both are visible in the response rather than left to assumption.

Responses are cached, and every answer carries its own age. One economics query can make two dozen upstream requests — measured, ten requests and 733 ms cold, then zero requests and 3 ms on a repeat. Each piece of evidence carries when it was measured and how old it is:

"freshness": {
  "state": "cached",
  "fetchedAt": "2026-08-27T20:21:52.494Z",
  "ageSeconds": 30,
  "expiresAt": "2026-08-27T20:26:52.494Z"
}

When the host is slow or down, the answer says so. With nothing cached you get a structured unavailable carrying a reason — never a fabricated number. With an expired entry in hand the last known value is returned, but marked:

"state": "expired",
"note": "Upstream could not be reached, so this is the last known value,
         measured 2026-08-27T20:21:52.494Z (3600s ago). It is not current."

Unmeasured is not zero, and stale is not fresh. A number is never handed back as current when it is not, and the age arrives with the answer so a caller can refuse it.

Why it exists

A free model does not announce itself when it stops being free. It simply starts costing money, and the bill arrives before the surprise does. Meanwhile the model that is cheapest for a task on one provider is rarely cheapest on another, and OpenRouter's own MCP server is single-vendor by construction — it cannot compare across the providers you actually use.

This server reads all three catalogues, puts them in one shape, and refuses to guess where they disagree.

What it does today

Each claim below is marked with what was actually measured, not what is intended. Where the answer is no, it says no.

What each provider actually publishes

The four catalogues disagree about nearly everything, and normalising that is most of the work. Every gap below is declared per provider, so a missing value is reported as that provider withheld it rather than appearing as a blank you might read as zero.

Measured against the live API, 2026-08-27.
ProviderModelsWith pricesContextModalityDeprecation signalSpend API
OpenRouter562417yesyesyesyes
Groq136yesyesnono
Cerebras20nononono
Sail99nononono

Three rules follow from that table, and the server enforces all three:

What it can tell you that one provider cannot

The same model, on the same day, across two providers:

openrouter  openai/gpt-oss-120b   in $0.037/M   out $0.17/M
groq        openai/gpt-oss-120b   in $0.150/M   out $0.60/M

Measured 2026-08-27. Four times cheaper on one provider than the other, for the identical model — the comparison a single-vendor tool cannot make.

Sail, and why a price carries its window

Sail publishes no prices programmatically. There is no catalogue endpoint to read, only a pricing document written for people — so the server reads that document, pins it by sha256, and parses the billing windows out of it.

The pin is the feature, not a detail. When the document’s digest does not match the pinned value, every Sail model is dropped from the answer and the response says PRICES ARE STALE and names the mismatch. It never falls back to prices it cannot vouch for. A router quoting a stale price is worse than one that returns nothing, because the caller cannot tell the difference.

Sail prices the same model differently by completion windowasap, balanced and flex — so the window is part of the price rather than a note about it. Two rows can carry identical numbers and require different settings to obtain, and a caller who omits the setting pays the ASAP rate. Every Sail row therefore carries pricingWindow naming the window its price came from, and latencyTolerance is an input to the query.

Measured from the pinned pricing document, 2026-09-03.
Sail models with pricesAll three windowsFewer windows
945

Five of the nine publish only one or two windows, so what you asked for is not always what is available. The rule is never slower than you asked for: a flex request will accept a balanced or asap price if that is all the model publishes, and pricingWindow says which one you got. An asap request is the strict case — a model that publishes only flex is left out of the answer rather than quoted at a price you could not obtain at that latency.

Roadmap — not built yet

Longer price history

Free-to-paid detection shipped in 0.2.0, and it compares the two most recent collection runs — so it answers “did anything change since the last collection”, not “what has this model cost over the past month”. 0.4.0 made that limit explicit in every answer rather than leaving it to be discovered, which is the honest version of the gap but not a closing of it. The archive retains a price observation per model per run, so a longer window — and the run dates that would let coverage actually be established — are a read away rather than new collection.

Automated switching

Deliberately out of scope for the server, which stays read-only so it can ship inside a distributed application without carrying a credential. The intended path is an agent that reads from here and writes to your own configuration — not a server that reaches into it.

Task-quality fitness

“Satisfies the criteria for the task” is currently as good as the criteria you can state: modality, context, tools, reasoning, availability. Whether a model is actually good enough at your task is not modelled, and a cheap model that passes every structural filter can still be the wrong choice.

Licence and source

MIT licensed. The package is published at npmjs.com/package/open-dashboard-mcp, and the server reads a public, zero-credential API; point it elsewhere with DASHBOARD_BASE_URL.

The repository is not public yet, so there is no source link to give you. Its history carries infrastructure names that have to come out before it can be opened, and deleting a file does not remove it from the commits behind it. Saying “open source” over a link that 404s would be the same kind of claim this page spends the rest of its length refusing to make.