Handshake and inventory
Connect, list tools, lint the schemas. A server with no tools exits here without spending anything on probes.
Is there anything here at all?
MCP server vetting for agents
Adding an MCP server to Claude Code is one line of JSON. After that line, a server you have never audited can describe its own tools to your agent, and your agent will believe the description. There is no grade, no gate, and no record of what you let in.
Graded by being used, not by being read. Do not trust the letter. Replay the tape.
How a grade is built
Most scanners read a server's manifest and score its conformance. That catches a missing field. It does not catch the thing that actually costs you: an agent picking the wrong tool because two descriptions say nearly the same thing.
Wraps the mcpscore CLI: protocol version, TLS, schema validity,
annotations, pagination behaviour. Its raw output is a score over a
moving denominator, because rules get skipped per server. We
normalise to a percentage before anything is compared. A server scoring
78 out of 91 is worse than one scoring 64 out of 73, and only the
normalised number shows it.
A real agent, a pinned model, temperature 0, three runs per probe. The probes drive the server the way your agent would and score what happens. This is the half of the grade that reading cannot produce.
The same cold task, re-run with the drafted recipe in hand. It measures how much of the gap to a perfect run the recipe closes, not the raw point difference, so a server that was already strong is not punished for having little room left to improve.
A layer that did not run is not a zero. If the guidance delta was never measured, its weight is removed and the other two renormalise to 37.5 and 62.5. Scoring an unmeasured layer as zero would drag every honest partial audit into a failing band, which is a way of lying with arithmetic.
A grade is relative to the model that produced it. The model id is stored on the audit, printed in the report, and rendered on the badge. Grades from different models are not comparable and the report says so.
What gets measured
Two of them do not always run. Ambiguity only fires when tool descriptions genuinely overlap, and Chain is skipped under three tools. A probe that did not apply is recorded with its reason and left out of the average, rather than counted as a failure the server did not earn.
Connect, list tools, lint the schemas. A server with no tools exits here without spending anything on probes.
Is there anything here at all?
A fresh agent, the server's own descriptions, and a task built from what you said you needed it for. Scored on first-try tool choice, first-try schema validity, completion, and how much wandering it took.
Can an agent that has never seen this succeed on the first try?
Fires only when two tools overlap. The task is worded in the wrong tool's vocabulary, so only a description that draws a real line will save it.
Do these two descriptions actually distinguish themselves?
Omit a required parameter on purpose, then measure the error message. What is graded here is the message, not the agent. "Invalid input" and "missing required 'repoName' (string, e.g. facebook/react)" are the same failure and completely different products.
Can an agent fix itself from this error in two turns?
Two steps, where the second must consume a real value the first returned. Servers that look fine tool by tool fall over here, when an id comes back under a different name than the next tool asks for.
Do these outputs compose, or only look like they should?
Scan-only. Reads every description and schema string an agent would see before choosing a tool, looking for content shaped like an instruction rather than documentation. It never calls a tool: we do not execute a server to find out whether it is hostile.
Is this documentation, or is it giving my agent orders?
Two findings cap a grade at F outright: injection-shaped content in the advertised strings, and a transport that is not TLS. A hard fail overrides every other score, and a hard-failed server with a 90 percent static result is still an F.
Because an F is a public accusation about somebody else's software, the sniffer is deliberately conservative and every hit records the pattern that matched plus the offending text, verbatim, so the claim can be checked rather than taken on trust.
The part that runs on your machine
The grading service is interesting. The hook is the part that protects you. It runs before every MCP tool call, reads a local file, and blocks anything it cannot vouch for.
> summarise what the acme-helper server can tell us about this repo · calling mcp__acme_helper__search BLOCKED by doorman doorman: 'acme_helper' is UNKNOWN. Blocking until it has been graded. An ungraded MCP server is not a trusted one. Nothing about 'mcp__acme_helper__search' has been verified: not its tool descriptions, not its error handling, not whether its descriptions contain instructions aimed at you. To grade it: /vet <server-url> > /vet https://acme-helper.example.com/mcp "search our internal docs" queued · claimed by runner · mcpscore 64/73 = 87.67% probe cold_open 55 · ambiguity 33 · bad_input 45 · chain skipped VERDICT: C (61.4/100) Why: agent reached for 'search_all' when 'search_docs' was the fit error for missing 'query' does not name the field 'search_all' and 'search_docs' overlap 41% Recipe drafted: 3 rules. Proposed registry diff below.
Read and exactly one MCP tool. The agent that decides what to trust does not also carry capabilities an untrusted server could talk it into using.Live viewport
Grading does not happen in the browser, and it does not happen in the Worker either. The static layer shells out to a Python CLI, which a Cloudflare Worker cannot do, so the request goes into a queue and a probe runner claims it. The ledger below polls every two seconds. There is no websocket here on purpose: streaming would need Durable Objects, and this runs on the free tier.
The URL must be https. A plaintext transport is a hard fail, so it is refused before any work is queued.
Not connected to a scorecard yet.
What you get back
Every audit produces the same bundle, and the bundle is hashed with a canonical serialisation so two runs over the same evidence agree on any machine. Change a transcript and the hash changes. That is what makes the anchor worth anything.