mcpcost
mcpcost provides read-only tools to measure MCP server context-token cost and explore the public MCP registry board.
Measure one remote or local MCP server now: status, protocol version, tool count, token estimate or exact Claude count, latency, and top tools.
Measure every server in an MCP config file, with per-server and total token cost/share.
Look up a registry server by name or URL for its latest board probe, auth/access details, and token cost.
Search and rank registry servers by words, status, sort order, and page.
Compare 2–5 servers side by side, including cheapest, most expensive, spread, and JSON/Markdown/CSV output.
Summarize the whole registry: statuses, auth methods, protocol versions, transports, token percentiles, and heaviest servers/publishers.
This server has a remotely hosted endpoint. Open its connector listing for connection details, authentication requirements, and setup instructions:
mcpcost
Is that MCP server alive, and what does it cost your context window?
Live board: mcpcost.ulehla.dev
mcpcost probes every remote server in the official MCP registry and records, for each one:
whether it answers
initializeandtools/list, and how fastthe protocol version it negotiates
whether it needs auth, which scheme (from
WWW-Authenticate), and how a client gets in: OAuth with dynamic client registration, OAuth with a client id from the publisher, or a key, read from the server's public OAuth metadatawhether it asks for payment (HTTP 402)
how many tools it has and how many tokens their definitions cost
mcpcost: what do your own servers cost?
npx mcpcost # reads Claude Code, Claude Desktop, Cursor, VS Code, Windsurf and Gemini CLI configs
npx mcpcost --config .mcp.json # one file
npx mcpcost --budget 30000 # exit 1 when the total is above the budget, for CI
npx mcpcost --claude # exact counts from the Anthropic count_tokens endpoint (free, needs ANTHROPIC_API_KEY)
npx mcpcost mcp # the same measurements as an MCP server over stdio, for your agentIt starts every configured server the way your client does, lists the tools and prints the token cost per server and in total. See packages/mcpcost.
Servers that need auth
A server that answers 401 is reachable but not measured until it gets credentials. Store them once; every later measurement of that URL uses them.
npx mcpcost auth https://mcp.linear.app/mcp # OAuth: register, consent in the browser, store the tokens
npx mcpcost auth https://api.githubcopilot.com/mcp/ --header "Authorization: Bearer ghp_…" # an API key instead
npx mcpcost auth --list # what is stored, without the secretsThe OAuth flow follows the MCP authorization spec: discovery, dynamic client registration, PKCE, a callback on 127.0.0.1. The consent screen is the one step that needs a person. After it, the tokens live in ~/.mcpcost/credentials.json (mode 0600, or $MCPCOST_CREDENTIALS), npx mcpcost sends them for that URL, and a refreshed token goes back to the file.
The board does the same: npm run credentials:push copies the file into the D1 table credentials; the daily run reads it before the probe, writes the refreshed tokens back after it, and marks the server "measured with credentials". A refresh token that a service revokes or lets expire needs the consent step again.
Without credentials, the board still shows a tool set for many gated servers: tool definitions do not depend on the token, so when the publisher's repository holds a package on npm or PyPI, probe/derive-packages.ts finds it and the weekly container run measures it with placeholder values. The server page then says "from the publisher's package". probe/derived-aliases.json maps the few servers whose registry entry names no repository.
In CI, as a GitHub Action
- uses: ondraulehla/mcpcost@v1
with:
config: .mcp.json # one or more config files, one per line
budget: 30000 # fail when the tool definitions cost more than thisThe job summary gets a table with every server, its result and its cost, plus the most expensive tools. A pull request that adds a 40 000-token server fails the check. Set claude: true and put ANTHROPIC_API_KEY in env for exact counts from the free count_tokens endpoint; the default is the o200k_base estimate. Outputs: tokens, servers, over-budget.
On a pull request the action also measures the same config files on the base branch and posts one comment with the difference: servers added, removed and changed, the token delta per server, the new total and the budget verdict. The comment is updated on every push, never duplicated. The job needs pull-requests: write for it; without that permission the step warns and the check still runs. Set comment: false to turn it off. A complete workflow is in .github/examples/mcp-budget.yml.
In Claude Code, as a plugin
In a Claude Code session:
/plugin install mcpcost --marketplace ondraulehla/mcpcostOr from the shell: claude plugin marketplace add ondraulehla/mcpcost, then claude plugin install mcpcost@mcpcost.
The plugin adds one skill, /mcpcost:measure, which runs npx mcpcost on your configs and reads the result, and the board's MCP server, so Claude can look up or probe a server before it goes into a config. What the plugin itself costs: one skill description in the context, and four tools that Claude Code defers behind tool search.
Related MCP server: nikhilnt
The board
mcpcost.ulehla.dev is rendered on the edge from a D1 database and refreshes every night. The only scripts it loads are a theme switch and the Cloudflare Web Analytics beacon, which counts page views without cookies.
Overview: the share of servers that answer, token cost percentiles, and a form to check any server
Check: probes one URL live, with the same steps as the daily run; the exact token count runs in the browser
Statistics: results by cause, token cost and tool count percentiles, the heaviest tool sets, protocol versions, auth schemes, transports, biggest publishers
Servers: full-text search over name, title, description and host (word prefixes, so
git copilotfinds the GitHub Copilot servers), filters by result, protocol and transport, seven sorts, and every filter is a plain URL you can shareServer page: status, latency, protocol, capabilities, the most expensive tools, servers with the same tool set, history, the badge, and e-mail alerts: a mail when the server stops answering, comes back, or its tool set or token cost changes
Compare: two to five servers side by side, status, access, tools, exact tokens, share of a 200k window, latency, with the cheapest and the spread;
/compare?s=<name>&s=<name>, linked from every server pageTrack: a server that is not in the registry can be tracked from the check page; the daily probe then measures it under the name
url/<host>/<path>Hosts: the 500 biggest publishers with how many distinct tool sets they actually serve
Report: one page a month, The state of the MCP registry, read from the daily runs, with a CC BY 4.0 dataset of every server
For agents and scripts
JSON:
/api/s/<name>.json,/api/lookup.json?url=…(the board's row for an endpoint URL, no probe),/api/servers.json?q=…&status=ok&sort=tokens,/api/check.json?url=…,/api/summary.json. The list API takes at most 6 requests in 10 seconds from one address; its answers are cached for three hours.Re-check evidence for the registry, the newest run:
/data/mcpcost-evidence-latest.json.gz(the row shape of modelcontextprotocol/registry#1715, changes after each daily run), with its index/data/mcpcost-evidence-latest.index.json.MCP server over Streamable HTTP, no auth:
https://mcpcost.ulehla.dev/mcpwith the toolslookup_server,search_servers,compare_servers,check_server,registry_summary. The manifest for the registry issite/server.json./llms.txtlists all of it./tokensanswers the general question: how many context tokens does an MCP server cost.
Each server on the board gets a page and a badge:
[](https://mcpcost.ulehla.dev/s/io.github.you/your-server)First full run, 2026-10-03
The registry held 38 942 latest entries. 24 294 of them have a remote endpoint, and the probe connected to all of them in 40 minutes.
Result | Servers | Share |
alive: | 12 975 | 53 % |
needs auth (401, 403) | 5 836 | 24 % |
not MCP: HTTP 200 but no valid MCP reply | 1 800 | 7 % |
not found (404, 405, 410) | 881 | 4 % |
no DNS | 728 | 3 % |
rate limited (429) | 500 | 2 % |
payment required (402) | 434 | 2 % |
server error (5xx) | 349 | 1 % |
other | 307 | 1 % |
TLS error | 259 | 1 % |
timeout | 204 | 1 % |
refused | 21 | 0 % |
Of the 12 975 servers that answered:
the median tool set costs 1 727 tokens, the 90th percentile 7 429, the 99th 28 200
208 servers cost more than 20 000 tokens, 46 more than 50 000, and 3 more than a whole 200k window
the heaviest is
com.replynodes/mcp: 66 tools, 431 925 tokensthe median server has 8 tools, the largest 1 385
median
initializelatency is 455 ms, the 90th percentile 1.5 s60 % negotiate protocol
2025-11-25, 24 % still2025-03-26, 4 %2024-11-05122 servers answer with protocol
2026-07-28, which the current TypeScript SDK rejects
The registry is lumpy. 16 161 of 16 534 hosts publish one server. Five hosts publish more than 6 000 entries between them: one Workers subdomain with 2 365 near-identical entries, a gateway with 1 716 entries of which 1 321 return a JSON-RPC error on initialize, and a host with 276 entries that all answer 402.
The monthly report and the dataset
/report/2026-10 is The state of the MCP registry, October 2026: the registry in numbers, what changed between the first full run and the run of 2026-10-31, token cost, auth, the lumps, protocol versions, what the registry does not catch, and the method in six sentences. The page reads only the runs table (the runs of the month up to the run day, one query) and is cached for a day, so it costs nothing on the free tier. /report lists the months; site/src/lib/reports.ts has one entry per report with the day of the run it is pinned to. The dataset that goes with it, data/mcpcost-2026-10.json.gz on the site, has one row per probed server: name, host, transport, status, HTTP status, auth scheme and kind, protocol version, tool count, the o200k estimate, the exact Claude counts and the probe time. A row's numbers are what /api/s/<name>.json gives for that server on that day. The licence is CC BY 4.0; the document carries the licence, the field list and a citation at the top. probe/dataset.ts writes data/latest/dataset.json and its gzip on every daily run (kept in the run artifact), and --publish site/public/data/mcpcost-YYYY-MM.json.gz copies the gzip into the site when it is under 10 MB: a static file is served before the Worker and costs no request. A bigger file would go out as a GitHub release asset instead. To publish a month: run the probe or download the run artifact into data/latest, run node --import tsx probe/dataset.ts --publish site/public/data/mcpcost-YYYY-MM.json.gz, add the month to reports.ts, write the page, and commit the file with it.
The same run goes out as re-check evidence for the registry, in the row shape agreed in modelcontextprotocol/registry#1715: entry, checked_at, check (endpoint or package), state (alive, auth, transient, dead, unknown) and evidence. probe/dataset.ts writes it daily next to the dataset, and the month's copy is /data/mcpcost-evidence-YYYY-MM.json.gz. The newest run is always at /data/mcpcost-evidence-latest.json.gz, with /data/mcpcost-evidence-latest.index.json next to it (run date, entries per state and per check, size, SHA-256, shape). Neither file is in git. The probe keeps the file as the artifact evidence-<run id>, and deploy.yml puts it into site/public/data before every build: after each successful probe run, and on each push, so a push does not take it off the site. probe/evidence-latest.ts refuses a file that is not whole, and the site then keeps the file it has. A deploy after a probe run builds main as it is, the same as a manual deploy, and it is its own workflow run, so it cannot fail the probe.
How it works
registry ──▶ probe/run.ts ──▶ data/raw/probe-run.json
│
probe/build-data.ts
│
data/latest/{servers,summary,hosts}.json
│
probe/to-sql.ts ──▶ import.sql ──▶ D1
│
site/ (Astro on Workers) ◀────────┘packages/mcpcost/the library and the CLImcpcost: registry client, remote and stdio probe, config discovery, token countingprobe/the batch runner and the data pipelinesite/the board: Astro 7 with the Cloudflare adapter on Workers, rendered from D1 with FTS5 search, SVG badges, no client JavaScript beyond the theme switch and the analytics beacon.github/workflows/probe.ymlruns the whole pipeline daily: probe, counts,build-data,to-sql, the D1 import. The run'ssummary.json,servers.jsonandhosts.jsongo up as a workflow artifact; the next run diffs against it and imports only the rows that changed, inside the free tier's 100 000 row writes a day.github/workflows/deploy.ymldeploys the site whensite/changes
Methodology
Transport. The probe uses the official TypeScript SDK as a client. Streamable HTTP first, SSE when that is the only remote.
No GET stream. The probe answers 405 to the SDK's standalone GET, so it never opens a server-to-client stream. The probe needs no server-initiated messages, and some servers stall
tools/listwhile that stream is open (DeepWiki held it for 15 s and never answered the POST meanwhile).Exact token count. The daily run asks the Anthropic
count_tokensendpoint for every alive server, and the GeminicountTokensendpoint whenGEMINI_API_KEYis set (the CLI:--gemini). Anthropic first: one request with the server's tools plus a marker tool, one with the marker tool only, and the difference is what the tools cost inclaude-opus-5-5. A second count uses Claude Code'smcp__<server>__prefix on each tool name. The endpoint is free and calls no model. A server is counted again only when its tool definitions change. About 5 % of servers publish a schema the endpoint refuses; they show the estimate and the reason.Estimate. Each tool is serialised as compact JSON with
name,descriptionandinput_schema, and counted with theo200k_basetokenizer. The exact count is about 1.9 times the estimate at the median. The estimate needs no key and is the same for every server.Same tool set. A hash of the sorted tool names and schema sizes marks servers that serve identical tools under different names.
Timeouts. 15 seconds per request. At most one probe runs against a host at a time.
Getting access. For a server that answers 401 or 403, the probe reads the OAuth protected-resource metadata (RFC 9728) and the first authorization server's metadata (RFC 8414, then OpenID discovery): authorization servers, scopes, the publisher's guide, dynamic client registration (RFC 7591), PKCE, grant types. The server page shows it as "Getting access", the JSON API as
authKindandauthMetadata. Two to four small requests, no token, no consent; the probe result does not change.Identification. Every request carries the User-Agent
mcpcost/<version> (+https://github.com/ondraulehla/mcpcost). To exclude a server, open an issue with its registry name.
Run it
npm install
npm run probe -- --sample 200 --per-host 2 # a sample, results in data/samples/
npm run probe -- --all --out data/raw/probe-run.json
node --import tsx probe/build-data.ts --in data/raw/probe-run.json --out data/latest
node --import tsx probe/to-sql.ts --in data/latest --out data/latest/import.sql
npm test --workspaces --if-presentSite, locally against a local D1:
cd site
npm run db:schema:local && npm run db:import:local
npm run devThe MCP endpoint answers initialize, tools/list, ping and the notifications from site/src/lib/mcp-snapshot.json, without the SDK; every other request goes to the SDK. The snapshot must be the SDK's own answers, or the site build fails: after a change to a tool definition, run npm run mcp:snapshot -w site and commit the new file in the same commit. npm test -w site, which the build runs too, holds the two answers side by side, byte for byte.
A shared link shows a card: a 1200x630 PNG in site/public/og/. There is a default card, and a card each for the October report, Compare and Statistics. site/src/lib/og.ts lists the cards and their text. The layout puts the card of a page into og:image and twitter:image; a page can also give the layout an image of its own. npm run og -w site draws the cards again with satori and resvg (as WebAssembly). It runs offline, with the fonts from node_modules and the colour tokens of Layout.astro. npm test -w site fails when a committed card is not what the script draws now: after a change to a card, a font or a colour token, commit the new PNGs in the same commit. A card has no daily numbers, because they go out of date. The cards are static files, so they are served before the Worker and cost no request. To use the default card as the social preview of the GitHub repository, upload site/public/og/default.png in the repository settings, under Social preview.
The alert mails need a sending domain: either Cloudflare Email Sending (Workers Paid plan, then the send_email binding in site/wrangler.jsonc) or Resend (verify the domain there and npx wrangler secret put RESEND_API_KEY). Without one, the watch form says that the confirmation mail could not be sent.
Deploying needs a Cloudflare account with a D1 database named mcpcost (wrangler d1 create mcpcost, then put the id in site/wrangler.jsonc). The workflows expect the repository secrets CLOUDFLARE_API_TOKEN (Workers Scripts: Edit, D1: Edit) and CLOUDFLARE_ACCOUNT_ID. Both workflows apply site/schema.sql and the pending files in site/migrations/ on every run. The two indexes on the shown token count (migrations 007 and 008) are the exception: each build writes a row per server, so the probe workflow applies one a day before the import and gives the import the rest of the write budget. A new database needs them applied by hand once.
The edge rules
The Workers Free plan counts every request the Worker answers, a 403 as much as a page. On 2026-10-22 and 23 scrapers with Chrome user agents on hosting addresses (Meta's cloud, Alibaba Cloud, RapidSeedbox) made 4 000 list variants an hour and spent the account's 100 000 requests a day, although the Worker refused them. What stops them must run before the Worker: site/edge/rules.mjs writes the zone's WAF rules through the API, idempotently.
a custom rule that blocks Meta's training crawler,
meta-externalagent, on the whole host: a verified bot that ignores robots.txt, made 28 000 of the Worker's 31 000 requests in the twelve hours to 2026-10-24 05:42 UTC, and sends no readers (the link previewfacebookexternalhitis not blocked)a custom rule that blocks those networks on the whole host, verified bots excepted
a custom rule that gives every list variant (
/servers?…) from anything but a verified bot a managed challenge; a browser passes it once, a script does not. The list API (/api/servers.json) is not in it: scripts and agents cannot pass a challenge, so the API stays open under the rate limiting rulea custom rule that blocks a verified bot on the list variants: robots.txt disallows them for everyone, search engines never ask, and Meta's crawler (meta-externalagent behind a Chrome agent string) walked 3 000 of them an hour on 2026-10-23
the one rate limiting rule of the Free plan: more than six list variants in ten seconds from one address is blocked for ten seconds
CLOUDFLARE_API_TOKEN=… node site/edge/rules.mjs --dry-run # shows what it would write
CLOUDFLARE_API_TOKEN=… node site/edge/rules.mjsThe Edge rules workflow (.github/workflows/edge.yml) runs the script when the file changes on main, or by hand, with the CLOUDFLARE_ZONE_TOKEN secret: a token with Zone: Zone WAF: Edit and Zone: Zone: Read on the zone. The probe's token has neither. The middleware in site/src/middleware.ts keeps the same refusals as a second layer, for the workers.dev host the zone rules do not see.
The watch
site/edge/watch.mjs says who read the board in a window of time and what it cost: the Worker's requests and D1 rows per hour from the account's analytics, and the networks, agents and URL shapes behind them from the Worker's logs. The Watch the edge workflow (.github/workflows/watch.yml) runs it every hour, over the time since the previous scheduled run (GitHub runs a schedule late and skips hours at times); the thresholds apply to the worst hour of that window. A threshold crossed (5 000 Worker requests an hour, 800 an hour from one network whose agents do not name a crawler, 300 list variants an hour from one network whatever it calls itself, a million D1 rows an hour; the WATCH_* variables) turns the run red and opens the issue labelled edge-watch, or adds the hour to the open one. The tables name the network; its ASN goes into SCRAPER_ASNS in site/edge/rules.mjs, and the Edge rules workflow blocks it before the Worker. The report also names the D1 queries that read the most rows in those hours. With Zone: Analytics: Read on the zone token, it shows what the zone stopped before the Worker as well.
CLOUDFLARE_API_TOKEN=… CLOUDFLARE_ACCOUNT_ID=… node site/edge/watch.mjs # the last hour
CLOUDFLARE_API_TOKEN=… CLOUDFLARE_ACCOUNT_ID=… node site/edge/watch.mjs 2026-10-22T22:00:00Z 2026-10-23T06:00:00Z # one nightA run started by hand with quiet on only writes the report: a look back at a past window does not open an issue or turn red for an hour that was already reported.
gh workflow run watch.yml -f from=2026-10-24T19:00:00Z -f quiet=trueThe old host
The site was mcp-pulse.ulehla.dev until 2026-10-15. The old host stays a route of the Worker, and the middleware in site/src/middleware.ts answers every request on it with a 301 to mcpcost.ulehla.dev.
Static assets are served before the Worker, and the Astro adapter serves prerendered pages before the middleware too, so a file in site/public/ or a prerendered page answers 200 on the old host. run_worker_first in wrangler.jsonc does not change that. So robots.txt, llms.txt and the methodology page are routes, and every page a crawler reads goes through the middleware. Only the favicon, the fonts under /_astro/, the social cards under /og/, the datasets under /data/ and the search engine verification file remain static.
To redirect those as well, with no Worker invocation at all, add a Redirect Rule to the ulehla.dev zone in the Cloudflare dashboard (Rules, Redirect Rules, Create rule):
When incoming requests match: Hostname equals
mcp-pulse.ulehla.devThen: Dynamic redirect, expression
concat("https://mcpcost.ulehla.dev", http.request.uri.path), status code 301, preserve query string on
Redirect Rules run before the Worker and before static assets, so the rule covers every path. The middleware stays as the fallback for the workers.dev host, which the zone rule does not see.
Releases
A tag v0.Y.Z starts the Release workflow (.github/workflows/release.yml). It checks that the version in the five files is the version of the tag (node scripts/version.mjs --check), runs the tests and npm run check -w site, and packs the package. Then it publishes the package to npm with provenance, publishes site/server.json to the MCP registry and makes the GitHub release. It needs no npm token, no OTP and no mcp-publisher login: npm trusts the workflow file (trusted publishing), and the registry takes the GitHub OIDC token of the run.
One time, on npmjs.com. Do it on the day of the first release: a new trusted publisher expires when it does not publish within 2 days.
Open the package
mcpcost, then Settings. In the Trusted Publisher section, select GitHub Actions.Organization or user:
ondraulehla. Repository:mcpcost. Workflow filename:release.yml. Environment name: empty.Under Allowed actions, allow
npm publish. A trusted publisher made after 2026-09-03 allows onlynpm stage publish, and a staged version waits for an approval with 2FA.Save. The same from the shell, with npm 11.15.0 or later and 2FA:
npm trust github mcpcost --file release.yml --repo ondraulehla/mcpcost --allow-publish.
After the first release, Settings, Publishing access, "Require two-factor authentication and disallow tokens" stops all publishes with a token. The workflow continues to publish.
A release:
node scripts/version.mjs patch # or minor, or 0.3.5: sets the version in the five files
git commit -am "mcpcost 0.3.5: …" # the message of this commit becomes the release notes
git push origin main
git tag v0.3.5 && git push origin v0.3.5To test the setup before the tag: Actions, Release, Run workflow, with the "Dry run" box selected. It runs the checks,
npm publish --dry-runand the registry login, and publishes nothing. The warning "npm did not accept this workflow" means that the trusted publisher on npmjs.com does not match. The dry run does not check the allowed actions.An annotated tag (
git tag -a v0.3.5 -m "…") gives its message as the release notes.When a run fails, run the failed jobs again. Each publish step skips a version that npm or the registry has already.
A run from main without "Dry run" is a release without a tag push: the release makes the tag on that commit.
A package release is never the Latest release (
--latest=false). So the Latest release of the repository stays the release of the GitHub Action (v1.1.0), which its Marketplace page shows. The Action has its own releases, v1.x.y, published to the Marketplace from the release form on GitHub, and its tagv1moves to the newest one. The workflow does not touch them. Only a tag v0.Y.Z starts it, so the package stays below 1.0.0 until it has a tag scheme of its own.
Licence
MIT
Available Tools
6 toolscompare_serversCompare servers side by sideARead-onlyIdempotentInspect
Puts two to five servers next to each other from the board's latest daily probe: status, how a client gets in, tool count, token cost (exact in Claude when counted, else the estimate), share of a 200k window and initialize latency, with the cheapest, the most expensive and the spread. Use it to choose between servers that do the same job; use lookup_server for the full record of one server, search_servers to find candidates, and measure_server to measure a server that is not in the registry. Instant, no connection to the servers, with registry names or endpoint URLs as the registry lists them. A name the board does not know gets a row with status "unknown" and the comparison goes on. format picks the text layout (JSON, a Markdown table, or CSV to paste into a spreadsheet); the structured content is always JSON.
| Name | Required | Description | Default |
|---|---|---|---|
| format | No | The layout of the text content: json (default), markdown (a table with a summary line), or csv (a header row, then one row per server) | |
| servers | Yes | Two to five registry names (io.github.owner/name) or https URLs of MCP endpoints |
Output Schema
| Name | Required | Description |
|---|---|---|
| format | No | |
| servers | No | One row per requested server, in the order given |
| cheapest | No | The server with the fewest tokens, when two or more rows are measured |
| measured | No | How many rows have a token number |
| tokenSpread | No | Tokens between the most expensive and the cheapest |
| mostExpensive | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/idempotent/openWorld annotations, it discloses that the call is instant with no live connection, that data comes from the board's last daily probe, and that unknown names produce an "unknown" row rather than an error. It also clarifies that structured content is always JSON regardless of format — behavior the annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and comparison dimensions, with routing and format notes after. It is one dense paragraph with several parenthetical asides (token cost caveat, format parenthetical) that could be broken into shorter sentences, but no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return shape need not be described, yet the description still enumerates the compared metrics. Combined with the unknown-name fallback, the error model, and the no-network note, an agent has everything needed to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so baseline is 3; the description still adds value by explaining accepted server identifiers (registry names or endpoint URLs "as the registry lists them") and what each format layout produces. It stops short of elaborating on edge cases like duplicate entries or mixed name/URL lists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("puts two to five servers next to each other") plus the exact dimensions compared (status, access, tool count, token cost, window share, init latency, cheap/expensive/spread). The scope of 2-5 and the source (board's latest daily probe) further disambiguate it from siblings that fetch a single record.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit selection rule ("use it to choose between servers that do the same job") and names three alternatives with the condition that selects each: lookup_server for a full record, search_servers to find candidates, measure_server for unregistered servers. An agent needs no inference to route correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lookup_serverLook up a registry server on the boardARead-onlyIdempotentInspect
Reads the public board's latest daily probe of one server in the official MCP registry: status, how a client gets access, the exact Claude token cost of its tool definitions, tool count, latency and the history of changes. Instant, no connection to the server, with a registry name or with the endpoint URL as the registry lists it. Use it when the server is in the registry; use search_servers when you do not know its name, and measure_server to probe a URL or a local command here and now. A name or URL that is not on the board returns isError with a short message that points to measure_server.
| Name | Required | Description | Default |
|---|---|---|---|
| nameOrUrl | Yes | The registry name, for example io.github.owner/name, or the https URL of the endpoint as the registry lists it; both are looked up on the board, nothing is contacted |
Output Schema
| Name | Required | Description |
|---|---|---|
| url | No | The endpoint the board probes |
| name | No | The registry name |
| page | No | The server's page on the board |
| title | No | |
| status | No | ok (answered initialize and tools/list), auth (needs credentials), payment (402), not_found, protocol_error (not MCP), timeout, dns, tls, refused, server_error, rate_limited, newer_protocol, or for a local command: install_failed, no_bin, needs_env, needs_args, needs_network, crashed |
| authKind | No | How a client gets in: oauth-dcr (clients register themselves), oauth (client id from the publisher), token (a key in the Authorization header), unknown |
| probedAt | No | ISO 8601 time of the probe |
| topTools | No | The five most expensive tools: name and o200k_base tokens |
| latencyMs | No | initialize and toolsList, milliseconds |
| toolCount | No | How many tools tools/list returned |
| authScheme | No | The WWW-Authenticate scheme of a server that needs auth |
| httpStatus | No | |
| claudeModel | No | The model the exact count is for |
| shareOf200k | No | Percent of a 200k window, exact when claudeTokens is present |
| statusLabel | No | The status in words, as the board shows it |
| toolsTokens | No | o200k_base estimate over the compact JSON of the tool definitions |
| claudeTokens | No | Exact count from the Anthropic count_tokens endpoint, names as published |
| protocolVersion | No | The MCP protocol version the server negotiated |
| authDocumentation | No | The publisher's guide to getting access |
| claudeTokensClaudeCode | No | The same with the Claude Code prefix mcp__<server>__ on each tool name |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, but the description adds meaningful traits: the data is a cached daily probe, the call is instant, and nothing contacts the target server. It also discloses the failure behavior (isError with a short message). It stops short of saying how stale the board data can be or how history entries are shaped, which the output schema covers.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the resource and returned fields, then the usage routing, then the failure mode — a sensible order. Dense but each clause carries information; slightly overstuffed as a single run-on sequence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with full annotations and an output schema, the description covers what it returns, when to prefer it, which siblings to use otherwise, and what happens on a miss. Nothing an agent needs to pick or invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter already documents both accepted forms (registry name like io.github.owner/name, or https endpoint URL). The description repeats the same facts ('with a registry name or with the endpoint URL as the registry lists it') without adding format constraints or edge cases, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('reads') and resource ('the public board's latest daily probe of one server in the official MCP registry') and enumerates the returned fields. It explicitly distinguishes itself from siblings search_servers and measure_server, so an agent can route without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use rule ('when the server is in the registry') plus the two alternative paths: search_servers for unknown names, measure_server for live probing. It also documents the negative path — unknown name/URL returns isError pointing at measure_server.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
measure_configMeasure every server in a config fileARead-onlyIdempotentInspect
Measures every server in one MCP config file (.mcp.json, Claude Desktop, Cursor, VS Code or Windsurf format): starts each local server the way the client would and stops it after tools/list, connects to each remote one, and reports the tokens per server and the total. Use it to see what a whole config costs the context window; use measure_server for one server. A server that fails to start or needs credentials is reported with its status, never thrown. Up to about 15 s per server.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the config file, absolute or relative to the working directory | |
| window | No | Context window in tokens for shareOfWindow; default 200000 (Claude) | |
| noStdio | No | true = measure the remote servers only and start no local process; default false |
Output Schema
| Name | Required | Description |
|---|---|---|
| path | No | The config file that was read |
| total | No | Over the servers that answered: how many, their tokens (exact when a Claude count exists, else the estimate) and the share of the window |
| servers | No | One entry per configured server: name, kind (remote or stdio) and the same fields as measure_server; or name and skipped, with the reason |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safe, idempotent, open-world profile; the description goes further by disclosing that local servers are actually spawned and stopped after tools/list, that remotes are connected to, that failures and credential-required servers are reported as status rather than thrown, and a ~15 s per-server ceiling. These are exactly the side-effect and latency facts an agent needs before invoking a process-launching tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with what it does, then the routing hint, then failure/timeout semantics. The parenthetical client-format list is compact and functionally necessary; nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a multi-parameter tool with a full output schema and strong annotations, the description covers scope, execution model, error behavior, and timing. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so path, window, and noStdio are already fully documented in the schema. The description implies process-spawning behavior ('starts each local server') that relates loosely to noStdio, but adds no syntax or format detail beyond what the schema provides. Baseline 3 is correct here.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('measures') and resource ('every server in one MCP config file'), enumerates supported file formats, and explicitly contrasts with the sibling measure_server for single-server measurement. An agent can distinguish it from all four siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use it to see what a whole config costs the context window; use measure_server for one server' gives both the when and the named alternative with the condition that selects it. No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
measure_serverMeasure one server nowARead-onlyIdempotentInspect
Measures one MCP server now: connects to a remote URL, or starts a local command and stops it after tools/list, then reports the result, the protocol version, the tool count and the context-token cost of the tool definitions (o200k_base estimate; the exact Claude count when ANTHROPIC_API_KEY is set). Use it for a server that is not in the official registry, or for a local command; for a registry server prefer lookup_server, which answers from the daily board without a connection. Sends no credentials: a server that needs them comes back with status "auth", not an error. 15 s timeout per request. Give url or command, not both.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Remote endpoint to connect to, https://…/mcp (Streamable HTTP) or an …/sse URL. Use this or command. | |
| window | No | Context window in tokens for shareOfWindow; default 200000 (Claude) | |
| command | No | Local server command with its arguments, started with stdio and stopped after tools/list, for example "npx -y @modelcontextprotocol/server-filesystem /tmp". Use this or url. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | The first line of the failure, when status is not ok |
| status | No | ok (answered initialize and tools/list), auth (needs credentials), payment (402), not_found, protocol_error (not MCP), timeout, dns, tls, refused, server_error, rate_limited, newer_protocol, or for a local command: install_failed, no_bin, needs_env, needs_args, needs_network, crashed |
| target | No | The url or command that was measured |
| topTools | No | The ten most expensive tools: name and o200k_base tokens |
| latencyMs | No | initialize and toolsList, milliseconds |
| toolCount | No | How many tools tools/list returned |
| serverInfo | No | name, version and title the server reports in initialize |
| claudeError | No | Why the Anthropic endpoint refused to count, for example a schema it does not accept |
| claudeTokens | No | Exact count from the Anthropic count_tokens endpoint, names as published; only with ANTHROPIC_API_KEY |
| shareOfWindow | No | Percent of the context window the tool definitions take, exact when claudeTokens is present, else the estimate |
| protocolVersion | No | The MCP protocol version the server negotiated |
| toolsTokensEstimate | No | o200k_base tokens over the compact JSON of every tool definition; the exact Claude count is about 1.9 times this at the median |
| claudeTokensClaudeCode | No | The same with the Claude Code prefix mcp__<server>__ on each tool name |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world, non-destructive, so the bar is lower, yet the description adds substantial operational context: no credentials are sent, auth-requiring servers return status "auth" rather than an error, there is a 15 s per-request timeout, and local commands are terminated after tools/list. These are exactly the behaviors an agent needs to predict outcomes and avoid misinterpreting failures.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single dense paragraph, but front-loaded with the core action and organized as action → outputs → usage routing → safety/timeout constraints. Every sentence carries information; the only cost is that the density makes it slightly harder to scan than a bulleted form.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values needn't be spelled out, yet the description still previews the key results. Combined with timeout, auth behavior, and process lifecycle, an agent has everything needed to invoke this correctly on the first try.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns extra credit by stating the mutual exclusivity of url and command and by noting the token-count estimation modes (o200k_base vs exact Claude count when ANTHROPIC_API_KEY is set), which explains the meaning of the reported cost. The `window` parameter's role in shareOfWindow is left to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Measures one MCP server now') and enumerates the mechanism (connect to remote URL or start a local command), plus exactly what is reported: result, protocol version, tool count, context-token cost. It also distinguishes itself from lookup_server by naming it explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit routing rules: use this for servers not in the official registry or for local commands, and prefer lookup_server for registry servers because it answers from the daily board without a connection. It also states the url-vs-command exclusion ('Give url or command, not both'), removing the main invocation ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
registry_summaryThe whole registry in numbersARead-onlyIdempotentInspect
Aggregates of the board's latest daily run over the whole official MCP registry: how many servers answer and why the rest do not, token cost percentiles and the exact-to-estimate ratio, how servers authenticate, protocol versions, transports, the heaviest servers and the biggest publishers. Use it for the state of the registry as a whole, or as the baseline a single server is compared against; use search_servers for a ranked list and lookup_server for one server. Instant, no input, a few kilobytes of JSON.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| ok | No | Servers that answered initialize and tools/list |
| probed | No | Servers probed in this run |
| byStatus | No | Servers per status |
| probedAt | No | ISO 8601 time of the run |
| authKinds | No | Servers that need auth, per kind of access: oauth-dcr, oauth, token, unknown |
| protocols | No | Alive servers per negotiated protocol version |
| toolCount | No | median, p90, max |
| transports | No | |
| authSchemes | No | Servers that need auth, per WWW-Authenticate scheme |
| toolsTokens | No | o200k_base estimate: median, p90, p99, max, total |
| claudeTokens | No | Exact Claude counts: model, counted, refused, median, p90, p99, max, histogram, ratioToEstimate |
| registryEntries | No | Entries in the registry |
| registryWithRemote | No | Entries with a remote endpoint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already cover safety, idempotency and open-world behavior, and the description adds context that the annotations cannot: the data comes from a latest daily run (freshness), it is instant and takes no input (latency and call cost), and it returns a few kilobytes of JSON (payload size). The only minor gap is that it does not say how stale the daily snapshot can be or whether anything is paginated, although the output schema covers the return shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single front-loaded paragraph: the core definition opens it, the routing guidance follows, and operational facts close it. The middle section is a long enumeration of aggregate categories. All of it is informative, but it reads slightly like a brochure list rather than a prioritized summary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The definition covers all the essentials: what it aggregates, the freshness of the source data, that it needs no input, its speed and payload size, and which sibling tool to use for other shapes of query. The return structure is deferred to the output schema, so nothing an agent needs in order to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4, and the description reinforces this with "no input." There is nothing further to document on the parameter side.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ("aggregates") and resource ("the board's latest daily run over the whole official MCP registry") and then enumerates the concrete aggregate families: availability, token-cost percentiles, auth, protocol versions, transports, heaviest servers and publishers. This is enough to distinguish it from lookup_server and search_servers without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives two explicit use conditions (the registry as a whole, or as the baseline to compare a single server against) and names the sibling alternatives with their roles: search_servers for a ranked list, lookup_server for one server. When and when-not are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_serversSearch the boardARead-onlyIdempotentInspect
Finds servers on the public board by words in their name, title, description or host, with optional filters, sorted by exact Claude token cost (highest first) by default. With no query and no filter it ranks the whole board, so page 1 is the most expensive servers in the registry and sort=claude-asc the cheapest. Use it to discover servers or to rank them by cost; use lookup_server once you have a name, compare_servers for a few side by side, registry_summary for the totals. Returns up to twenty servers per page with name, host, status, tool count and tokens; hasNext says whether a next page exists.
| Name | Required | Description | Default |
|---|---|---|---|
| page | No | Page number, 1 to 20, twenty servers each; default 1 | |
| sort | No | claude = exact Claude tokens, highest first (default); claude-asc = lowest first; tokens = the o200k_base estimate; tools = tool count; latency = initialize time; name; updated = registry date | |
| query | No | Words to match, three or more characters each, as prefixes: "git copilot" finds the GitHub Copilot servers. Omit for the whole list. | |
| status | No | ok = answers and lists tools; auth = needs credentials; payment = 402; newer_protocol = a protocol newer than the SDK; down = every other failure. Omit for all. |
Output Schema
| Name | Required | Description |
|---|---|---|
| next | No | Cursor for the next page, when hasNext |
| page | No | |
| sort | No | The sort that was applied; a big unfiltered list keeps the token order |
| fields | No | What claude_tokens, claude_tokens_cc and tools_tokens mean |
| hasNext | No | |
| perPage | No | |
| servers | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world and non-destructive, so the safety profile is covered. The description adds behavior the annotations cannot: default sort is by exact Claude token cost descending, an empty query ranks the entire board, pages hold twenty servers, and hasNext signals pagination.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four front-loaded sentences: what it does, the key edge case, which sibling to use instead, and what comes back. No sentence is redundant with the other.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Even though an output schema exists, the description still summarizes the return fields and pagination flag, and it covers the degenerate empty-query case an agent would otherwise have to infer. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description goes further by explaining the consequence of omitting query and status ("no query and no filter it ranks the whole board") and by contrasting the default descending cost sort with sort=claude-asc, which the enum alone only hints at.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("finds servers on the public board") plus the matchable fields (name, title, description, host) and the default ordering. The agent can distinguish it from lookup_server and compare_servers without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes: "Use it to discover servers or to rank them by cost; use lookup_server once you have a name, compare_servers for a few side by side, registry_summary for the totals." Each alternative is named with the condition that selects it.
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.
2 tool updates
- Changed
lookup_server1 field changed- changed
Input schema / properties / nameOrUrl / descriptionPrevious value: -"The registry name, for example io.github.owner/name (exact, instant), or an https URL of an MCP endpoint (probed live by the board)"New value: +"The registry name, for example io.github.owner/name, or the https URL of the endpoint as the registry lists it; both are looked up on the board, nothing is contacted"
- Added
registry_summary
5 tool updates
v0.3.4- Added
compare_servers - Changed
lookup_server2 fields changed- added
Input schema / properties / nameOrUrl / descriptionAdded value: +"The registry name, for example io.github.owner/name (exact, instant), or an https URL of an MCP endpoint (probed live by the board)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "authDocumentation": { + "description": "The publisher's guide to getting access", + "type": [ + "string", + "null" + ] + }, + "authKind": { + "description": "How a client gets in: oauth-dcr (clients register themselves), oauth (client id from the publisher), token (a key in the Authorization header), unknown", + "type": [ + "string", + "null" + ] + }, + "authScheme": { + "description": "The WWW-Authenticate scheme of a server that needs auth", + "type": [ + "string", + "null" + ] + }, + "claudeModel": { + "description": "The model the exact count is for", + "type": [ + "string", + "null" + ] + }, + "claudeTokens": { + "description": "Exact count from the Anthropic count_tokens endpoint, names as published", + "type": [ + "integer", + "null" + ] + }, + "claudeTokensClaudeCode": { + "description": "The same with the Claude Code prefix mcp__<server>__ on each tool name", + "type": [ + "integer", + "null" + ] + }, + "httpStatus": { + "type": [ + "integer", + "null" + ] + }, + "latencyMs": { + "description": "initialize and toolsList, milliseconds", + "type": [ + "object", + "null" + ] + }, + "name": { + "description": "The registry name", + "type": [ + "string", + "null" + ] + }, + "page": { + "description": "The server's page on the board", + "type": [ + "string", + "null" + ] + }, + "probedAt": { + "description": "ISO 8601 time of the probe", + "type": [ + "string", + "null" + ] + }, + "protocolVersion": { + "description": "The MCP protocol version the server negotiated", + "type": [ + "string", + "null" + ] + }, + "shareOf200k": { + "description": "Percent of a 200k window, exact when claudeTokens is present", + "type": [ + "number", + "null" + ] + }, + "status": { + "description": "ok (answered initialize and tools/list), auth (needs credentials), payment (402), not_found, protocol_error (not MCP), timeout, dns, tls, refused, server_error, rate_limited, newer_protocol, or for a local command: install_failed, no_bin, needs_env, needs_args, needs_network, crashed", + "type": [ + "string", + "null" + ] + }, + "statusLabel": { + "description": "The status in words, as the board shows it", + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "toolCount": { + "description": "How many tools tools/list returned", + "type": [ + "integer", + "null" + ] + }, + "toolsTokens": { + "description": "o200k_base estimate over the compact JSON of the tool definitions", + "type": [ + "integer", + "null" + ] + }, + "topTools": { + "description": "The five most expensive tools: name and o200k_base tokens", + "type": [ + "array", + "null" + ] + }, + "url": { + "description": "The endpoint the board probes", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
- Changed
measure_config4 fields changed- changed
Input schema / properties / noStdio / descriptionPrevious value: -"Measure remote servers only, do not start local ones"New value: +"true = measure the remote servers only and start no local process; default false" - changed
Input schema / properties / path / descriptionPrevious value: -"Path to the config file"New value: +"Path to the config file, absolute or relative to the working directory" - added
Input schema / properties / window / descriptionAdded value: +"Context window in tokens for shareOfWindow; default 200000 (Claude)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "path": { + "description": "The config file that was read", + "type": "string" + }, + "servers": { + "description": "One entry per configured server: name, kind (remote or stdio) and the same fields as measure_server; or name and skipped, with the reason", + "items": { + "properties": { + "claudeError": { + "description": "Why the Anthropic endpoint refused to count, for example a schema it does not accept", + "type": "string" + }, + "claudeTokens": { + "description": "Exact count from the Anthropic count_tokens endpoint, names as published; only with ANTHROPIC_API_KEY", + "type": "integer" + }, + "claudeTokensClaudeCode": { + "description": "The same with the Claude Code prefix mcp__<server>__ on each tool name", + "type": "integer" + }, + "error": { + "description": "The first line of the failure, when status is not ok", + "type": "string" + }, + "kind": { + "enum": [ + "remote", + "stdio" + ], + "type": "string" + }, + "latencyMs": { + "description": "initialize and toolsList, milliseconds", + "type": "object" + }, + "name": { + "type": "string" + }, + "protocolVersion": { + "description": "The MCP protocol version the server negotiated", + "type": "string" + }, + "serverInfo": { + "description": "name, version and title the server reports in initialize", + "type": "object" + }, + "shareOfWindow": { + "description": "Percent of the context window the tool definitions take, exact when claudeTokens is present, else the estimate", + "type": "number" + }, + "skipped": { + "description": "Why the server was not measured: disabled in config, or a local server under noStdio", + "type": "string" + }, + "status": { + "description": "ok (answered initialize and tools/list), auth (needs credentials), payment (402), not_found, protocol_error (not MCP), timeout, dns, tls, refused, server_error, rate_limited, newer_protocol, or for a local command: install_failed, no_bin, needs_env, needs_args, needs_network, crashed", + "type": "string" + }, + "toolCount": { + "description": "How many tools tools/list returned", + "type": "integer" + }, + "toolsTokensEstimate": { + "description": "o200k_base tokens over the compact JSON of every tool definition; the exact Claude count is about 1.9 times this at the median", + "type": "integer" + }, + "topTools": { + "description": "The ten most expensive tools: name and o200k_base tokens", + "items": { + "properties": { + "name": { + "type": "string" + }, + "tokens": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" + }, + "type": "array" + }, + "total": { + "description": "Over the servers that answered: how many, their tokens (exact when a Claude count exists, else the estimate) and the share of the window", + "properties": { + "servers": { + "type": "integer" + }, + "shareOfWindow": { + "type": "number" + }, + "tokens": { + "type": "integer" + } + }, + "type": "object" + } + }, + "type": "object" +}
- Changed
measure_server4 fields changed- changed
Input schema / properties / command / descriptionPrevious value: -"Local server command with its arguments, for example \"npx -y @modelcontextprotocol/server-filesystem /tmp\""New value: +"Local server command with its arguments, started with stdio and stopped after tools/list, for example \"npx -y @modelcontextprotocol/server-filesystem /tmp\". Use this or url." - changed
Input schema / properties / url / descriptionPrevious value: -"Remote endpoint, https://…/mcp or an SSE URL"New value: +"Remote endpoint to connect to, https://…/mcp (Streamable HTTP) or an …/sse URL. Use this or command." - changed
Input schema / properties / window / descriptionPrevious value: -"Context window for the share, default 200000"New value: +"Context window in tokens for shareOfWindow; default 200000 (Claude)" - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "claudeError": { + "description": "Why the Anthropic endpoint refused to count, for example a schema it does not accept", + "type": "string" + }, + "claudeTokens": { + "description": "Exact count from the Anthropic count_tokens endpoint, names as published; only with ANTHROPIC_API_KEY", + "type": "integer" + }, + "claudeTokensClaudeCode": { + "description": "The same with the Claude Code prefix mcp__<server>__ on each tool name", + "type": "integer" + }, + "error": { + "description": "The first line of the failure, when status is not ok", + "type": "string" + }, + "latencyMs": { + "description": "initialize and toolsList, milliseconds", + "type": "object" + }, + "protocolVersion": { + "description": "The MCP protocol version the server negotiated", + "type": "string" + }, + "serverInfo": { + "description": "name, version and title the server reports in initialize", + "type": "object" + }, + "shareOfWindow": { + "description": "Percent of the context window the tool definitions take, exact when claudeTokens is present, else the estimate", + "type": "number" + }, + "status": { + "description": "ok (answered initialize and tools/list), auth (needs credentials), payment (402), not_found, protocol_error (not MCP), timeout, dns, tls, refused, server_error, rate_limited, newer_protocol, or for a local command: install_failed, no_bin, needs_env, needs_args, needs_network, crashed", + "type": "string" + }, + "target": { + "description": "The url or command that was measured", + "type": "string" + }, + "toolCount": { + "description": "How many tools tools/list returned", + "type": "integer" + }, + "toolsTokensEstimate": { + "description": "o200k_base tokens over the compact JSON of every tool definition; the exact Claude count is about 1.9 times this at the median", + "type": "integer" + }, + "topTools": { + "description": "The ten most expensive tools: name and o200k_base tokens", + "items": { + "properties": { + "name": { + "type": "string" + }, + "tokens": { + "type": "integer" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "type": "object" +}
- Changed
search_servers5 fields changed- added
Input schema / properties / page / descriptionAdded value: +"Page number, 1 to 20, twenty servers each; default 1" - added
Input schema / properties / query / descriptionAdded value: +"Words to match, three or more characters each, as prefixes: \"git copilot\" finds the GitHub Copilot servers. Omit for the whole list." - added
Input schema / properties / sort / descriptionAdded value: +"claude = exact Claude tokens, highest first (default); claude-asc = lowest first; tokens = the o200k_base estimate; tools = tool count; latency = initialize time; name; updated = registry date" - added
Input schema / properties / status / descriptionAdded value: +"ok = answers and lists tools; auth = needs credentials; payment = 402; newer_protocol = a protocol newer than the SDK; down = every other failure. Omit for all." - changed
Output schema / (root)Previous value: -nullNew value: +{ + "properties": { + "fields": { + "description": "What claude_tokens, claude_tokens_cc and tools_tokens mean", + "type": [ + "object", + "null" + ] + }, + "hasNext": { + "type": [ + "boolean", + "null" + ] + }, + "next": { + "description": "Cursor for the next page, when hasNext", + "type": [ + "string", + "null" + ] + }, + "page": { + "type": [ + "integer", + "null" + ] + }, + "perPage": { + "type": [ + "integer", + "null" + ] + }, + "servers": { + "items": { + "properties": { + "auth_scheme": { + "description": "The WWW-Authenticate scheme of a server that needs auth", + "type": [ + "string", + "null" + ] + }, + "claude_tokens": { + "description": "Exact Claude count, names as published", + "type": [ + "integer", + "null" + ] + }, + "claude_tokens_cc": { + "description": "Exact Claude count with the Claude Code prefix", + "type": [ + "integer", + "null" + ] + }, + "host": { + "type": [ + "string", + "null" + ] + }, + "http_status": { + "type": [ + "integer", + "null" + ] + }, + "init_ms": { + "description": "initialize latency, milliseconds", + "type": [ + "integer", + "null" + ] + }, + "name": { + "description": "The registry name; the page on the board is https://mcpcost.ulehla.dev/s/<name>", + "type": [ + "string", + "null" + ] + }, + "protocol_version": { + "type": [ + "string", + "null" + ] + }, + "shown_tokens": { + "description": "The number the board shows: exact when it exists, else the estimate", + "type": [ + "integer", + "null" + ] + }, + "status": { + "description": "ok (answered initialize and tools/list), auth (needs credentials), payment (402), not_found, protocol_error (not MCP), timeout, dns, tls, refused, server_error, rate_limited, newer_protocol, or for a local command: install_failed, no_bin, needs_env, needs_args, needs_network, crashed", + "type": [ + "string", + "null" + ] + }, + "title": { + "type": [ + "string", + "null" + ] + }, + "tool_count": { + "type": [ + "integer", + "null" + ] + }, + "tools_tokens": { + "description": "o200k_base estimate", + "type": [ + "integer", + "null" + ] + }, + "transport": { + "enum": [ + "streamable-http", + "sse", + "stdio" + ], + "type": [ + "string", + "null" + ] + } + }, + "type": "object" + }, + "type": [ + "array", + "null" + ] + }, + "sort": { + "description": "The sort that was applied; a big unfiltered list keeps the token order", + "type": [ + "string", + "null" + ] + } + }, + "type": "object" +}
4 tool updates
v0.1.0- First observed
lookup_server - First observed
measure_config - First observed
measure_server - First observed
search_servers
TDQS
Scored across 6 tools
Each tool targets a distinct axis of the domain: registry lookup by name, discovery/ranking by query, side-by-side comparison, whole-registry aggregates, single-server live measurement, and whole-config measurement. The descriptions explicitly cross-reference the right alternative for each edge case (unknown name -> measure_server, no name -> search_servers), leaving essentially no room for misselection.
Five of six names follow a clear verb_noun pattern (lookup_server, search_servers, compare_servers, measure_config, measure_server) with consistent snake_case. registry_summary breaks the pattern as noun_noun, a minor deviation that is still readable and unambiguous.
Six tools is well within the sweet spot, and each earns its place: three read-only board tools, one aggregate, and two measurement tools split sensibly by scope (single server vs. config file). No redundant or filler tools.
The surface covers discovery, detail, comparison, aggregate baselines, and live measurement of both individual servers and full configs, including graceful handling of auth failures and timeouts. Minor gap: no per-tool token breakdown within a server, only totals, so an agent cannot see which tool in a server is expensive.
Maintenance
Related MCP Connectors
Analytics for MCP servers. Query your tool calls, first-call success, retries and schema cost.
Free, no-key MCP server: token estimates, JSON Schema conversion, MCP configs, tool search.
Scan MCP tool definitions for poisoning, look up server history, count tool-list tokens. Free.
Directory of remote MCP servers with daily measured reachability, tools and changes.
Related MCP Servers
- AlicenseAqualityBmaintenanceMonitor MCP server health, uptime, response times, and Azure DevOps pipeline status1412 npm1MIT
- AlicenseBqualityFmaintenanceTrack LLM token costs across Claude, GPT and Gemini. MCP server + CLI with optimization hints and $ savings estimates.89 npm1MIT
- AlicenseNot gradedqualityDmaintenanceLive LLM pricing as an MCP server. Ask Claude or any MCP client 'how much does this prompt cost?' and get real numbers from a hand-checked pricing table for every major LLM.MIT
- AlicenseNot gradedqualityDmaintenanceProvides tools to count tokens, estimate API costs, optimize prompts, and compare AI model pricing for multiple LLMs.59 npmMIT