Skip to main content
Glama

https://github.com/user-attachments/assets/6bfecd10-84a9-408b-b08c-ff9481648692


Why this exists

Every LLM cost calculator on the web has the same failure mode: it is a snapshot. Someone builds it, hard-codes a dozen model prices, and within a few months the entire premise is wrong — the models it compares have been superseded and the prices it quotes no longer exist.

PromptSpend is built the other way round. The pricing pipeline is the product; the calculator is what sits on top of it. Every morning a GitHub Action re-fetches the catalog from independent sources, merges them under an explicit trust order, runs sanity checks, and either commits the result or opens a pull request for a human. Capture patterns are family-level, so a brand-new model version is picked up automatically without anyone touching code.

Related MCP server: Model Price Watch

What it does

  • Receipt — copy a fully visible, one-response cost-audit object into an existing AI conversation. It estimates the visible workload, retrieves current PromptSpend prices, names the two largest cost drivers and suggests cheaper models worth testing without pretending price proves equal quality.

  • Estimate — describe one interaction (paste your real prompt or move the sliders), set your scale, and see the monthly, yearly, per-user and margin numbers for up to four models side by side.

  • Compare — every tracked model on a price-versus-capability value map, plus a sortable catalog you can select from directly, with the source and verification date for every row.

  • Learn — seven short interactive lessons on tokens, why output costs more, how wide the price spread is, compounding chat history, hidden reasoning tokens, caching and batching, and how the data pipeline works.

  • Free tiers — which providers let a new account start without paying, card rules, limits and whether free use trains their models, quoted word for word from each vendor's own pages with a link and date on every fact, and re-checked each morning. One comparison page and one page per provider; see docs/FREE_TIERS.md.

  • Data & Alerts — pipeline health, full provenance for every number with a link to the vendor page it came from, what is currently flagged, and four ways to hear about a price change: an Atom feed, the repository's own pull requests, browser push, and an email digest.

Price alerts

Opt-in, and off unless a deployment is configured for them. Browser push stores nothing personal — a push subscription is an opaque URL the browser issues. Email is double opt-in with one-click unsubscribe, and stores your address, the models you follow, and the date you asked; nothing else. Either channel can watch the whole catalog or just the models you pick.

The delivery service is a Cloudflare Worker in worker/, with the push payload encryption written out against RFC 8291 and checked byte for byte against the RFC's own worked example. docs/ALERTS.md has the architecture, the cost model and the domain cutover.

Things it does that most calculators get wrong

Output is priced separately

Output typically costs 3–5× input. Averaging the two, as many calculators do, understates most real workloads.

Chat history compounds

Turn N re-sends turns 1…N−1 as input, so conversation cost grows with the square of the turn count.

Tokenizers differ per family

The same pasted text is counted with each model's own tokenizer — exactly (js-tiktoken, run in your browser) for OpenAI-family models and with a clearly labelled calibrated ratio elsewhere.

Caching is not free

Cache writes cost 1.25× input at both OpenAI and Anthropic. Counting only the cheaper reads reports a saving your invoice will not have, so writes are billed and caching is off by default.

Long context costs more

Above 272K input tokens OpenAI bills the whole request at 2× input and 1.5× output. Tiers apply per request, so a conversation can cross over partway through.

Reasoning tokens are billable

A multiplier for hidden thinking tokens, because the visible answer is not what you pay for.

Promotional pricing expires

Introductory rates apply only inside their window, and the engine takes a date.

Assumptions are visible

Every non-published number used in a calculation is listed under the results, not buried — and so is what the prices do not cover.

Impossible scenarios are named

A request that will not fit the context window, or a response past the output ceiling, is flagged rather than priced as if it would work.

How the data stays current

                    ┌─────────────────────────┐
  LiteLLM catalog ──┤                         │
                    │   allowlist → merge →   │──→ public/data/pricing.json ──→ the app
  OpenRouter API ───┤   validate → diff       │
                    └───────────┬─────────────┘
  data/pricing-overrides.json ──┘            └──→ docs/pricing-changelog.md
       (hand-verified, wins)

The trust ladder, in order:

  1. Hand-verified vendor rates (data/pricing-overrides.json) — win every conflict.

  2. The LiteLLM community catalog — the automated daily feed; thousands of models, updated within days of a release.

  3. The OpenRouter API — an independent cross-check, never a source of record. Reseller pricing differs from first-party list pricing, so a disagreement of more than 20% flags the model rather than changing it.

  4. Sanity rules — schema validation, non-negative rates, implausibility checks, a review flag on any price that moved more than 50% in a single day, a floor on how many rows a source may return, and a cap on how much the catalog may shrink in one run.

A diff is committed and deployed automatically, flags included: there is no human gate on publication, on purpose, because a flag that held the whole catalog once left the site's dates two days behind. A newly raised flag publishes with everything else, marks that row disputed on the site, and opens an issue for review — a long-standing disagreement does not re-open one every morning. A run that loses a source or trips a size guard is degraded: it publishes nothing, records why in public/data/sync-status.json, and fails loudly. Either way the change lands in docs/pricing-changelog.md.

Nothing disappears on one bad morning. A model missing from the feed is kept and marked stale, not deleted; retiring one for good is a deliberate edit to data/models-allowlist.json.

Rung 1 is worked by hand, and the split is published rather than blurred. Every row says which rung it came from, and rows read against a vendor's own page carry the URL that was read and the date it was read. Most of the catalog is now vendor-sourced — but not all of it, because some vendors do not publish a pricing page that lists their own models, and the honest answer there is to leave the row labelled litellm rather than launder an aggregator's number into a first-party claim. The models this currently affects are named in docs/DEFERRED.md. A number is only worth what its worst source is, so the site shows you the source per row instead of an average you cannot inspect.

Something watches the promise

A daily job reads the live site — not the copy in this repository — and raises an issue if the published catalog is more than two days old. That distinction is the whole point. Between a price moving upstream and you seeing it, four things can fail: the sync errors, the sync cannot commit its result, the deploy fails after a green sync, or the CDN serves a stale artifact. Checking the file in git catches the first of those. Fetching what the site actually serves catches all four.

It exists because the sync once failed at its publishing step and nothing said so; the site quietly served a day-old catalog until someone happened to look. A project that claims its numbers are never a year out of date should be the first to know when they are.

Two dates, not one

The site shows prices last changed and sources last checked separately, because they answer different questions. A quiet week in the market makes the first date age while everything works perfectly; a broken scheduler looks exactly the same if you only publish one date. The second comes from a health manifest written on every run, successful or not:

https://promptspend.com/data/sync-status.json

Right now the first of those reads not yet recorded, and that is correct rather than broken. No vendor has moved a price since this catalog's history began on 2026-08-01, so there is no date to show — and the alternative, quietly displaying the last build date, would announce a price change every morning nothing happened. An empty field you can trust beats a populated one you cannot.

The second is now a state and not just a date: the chip on the results panel is green while the sources were checked within a day, blue at two days, amber past the window the freshness monitor tolerates or after a degraded run, and outlined-grey when the manifest could not be loaded at all. That last state exists on purpose. A status light that reads "fine" when its own evidence is missing is precisely the failure the monitor was built to catch.

Three things a number can do

Keeping "prices last changed" honest means the pipeline has to tell apart three events that all look like a diff:

What happened

lastChanged

Price change

Same source, different number. The vendor repriced.

stamped

Coverage

A field went from absent to present. We started recording a rate that was always offered.

untouched

Correction

The number moved in the same run its source URL did. We had been reading the wrong page.

untouched

Only the first is news. Conflating them is not hypothetical: reading x.ai's real pricing page instead of its model list once gained a long-context tier and restated a cached-input rate, and the catalog stamped both as price changes — putting PRICES CHANGED 2026-08-06 on the busiest panel of the site with no vendor having touched a rate. Suppressing corrections can hide a genuine same-day move, and that trade is deliberate: on a catalog whose whole claim is provenance, announcing a change nobody made costs more than missing one by a day.

Use the data yourself

There is a free, keyless, CORS-open API at promptspend.dev — no account, no key, no rate limit:

curl https://promptspend.dev/v1/prices          # flat rows: the numbers only
curl https://promptspend.dev/v1/models/gpt-5    # one model, in full
curl https://promptspend.dev/v1/prices.csv      # the same rows, for a spreadsheet

Filters: ?provider=, ?status=, ?aliases=include. Every response carries X-PromptSpend-Generated-At, and OpenAPI 3.1 lives at /openapi.json. See docs/API.md.

Or drop a price badge in your own README

claude-opus-5 price

[![claude-opus-5 price](https://promptspend.dev/badge/claude-opus-5.svg)](https://promptspend.dev/)

Swap the model id for any id from /v1/models. The badge is drawn fresh on every fetch — no cache — so the date it shows is always the day that price was last confirmed.

Or inside your coding agent

claude mcp add promptspend -- npx -y @promptspend/mcp

Other pricing MCP servers exist and index more models than this one. What none of them do is tell you where a number came from and when it was last confirmed — the competing server's own documentation says only that pricing "is updated regularly", with no verification date per price. That gap is the reason this exists.

It matters more to a model than to a person. Someone reading a web page sees the interface around a figure and calibrates. A model handed a bare number repeats it with whatever confidence the sentence implies. Given the source and the date it can say "as of 1 August, per OpenAI's pricing page" — and when two sources disagree it is told so, rather than being handed a number somebody picked.

Three tools, deliberately. estimate_cost is the one a price lookup cannot provide: it runs this repository's cost engine, imported rather than reimplemented, so it accounts for compounding conversation history, cache writes, long-context tiers and reasoning tokens — and cannot report a figure that disagrees with the calculator, because it is the same code. A test asserts that.

And because MCP tool definitions load into your context on every turn, the server's own overhead is measured, budgeted at 900, checked in CI and published: ~700 tokens. Nothing else in the ecosystem appears to publish its own footprint. See mcp/README.md.

Or in your editor

The same catalog, on the line of code that chooses the model.

response = client.messages.create(
    model="claude-sonnet-4-6", # $3 / $15 per M · max out $0.061
    max_tokens=4096,
)

A linter for model choice rather than a calculator in a sidebar — a calculator in an editor is only this website with worse ergonomics. What an editor can do that a web page cannot is notice things: a nearby max_tokens becomes the output ceiling in money, a cap above what the model can emit is named rather than priced as though it would work, deprecated and disputed rows reach the Problems panel, and an Explorer view lists every model the repository calls, dearest first.

Everything it says is Information severity, never a warning. None of these are mistakes and the extension has no idea what the code needs. The cheaper-model suggestion is off by default for the same reason the value map's capability axis is labelled illustrative: it is an opinion, where the rest are facts.

code --install-extension promptspend.promptspend

Or search PromptSpend in the Extensions pane. It is on Open VSX too, which is where Cursor, Windsurf and VSCodium look.

Same rule as everywhere else — no bundled prices. If the catalog cannot be reached it says so and shows nothing, and the status bar carries the generation date at all times. See vscode/README.md.

Or on your phone

Native apps for iPhone and Android, free on the App Store and Google Play: paste a sample conversation, compare up to four models, and see the cost per conversation, day, month and year from the same catalog. Pasted text is processed on the device and never uploaded. Both are described at promptspend.com/app; the source is in apps/mobile/.

Or read the file the API reads. The catalog is plain, versioned JSON with a stable shape:

https://promptspend.com/data/pricing.json
{
  "schemaVersion": 2,
  "generatedAt": "2026-08-02T02:27:22.781Z",
  "providers": [{ "id": "openai", "name": "OpenAI", "country": "US", "pricingUrl": "https://…" }],
  "models": [
    {
      "id": "gpt-5.6-terra",
      "providerId": "openai",
      "displayName": "GPT-5.6 Terra",
      "status": "current", // current | legacy | deprecated
      "contextWindow": 1050000,
      "pricing": {
        "input": 2, // USD per 1M tokens
        "output": 12,
        "cachedInput": 0.2,
        "cacheWrite": 2.5, // writing costs *more* than sending
        "batchDiscount": 0.5,
        "longContext": { "thresholdTokens": 272000, "input": 4, "output": 18 },
      },
      "tokenizer": { "kind": "tiktoken", "encoding": "o200k_base" },
      "provenance": {
        "source": "vendor", // vendor | litellm | openrouter
        "lastVerified": "2026-08-01", // when it was checked — always present
        "lastChanged": "2026-08-01", // optional: when the number last moved
        "verifiedUrl": "https://developers.openai.com/api/docs/pricing",
      },
    },
  ],
}

Optional fields worth knowing: aliasOf marks an id that routes to another model (so it is not counted twice), provenance.stale marks a row upstream has stopped listing, and provenance.needsReview plus reviewNote carry an unresolved disagreement and both numbers involved.

provenance.lastChanged is optional too: it is present only on a model whose rate has actually moved since this catalog's recorded history began on 2026-08-01, and absent otherwise. Read its absence as "no change on record", never as "unknown freshness": lastVerified answers that, and it is always there. A field that reported the last sync instead would read "changed today" every morning, which is the one failure a provenance catalog cannot afford — so it stays empty until a rate actually moves.

Running it locally

npm ci                 # `ci`, not `install` — this repo has a lockfile and CI honours it
npm run dev            # http://localhost:5173
npm run verify             # exactly what CI runs, and what the deploy gate runs
npm run sync:pricing:dry   # see what today's sync would change, without writing

verify is typecheck, lint, format check, an encoding check, tests with coverage thresholds, the published test counts, the published page counts, a production build, catalog schema validation, the bundle budget, the Content Security Policy and the SEO checks. The deploy workflow calls the same reusable workflow CI does and publishes the artifact it produced, so a commit that fails any of them cannot reach the live site.

It does not run the other packages' suites — CI has a job each for api/, mcp/, updates/, vscode/ and worker/. See CONTRIBUTING.md.

Project layout

src/lib/engine/     the cost engine — pure functions, no React, heavily tested
src/receipt/        the transparent Receipt object, page and versioned instruction contract
receipt/            the second Vite HTML entry, published as /receipt/
src/lib/tokenize/   exact tokenizer (lazy-loaded) + calibrated ratios
src/lib/pricing/    catalog schema, validation, lookups
src/lib/alerts/     browser-side push and alerts API client
src/components/     the four views
src/lib/seo/        the generated pages: slugs, page model, HTML renderer
scripts/            the daily sync pipeline (scripts/lib is unit-tested)
data/               capture patterns and hand-verified overrides
public/data/        the published catalog the app reads
public/sw.js        service worker — push display only, no offline cache
worker/             the alerts API (Cloudflare Worker, own package and tests)
api/                the public pricing API on promptspend.dev (own package and tests)
updates/            the app's self-hosted over-the-air update server (own package and tests)
src/state/          the scenario hook, and the URL it mirrors itself into
tests/              the browser suite: Playwright at four viewports, plus axe
tools/              the promo pipeline — capture, render, stitch
mcp/                the MCP server — imports the engine above, so it cannot disagree with it
vscode/             the VS Code extension — imports it too, for the same reason

Beyond the calculator and Receipt, the build writes 351 crawlable pages — one per model, one per provider, and a curated set of head-to-heads — from the same catalog and the same cost engine. See docs/PAGES.md.

Design and accessibility

Cobalt on a cool-paper canvas, with a distinct set of money colours that never change with branding: green means savings, red means this option costs more. The input/output chart pair is validated for colour-vision deficiency in CI — src/lib/palette.test.ts simulates protanopia and deuteranopia and fails the build if the two marks stop being distinguishable.

src/lib/contrast.test.ts reads tokens.css directly and fails the build if any accent, on any theme and any canvas, drops below 4.5:1 against a surface it can appear on. Every interactive target is at least 24×24 (44×44 on touch), no text renders below 12px, and there is no horizontal page scroll from 320px up. Keyboard navigation throughout — including every point on the value map, which is a real button — focus is returned when a dialog closes, prefers-reduced-motion is respected in JavaScript as well as CSS, and there is a Ctrl/Cmd+K command palette.

Documentation

Document

What is in it

docs/ARCHITECTURE.md

How the pipeline, the engine and the state layer work, and why each is shaped that way

docs/TESTING.md

What the 1570 tests cover, the uneven coverage thresholds, and what the suite deliberately does not cover

docs/TROUBLESHOOTING.md

"The estimate does not match my bill", flagged prices, missing models, running it locally

docs/PAGES.md

The 351 generated pages: what is built, why the comparison set is curated, and the IndexNow pipeline

docs/API.md

The public pricing API on promptspend.dev — endpoints, why it fetches rather than bundles, going live

docs/DOMAINS.md

What each hostname serves and why, plus the cutover runbook and rollback

docs/ALERTS.md

The price-alerts Worker — push and email architecture, the cost model, the domain cutover

docs/pricing-changelog.md

Every price change the daily sync has published, written by the pipeline itself

docs/PRICE_HISTORY.md

The same history as a citable CSV (CC0): its columns, units, and what the data does and does not claim

CHANGELOG.md

Changes to the application, as opposed to the data

docs/DEFERRED.md

Work proposed and deliberately not done yet, with the reason — a decision, not a gap

docs/FREE_TIERS.md

The free-tier pages: where the facts live, the daily quote check, and how to update a record

docs/ACCOUNTS_PLAN.md

The plan for user accounts: sign-in, where it must live, data, duties, phases. Not built yet

docs/SPONSORS.md

The sponsor policy: never in the data, always labelled, one slot per page. No sponsor yet

docs/AUTOMATION.md

What runs by itself while working on the project: the hooks, /ship, the reviewers, the test-count self-fix, and the Worker deploy

docs/PROMO.md

How the promo video is built from real screenshots, and how to rebuild it

mcp/README.md

The MCP server — pricing for coding agents, with the source and date on every number

vscode/README.md

The VS Code extension — prices on the line of code that chooses the model

CONTRIBUTING.md

Adding a model, the house style, and the rules that are not negotiable

SECURITY.md

What is in scope — including a wrong price, which is treated as the most serious class of bug

Contributing

Adding a model is usually a one-line change. See CONTRIBUTING.md, or open a model request and someone will pick it up.

Not a code change? info@promptspend.com. Security reports go to security@promptspend.com or GitHub's private vulnerability reporting — see SECURITY.md.

The three rules that are not up for negotiation, because breaking any of them turns an estimator into a guess with good typography:

  1. Never invent a rate. If a provider does not publish a number, charge full price and say so.

  2. A claim on screen must be true of the code. When behaviour and copy disagree, fixing the copy is a legitimate fix; leaving both is not.

  3. No enabled control that does nothing. Describe a planned feature — do not simulate it.

Honest limitations

The point of this section is that it is longer than it needs to be. An estimator that hides its edges is just a confident guess.

  • Scope of the prices. Standard-tier, global-endpoint list prices in USD. Not modelled: regional and data-residency premiums (OpenAI and Anthropic both charge 1.1×), fast/priority tiers, server-side tool call fees, fine-tuning, and negotiated or committed-use discounts. The site says this under every estimate, not only here.

  • "Exact" means exact raw text. The tokenizer counts the string you give it. A real request also bills message framing, tool definitions and any images. Treat an exact count as a floor.

  • Token counts for non-OpenAI families are estimates from calibrated characters-per-token ratios, labelled as such everywhere they appear. Those providers do not ship a browser-runnable tokenizer.

  • The capability axis on the value map is illustrative, not a benchmark. Models without an estimate are not plotted at all rather than being given a default, and the chart says how many that is.

  • Caching is off by default and the estimate charges cache writes where a provider publishes a rate. Where one does not, cached tokens are billed at the full input rate rather than at an invented discount. Providers that bill cache residency separately are labelled with that per-hour rate; it is excluded from the estimate until a retention duration is known, and enabling caching raises an explicit warning.

  • Long-context tiers are modelled where they are published (per request, not per conversation). Where a provider has a tier we have not recorded, the estimate says so instead of quietly using the flat rate.

  • The Receipt sees a transcript, not an invoice. It cannot see hidden system prompts, provider-side tools or media, cache usage, hidden reasoning, or an exact billable model unless the conversation exposes them. It reports ranges and exclusions, and refuses to invent a dollar amount when current pricing is unavailable.

  • Exact counting downloads a ~3 MB tokenizer chunk, and only when you paste text for an OpenAI-family model. The initial page is about 100 KB gzipped, and CI fails if it passes 105.

Privacy, precisely

Nothing you type or paste leaves your browser. No accounts, no ads. Fonts are self-hosted. One image is not: the footer's LaunchNest listing badge loads from launchnest.io (their directory requires it), with no referrer, so LaunchNest's server sees a visitor's IP address but not which page they were on.

The website counts visits with Google Analytics, which sets cookies. Since 2026-10-24 every page of promptspend.com loads Google Analytics 4 and shows a small notice saying so, with a link to the privacy policy and a Turn off button. Google Analytics sets two cookies (_ga, _ga_08GFGLY4VD). PromptSpend's code sends it the page's site and path only — never the query string or #fragment, where the scenario and alert tokens live — plus the page title and referring page (cut down the same way); it switches off GA's automatic page view, Google signals and ad personalisation, and passes it nothing anyone types, pastes or enters in a form (src/lib/analytics/). It runs only on promptspend.com, never when the browser sends Global Privacy Control, and one line in src/lib/analytics/config.ts (ANALYTICS_REQUIRES_CONSENT) switches it to loading only after a visitor clicks Accept. Visitors can turn it off on the notice, on the privacy page, or with Google's own opt-out add-on.

The website also keeps Cloudflare Web Analytics, a cookieless beacon that reports a page's address (without its query string or fragment), referrer, country and load timings to promptspend.com's own /cdn-cgi/rum; neither service sees pasted text. The apps, the VS Code extension, the MCP server and the API carry no analytics. Pasted prompt text is tokenised in your browser, deliberately excluded from the shareable URL, held in a bounded in-memory cache, and gone when you close the tab. localStorage holds only interface choices: your theme, accent and background, whether you dismissed the welcome and apps banners, and your answer to the analytics notice.

Price alerts are the one exception, and only if you opt in. They are a feature you have to switch on, and they are the only reason this project has a server that stores anything (a Cloudflare Worker — docs/ALERTS.md); the pricing API stores nothing but Cloudflare's request logs (kept up to seven days), and the apps' update server has its logging switched off. Precisely what changes:

  • The Content Security Policy opens connect-src for that one API origin and, whenever an API is configured, script-src, connect-src and frame-src for Turnstile's challenges.cloudflare.com (whether Turnstile is actually required is decided at runtime, so the build permits it). Beyond that, the remote origins are img-src for the LaunchNest badge, script-src for the Cloudflare beacon (which posts only to this site), and Google Analytics: www.googletagmanager.com for gtag.js (in script-src, and in connect-src and img-src as Google's guidance asks), and its collection hosts (www.google-analytics.com, region1.google-analytics.com, region1.analytics.google.com) in connect-src and img-src, each named rather than wildcarded. That connect-src line is what stops a compromised dependency exfiltrating a pasted prompt, so it is generated from configured values rather than hand-maintained, and npm run check:csp fails on any origin it does not list. Admitting Google's collector is a real cost — a script that got onto the page could post to an analytics account of its own — accepted on 2026-10-06 for visit counts.

  • Browser push stores nothing personal. A push subscription is an opaque URL the browser issues. No address, no name, nothing that identifies you.

  • Request logs. Alert links carry a private token in their address, so the alerts Worker keeps no per-request logs (invocation_logs is off) and its own messages log counts and error types, never an address. The public pricing API keeps Cloudflare's request logs, retained for up to seven days (Cloudflare's published maximum), because its addresses carry no secrets and they are how faults get diagnosed.

  • Email stores your address, the models you follow, and the date you asked. That is the whole record. No name, no raw IP (consent is recorded as a salted hash), no opens, no clicks. Cloudflare hosts the database and sends the mail; no other company receives it. Double opt-in, one-click unsubscribe, and unconfirmed addresses are deleted within a week.

  • The alerts form never sees anything you paste into the estimator. Those are different parts of the page and the prompt text never leaves the browser.

A deployment with no API configured — which is what this repository builds by default — leaves the alerts API and Turnstile out of its policy (the analytics and badge origins above stay) and says on screen that alerts are not switched on, rather than rendering a form that cannot work.

Security

See SECURITY.md. Wrong prices are treated as the most serious class of bug this project can have, and are explicitly in scope for a report.

Licence

MIT — see LICENSE. The self-hosted typefaces (Space Grotesk, IBM Plex Sans, JetBrains Mono) are SIL Open Font License 1.1.

Available Tools

3 tools
estimate_costA
Read-only

What a described workload actually costs per month on each model. Accounts for conversation history compounding, cache writes, long-context tiers and reasoning tokens. Use this instead of multiplying prices by hand.

NameRequiredDescriptionDefault
turnsNoTurns per conversation. Default 4.
modelsYesModels to compare, up to about 8.
user_tokensNoTypical user message. Default 150.
output_tokensNoTypical reply. Default 350.
system_tokensNoSystem prompt size. Default 800.
use_batch_apiNoApply batch discounts. Default false.
cached_input_shareNo0-1. Default 0.
reasoning_multiplierNoBill output at this multiple. Default 1.
conversations_per_dayNoDefault 1000.

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered; the description adds real modeling behavior beyond that, disclosing that the estimate compounds conversation history, accounts for cache writes, long-context tiers and reasoning tokens. It does not state the currency or the shape of the returned comparison, leaving a small gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with what the tool produces, then the modeling factors, then the call to action. Every sentence carries information the agent cannot get from the schema or annotations.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With nine optional-or-required numeric parameters fully documented in the schema and no output schema, the description supplies the missing conceptual layer: what the estimator simulates and which factors it models. Currency and output shape are unstated, but the schema and a 'per month on each model' framing cover enough for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so a baseline of 3 applies, but the description earns a bump by explaining the mechanisms behind several parameters: history compounding (turns), cache writes (cached_input_share), long-context tiers, and reasoning tokens (reasoning_multiplier). This tells the agent why those knobs matter, not just what they are.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific computation ('what a described workload actually costs per month on each model'), which is more than a restatement of the name and clearly implies a multi-model comparison output. It does not explicitly contrast with the siblings get_price and find_cheaper, so an agent must infer that this is the multi-model workload estimator rather than a single-price lookup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use this instead of multiplying prices by hand' gives one clear usage condition, but the alternative it names is a manual process, not the sibling tools. Nothing tells the agent when to prefer get_price or find_cheaper, and there are no exclusions stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_cheaperA
Read-only

Cheaper models that score at or above the given one on capability, costed on the same workload. Returns candidates to test, not a recommendation.

NameRequiredDescriptionDefault
modelYesThe model currently in use.
turnsNoDefault 4.
user_tokensNoDefault 150.
output_tokensNoDefault 350.
system_tokensNoDefault 800.
min_capabilityNo0-100. Defaults to the given model’s score.
conversations_per_dayNoDefault 1000.

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already establish readOnlyHint=true and openWorldHint=true. The description adds useful behavioral context by clarifying that results are candidates for testing rather than a recommendation, but it does not disclose ranking, limitations, or output shape.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences, with the core purpose front-loaded and the important caveat immediately following. There is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a seven-parameter retrieval tool with no output schema, the description gives only a high-level indication of what is returned. It is sufficient to understand the tool's intent, but it does not describe the candidate result structure or any workload assumptions beyond the schema defaults.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all seven parameters are already documented, including defaults and the min_capability behavior. The description reinforces the capability threshold and workload basis but adds no parameter-specific semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific task: finding cheaper models that meet or exceed the given model's capability, costed on the same workload. It also clarifies the return is test candidates, not a recommendation, which distinguishes it from the price/cost siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied by "cheaper models that score at or above the given one," but there is no explicit when-to-use or when-not-to-use guidance relative to get_price or estimate_cost. The caveat "Returns candidates to test, not a recommendation" helps interpretation but not tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_priceA
Read-only

List price for one LLM in USD per million tokens, with its source and last-confirmed date. Returns disputed=true when two sources disagree, and close matches when the model is unknown. To cost a workload, use estimate_cost.

NameRequiredDescriptionDefault
model_nameYesModel id or name, e.g. gpt-5 or "Claude Opus 5".

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real behavior beyond the readOnly/openWorld annotations: it advertises the disputed=true disagreement signal, a close-matches fallback for unknown models, and provenance via source and last-confirmed date. It stops short of saying whether the base price is an average or a preferred source when sources agree.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The primary capability is front-loaded and the routing note trails it, which is the right ordering.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does so for the headline fields (price, unit, source, date, disputed, close matches). What the close-match payload looks like and how ambiguity is resolved is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter and schema coverage is 100%, with the schema already giving id-or-name examples. The description adds unit framing for the returned price but nothing about model_name syntax or edge cases (aliases, versions), so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List price for one LLM') plus the unit basis (USD per million tokens), which immediately separates it from estimate_cost and find_cheaper. An agent knows exactly what it retrieves without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly redirects workload costing to estimate_cost, giving a clear when-not-to-use condition. It says nothing about find_cheaper, so the sibling triage is only two-thirds complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.1.1
    • Changedfind_cheaper5 fields changed
      • addedInput schema / properties / conversations_per_day / description
        Added value: +"Default 1000."
      • addedInput schema / properties / output_tokens / description
        Added value: +"Default 350."
      • addedInput schema / properties / system_tokens / description
        Added value: +"Default 800."
      • addedInput schema / properties / turns / description
        Added value: +"Default 4."
      • addedInput schema / properties / user_tokens / description
        Added value: +"Default 150."
  2. 3 tool updatesv0.1.0
    • First observedestimate_cost
    • First observedfind_cheaper
    • First observedget_price

TDQS

A4.2/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct role: raw price lookup, workload-based cost estimation, and cheaper alternative discovery. The descriptions explicitly cross-reference each other to prevent confusion, especially get_price vs estimate_cost.

Naming Consistency5/5

All three tools follow a consistent verb_noun snake_case pattern: get_price, estimate_cost, find_cheaper. The naming is predictable and easy to scan.

Tool Count5/5

Three tools is a well-scoped set for an LLM pricing/cost-estimation server. Each tool earns its place by covering a distinct step in the workflow: price lookup, workload costing, and alternative comparison.

Completeness4/5

The core lifecycle is covered: inspect prices, estimate real workload costs, and find cheaper capable alternatives. A minor gap is the absence of a list/browse operation for discovering available models, though get_price offers close matches for unknown models.

Maintenance

ActivityActive
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Live LLM API pricing: current token prices, model comparisons, cheapest-model lookups, and The LLM Price Index for 150+ models across 20+ providers, re-verified daily. No API key required.
    4
    1
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A local-first, multi-provider cost meter for LLM usage, exposed as MCP tools. Captures every call into a local SQLite ledger and lets any coding agent query spend, compare providers, and get recommendations — no cloud, no account. First-class support for Chinese providers (Qwen, DeepSeek) alongside Anthropic and OpenAI.
    7
    53 PyPI
    6
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables agents to rank model variants and hunt down API offers for a specific task, estimate real billed cost, audit n8n/Make automations for overpay, missing fallbacks and deprecated models, and plan or run evaluation and canary suites on the user's own examples. It also supports price comparison, custom reseller channels with measured per-call cost, and non-LLM capabilities such as web search and speech-to-text.
    AGPL 3.0