MCP Verification Gate: check an MCP server or an A2A agent before you connect or delegate
Check an A2A agent before you delegate, or an MCP server's measured conduct. Free, no key.
Should I use this
Quality & Safety
Based on automated analysis of tool definitions and protocol compliance.
Context Cost
This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.
Install
One-Click Install
Add this to your `claude_desktop_config.json` file:
{
"mcpServers": {
"hs-verify-gate": {
"url": "https://hs-verify-gate.oga-surf-project.workers.dev/mcp"
}
}
}Remote endpoints
https://hs-verify-gate.oga-surf-project.workers.dev/mcpstreamable-httphttps://gate.horizonshield.dev/mcpstreamable-httpWhat it can do
Tool inventory
Tools (6)
🟢get_conditions
Return the five conditions this gate measures, what it explicitly does not verify, and the tier definitions. Takes no arguments and returns identical output every time. Read this before running a check so you know what a verdict does and does not claim.
Input Schema
{
"type": "object",
"properties": {},
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"gate": {
"type": "string",
"description": "Name of this gate."
},
"version": {
"type": "string",
"description": "Version of the gate code that produced this document."
},
"gate_commit": {
"type": "string",
"description": "Git commit of the deployed gate, or a sentence saying the deployment did not pin one."
},
"what_this_verifies": {
"type": "array",
"description": "The claims a verdict from this gate supports, as sentences."
},
"what_this_does_not_verify": {
"type": "array",
"description": "What a verdict from this gate never supports, as sentences."
},
"conditions": {
"type": "object",
"description": "The measured conditions, keyed by condition id, each with what is measured and how."
},
"reachability": {
"type": "string",
"description": "How an answer from the server is told apart from a failure to reach it (pending versus held)."
},
"consent": {
"type": "string",
"description": "When this gate calls a tool on a checked server, and what counts as the owner's consent."
},
"establishes_and_does_not_establish": {
"type": "object",
"description": "What a verdict establishes and what it does not, as two lists."
},
"lookup": {
"type": "object",
"description": "How to read the register for one endpoint before connecting (GET /register/lookup)."
},
"number_safety": {
"type": "object",
"description": "How numbers in a verdict are kept recomputable across JSON implementations."
},
"record_bytes": {
"type": "object",
"description": "Where the exact bytes that record_sha256 hashes are served, and since when."
},
"instant_coordinate": {
"type": "object",
"description": "How the time of a scheduled measurement and the measured tool are derived rather than chosen."
},
"well_known_consent": {
"type": "object",
"description": "The consent file an origin can publish, its path and its fields."
},
"red_team": {
"type": "string",
"description": "The adversarial test suite this gate is run against, with its scores by version."
},
"also_measured_no_verdict": {
"type": "object",
"description": "Measurements that are disclosed and never change a verdict."
},
"tiers": {
"type": "object",
"description": "The status words a verdict can carry and what each one means."
},
"operator": {
"type": "string",
"description": "Who operates this gate."
},
"self_applied": {
"type": "string",
"description": "Statement that this gate is measured under its own conditions."
}
},
"description": "Deterministic. Takes no arguments, looks nothing up, and returns the same document every time. It therefore declares no read-state field, and a structural probe will score it as unable to hold the difference between a failed read and an empty one. That score is correct and is left standing: this tool has no read to fail. Adding a state field it can never use would make the number look better and mean less.",
"additionalProperties": true
}🟢check_conformance(endpoint, allow_tool_call)
Measure a public MCP endpoint against five conditions: it speaks MCP, it publishes an A2A agent card, it declares who pays it, identical input returns identical output, and the verdict itself can be recomputed by anyone. Free, no key. Conformance and disclosure only; this says nothing about whether any figure the checked server returns is correct. By default no tool on the checked server is called, so determinism comes back as not measured rather than guessed. It is measured when the owner has published /.well-known/mcp-conduct.json with allow_tool_call true.
Input Schema
{
"type": "object",
"properties": {
"endpoint": {
"type": "string",
"description": "https URL of the MCP endpoint to measure"
},
"allow_tool_call": {
"type": "boolean",
"description": "Kept for compatibility. Since 2026-10-08 an assertion alone calls no tool: consent is proven only by the owner's /.well-known/mcp-conduct.json. Default false."
}
},
"required": [
"endpoint"
],
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"gate": {
"type": "string",
"description": "Name of this gate."
},
"gate_version": {
"type": "string",
"description": "Version of the gate code that took this measurement."
},
"gate_commit": {
"type": "string",
"description": "Git commit of the deployed gate, or a sentence saying the deployment did not pin one."
},
"endpoint": {
"type": "string",
"description": "The MCP endpoint that was measured."
},
"checked_at": {
"type": "string",
"description": "When the measurement started, ISO 8601 UTC."
},
"reachable": {
"type": [
"boolean",
"null"
],
"description": "Three-valued on purpose (gate58). true = measured and answered. false = measured and did not answer. null = NOT MEASURED. null is never to be read as a failing endpoint; it means this gate has nothing to say."
},
"status": {
"type": "string",
"description": "verified = every measured condition passed. pending = measured, not all passing. held = could not be reached, nothing established."
},
"scope_note": {
"type": "string",
"description": "What this measurement covers and what it does not."
},
"tools_called": {
"type": "string",
"description": "Whether a tool on the checked server was executed, in words."
},
"coordinate_derivation": {
"type": "object",
"description": "How the measured tool and instant were derived, or that the legacy rule applied."
},
"consent_basis": {
"type": "string",
"description": "On what basis a tool call was or was not made."
},
"consent_source": {
"type": "string",
"description": "Where the consent came from: operator_list, well_known, requester or none."
},
"consent_lookup": {
"type": "object",
"description": "Present when no proven consent was found: the consent file that was read, the result, and how to consent."
},
"consent_assertion_ignored": {
"type": "object",
"description": "Present when the request set allow_tool_call true without proven consent: the assertion was recorded and no tool was called."
},
"probed_via": {
"type": "string",
"description": "The network path the probe took (relay or direct)."
},
"measurement_note": {
"type": "string",
"description": "Present only when the gate's own relay failed, so that nothing here is read as a statement about the target."
},
"checks": {
"type": "object",
"description": "One entry per condition, each with whether it was measured, whether it passed, and the detail."
},
"absence_vs_failure": {
"type": "object",
"description": "Condition 06, disclosed and never a verdict: whether the server's tools can tell a failed lookup from an empty one."
},
"canonicalization": {
"type": "object",
"description": "Condition 07, disclosed and never a verdict: whether the declared tool surface canonicalizes under RFC 8785."
},
"establishes": {
"type": "array",
"description": "What this verdict establishes, as sentences."
},
"does_not_establish": {
"type": "array",
"description": "What this verdict does not establish, as sentences."
},
"number_safety": {
"type": "object",
"description": "Whether every number in this verdict survives a JSON round trip unchanged."
},
"record_sha256": {
"type": "string",
"description": "Hash of this verdict with record_sha256 and recompute_note removed. Recompute it yourself; verify_verdict does the same arithmetic."
},
"recompute_note": {
"type": "string",
"description": "How to recompute record_sha256. Not part of the hashed bytes."
}
},
"additionalProperties": true
}🟢verify_verdict(record)
Take a verdict this gate issued and recompute its record_sha256 independently. Removes record_sha256 and recompute_note, serialises the remainder in key order, and hashes it. Returns whether the verdict was altered after it was issued. You do not have to trust the party that issued the verdict, including this one.
Input Schema
{
"type": "object",
"properties": {
"record": {
"type": "object",
"description": "The full verdict object as returned by check_conformance or GET /self"
}
},
"required": [
"record"
],
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"verified": {
"type": "boolean",
"description": "true = the verdict hashes to its own record_sha256, so it was not altered after issue. false = it was altered, or it carries no record_sha256. This is a finding about the record, not an error."
},
"expected_sha256": {
"type": [
"string",
"number",
"boolean",
"object",
"array"
],
"description": "The record_sha256 found in the record you passed, echoed as given (a string in any verdict this gate issued). Absent when the record had none."
},
"recomputed_sha256": {
"type": "string",
"description": "SHA-256 this call computed from the record. Absent when there was nothing to compare it with."
},
"method": {
"type": "string",
"description": "The arithmetic used, so you can repeat it without this gate."
},
"note": {
"type": "string",
"description": "What a match or a mismatch does and does not prove."
},
"reason": {
"type": "string",
"description": "Present instead of the hashes when the input could not be checked: not an object, or no record_sha256."
}
},
"additionalProperties": true
}🟢lookup_server(endpoint)
Returns one record (not a list). Look up what this register already holds about an MCP endpoint: whether it is watched, how often it is re-measured, how many measurements exist, when the first and latest were taken, and the latest verdict with the record_sha256 you can recompute yourself. Reads stored measurements only. It contacts nothing and measures nothing, so use check_conformance for a fresh reading. An endpoint that is absent is reported as absent and that is NOT a negative verdict: it means nobody has measured it here, not that it failed.
Input Schema
{
"type": "object",
"properties": {
"endpoint": {
"type": "string",
"description": "https URL of the MCP endpoint to look up, exactly as it appears on the register"
}
},
"required": [
"endpoint"
],
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"endpoint": {
"type": "string",
"description": "The endpoint you asked about, echoed."
},
"on_register": {
"type": "boolean",
"description": "true = this endpoint is on the register. false = the register was READ and this endpoint is not on it. If the register could not be read at all, this field is not returned: the call comes back as a tool error (isError), because absence and not-knowing are different answers."
},
"register_size": {
"type": "integer",
"description": "Absent endpoint only: how many endpoints are on the watchlist."
},
"how_to_appear": {
"type": "string",
"description": "Absent endpoint only: how anyone can add it to the register."
},
"fresh_reading": {
"type": "string",
"description": "Absent endpoint only: how to measure it right now."
},
"tier": {
"type": "string",
"description": "On the register: free, paid or self. The verdict is the same for every tier."
},
"cadence": {
"type": "string",
"description": "On the register: how often it is re-measured (weekly or daily)."
},
"added_at": {
"type": [
"string",
"null"
],
"description": "On the register: when the row was added, or null if not recorded."
},
"alerted_on_change": {
"type": "boolean",
"description": "On the register: whether someone asked to be notified when the row changes."
},
"measurements": {
"type": "integer",
"description": "On the register: how many measurements are stored for this endpoint."
},
"standing": {
"type": "string",
"description": "On the register: measured, or a sentence saying it is watched and not yet measured."
},
"first_measured_at": {
"type": [
"string",
"null"
],
"description": "On the register: time of the first stored measurement, or null."
},
"last_measured_at": {
"type": [
"string",
"null"
],
"description": "On the register: time of the latest stored measurement, or null."
},
"latest": {
"type": [
"object",
"null"
],
"description": "On the register: the latest stored measurement as a summary with its record_sha256, or null if none."
},
"history": {
"type": "array",
"description": "On the register: the most recent stored measurements, oldest first, at most 20."
},
"history_truncated": {
"type": "boolean",
"description": "On the register: true when history leaves out older measurements."
},
"full_history_url": {
"type": "string",
"description": "On the register: URL of the complete history for this endpoint."
},
"means": {
"type": "string",
"description": "What this answer means."
},
"does_not_mean": {
"type": "string",
"description": "What this answer must not be read as."
}
},
"description": "Returns one record (not a list): what this register holds for the single endpoint you named. Fields after on_register depend on its value: an absent endpoint carries register_size, how_to_appear and fresh_reading; an endpoint on the register carries the rest.",
"additionalProperties": true
}🟢is_verified(endpoint)
A single machine-first answer for an agent deciding whether to trust an MCP endpoint BEFORE it connects. Returns verified (true only when the latest scheduled measurement passed every measured condition; null otherwise, never false), a state enum saying which case it is, measured_at, and a record_sha256 with a recompute_url so you can check the verdict without trusting this gate. Reads the stored register only: it contacts nothing and measures nothing. Absent and pending are reported honestly and are NOT negative verdicts. For a fresh measurement rather than the stored one, use check_conformance.
Input Schema
{
"type": "object",
"properties": {
"endpoint": {
"type": "string",
"description": "https URL of the MCP endpoint to look up, exactly as it appears on the register"
}
},
"required": [
"endpoint"
],
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"endpoint": {
"type": "string",
"description": "The endpoint you asked about, echoed."
},
"gate": {
"type": "string",
"description": "Name of this gate."
},
"gate_commit": {
"type": "string",
"description": "Git commit of the deployed gate, or a sentence saying the deployment did not pin one."
},
"recompute_url": {
"type": "string",
"description": "Where to fetch what record_sha256 can be checked against: record_url when it exists, otherwise the history."
},
"record_url": {
"type": [
"string",
"null"
],
"description": "URL of the exact bytes that record_sha256 hashes, or null for a verdict stored before those bytes were kept."
},
"history_url": {
"type": "string",
"description": "URL of the stored measurements for this endpoint."
},
"recompute_note": {
"type": "string",
"description": "How to recompute record_sha256 from record_url, or why it cannot be recomputed."
},
"verified_meaning": {
"type": "string",
"description": "What verified true and null mean."
},
"not_an_endorsement": {
"type": "string",
"description": "What a verified reading does not claim."
},
"on_register": {
"type": "boolean",
"description": "true = the endpoint has a row here. false = the register was read and it has none."
},
"state": {
"type": "string",
"enum": [
"verified",
"pending",
"held",
"watched",
"absent"
],
"description": "verified = passed all measured conditions. pending = measured but not passing every one (often only because determinism needs the owner's consent). held = could not be reached. watched = on the list, not yet measured. absent = no row here at all."
},
"verified": {
"type": [
"boolean",
"null"
],
"description": "true = latest measurement passed all measured conditions. null = not established here (see state). Never false: unmeasured or not-yet-passing is not a failure."
},
"measured_at": {
"type": [
"string",
"null"
],
"description": "Time of the latest stored measurement, or null when there is none."
},
"record_sha256": {
"type": [
"string",
"null"
],
"description": "Hash of the latest verdict. Recompute it via recompute_url; no trust in this gate required."
},
"conditions": {
"type": [
"object",
"null"
],
"description": "Per condition: true passed, false did not pass, null not measured. null as a whole when nothing was measured."
},
"absence_vs_failure": {
"type": [
"object",
"null"
],
"description": "Measured endpoints only: condition 06 from the latest measurement, disclosed and never a verdict."
},
"measurements": {
"type": "integer",
"description": "Measured endpoints only: how many measurements are stored."
},
"reason": {
"type": "string",
"description": "One sentence saying why state has the value it has."
},
"how_to_appear": {
"type": [
"string",
"null"
],
"description": "Absent endpoint only: how anyone can add it to the register."
}
},
"description": "A one-glance answer for an agent deciding whether to trust an MCP endpoint BEFORE connecting. Reads the register only; measures nothing. verified is true ONLY when the latest scheduled measurement passed every measured condition; it is null in every other case (pending, held, watched, absent), and never false, because this gate calls nothing a failure. The state enum says which case it is, so a consumer can tell 'not verified here' apart from 'the lookup failed' (that returns as a tool error, isError) and from 'measured and passing'.",
"additionalProperties": true
}🟢preflight_agent(agent)
Call this before handing work to an A2A agent you have not used before. Fetches the agent's public card (https://<agent>/.well-known/agent-card.json, one request), reports whether it declares the A2A Conduct Extension, who it says pays it (the compensation declaration, as declared and not verified), whether the card carries a signature, the endpoints it asks to be measured on, and this register's stored reading for each (verified is true only when the latest scheduled measurement passed; null otherwise, never false), plus where to file your own witness walk. Measures nothing new and returns counts and pointers, never a score. An agent that does not declare the extension is reported as such, which is not a negative verdict.
Input Schema
{
"type": "object",
"properties": {
"agent": {
"type": "string",
"description": "https origin of the agent (https://agent.example) or the full URL of its agent card"
}
},
"required": [
"agent"
],
"additionalProperties": false
}Output Schema
{
"type": "object",
"properties": {
"schema": {
"type": "string",
"description": "Format name of this object: gate-preflight-v1."
},
"agent": {
"type": "string",
"description": "The agent's https origin."
},
"card_url": {
"type": "string",
"description": "The agent card URL that was fetched."
},
"card_status": {
"type": [
"integer",
"null"
],
"description": "HTTP status the card URL answered with."
},
"extension_declared": {
"type": "boolean",
"description": "true = the card declares the A2A Conduct Extension. false is not a negative verdict."
},
"declared_uri": {
"type": [
"string",
"null"
],
"description": "The extension URI the card declared, or null."
},
"compensation": {
"type": [
"object",
"null"
],
"description": "Who the agent says pays it, as declared and not verified, or null when it says nothing."
},
"compensation_source": {
"type": [
"string",
"null"
],
"description": "Where the compensation declaration was read: extension params or card top-level."
},
"card_signature_present": {
"type": "boolean",
"description": "Whether the card carries a signature. Presence only; the signature is not verified here."
},
"measured_endpoints": {
"type": "array",
"description": "The https endpoints the card asks to be measured on, at most 5."
},
"register": {
"type": "array",
"description": "This register's stored reading for each of those endpoints: state, verified (true or null, never false), record_sha256."
},
"witness_intake": {
"type": [
"string",
"null"
],
"description": "Where the card says witness records can be filed, or null."
},
"conduct_record": {
"type": [
"string",
"null"
],
"description": "Where the card says its conduct record is published, or null."
},
"how_to_file": {
"type": "string",
"description": "How to walk the agent yourself and file your own record."
},
"does_not_establish": {
"type": "array",
"description": "What this reading does not establish, as sentences."
},
"ok": {
"type": "boolean",
"description": "Always true in this object: the card was fetched and read."
}
},
"description": "What the agent's public card declares and what this register holds for the endpoints it names. Counts and pointers, never a score. A card that could not be fetched or read comes back as a tool error (isError), not as this object.",
"additionalProperties": true
}Community
Evidence