Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Certificate changed, valid to 2026-12-18
Certificate changed, valid to 2026-12-18
Certificate changed, valid to 2026-12-18
Certificate changed, valid to 2026-12-18
Changed the definition of "whisper_verify"
{"destructiveHint":false,"openWorldHint":true,"readOnlyHint":falsetrue}
Certificate recorded, valid to 2026-12-18
Authorization not required
Added "whisper_lookupTlsFingerprint", "whisper_lookupTorRelay", "whisper_rdap" and 2 more; removed "whisper_lookuptlsfingerprint", "whisper_lookuptorrelay" and "whisper_topasnsbyprefixcount"; changed the definition of "whisper_assess", "whisper_asset", "whisper_explain" and 9 more (15 tools before, 17 now)
before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}Unknown → Live
First tool surface recorded: 15 tools (server version 0.219.2)
npm:@whisper-security/whisper-mcp (package_npm) — from mcp_registry
https://whisper.online/mcp (mcp_streamable_http) — from mcp_registry
oci:ghcr.io/whisper-sec/whisper:0.219.2 (package_oci) — from mcp_registry
oci:ghcr.io/whisper-sec/whisper:0.214.0 (package_oci) — from mcp_registry
Showing the latest 14 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"The result of a signup step: an id to continue with, or the API key itself.","properties":{"api_key":{"description":"Returned by the second step. This is the credential; send it as the X-API-Key header and the provisioning and governance tools appear in tools/list.","type":"string"},"message":{"description":"What to do next, in a sentence.","type":"string"},"ok":{"description":"Whether the step succeeded.","type":"boolean"},"signup_id":{"description":"Returned by the first step. Send it back with the six-digit code from the email to finish.","type":"string"}},"required":["ok"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}before
—after
{"description":"A tabular graph answer: the column names, the rows keyed by them, and the cost.","properties":{"columns":{"description":"The column names, in order. Every row object has exactly these keys, so this is the row shape and reading it is cheaper than inspecting a row.","items":{"type":"string"},"type":"array"},"rows":{"description":"The answers, one object per row, keyed by the column names above. An empty array means the question was understood and nothing matched, which is an answer and not a failure.","items":{"type":"object"},"type":"array"},"statistics":{"description":"What the query cost.","properties":{"executionTimeMs":{"description":"Milliseconds the graph spent answering.","type":"integer"},"rowCount":{"description":"How many rows came back.","type":"integer"}},"required":["rowCount"],"type":"object"}},"required":["columns","rows"],"type":"object"}lookupTlsFingerprint — Look up a TLS (JA3/JA4) fingerprint in the graph. Answers without an API key. Example call: {"skill":"lookupTlsFingerprint","input":"ja3:771,4865-4866-4867"}
lookupTorRelay — Look up Tor relay metadata for an address. Answers without an API key. Example call: {"skill":"lookupTorRelay","input":"185.220.101.1"}
Look up an address in RDAP — The public registration record for any address in Whisper's space, in RFC 9083 form: the handle, the agent's label, its country, and the entities behind it. The same document the RDAP service serves at /ip/{address}, which any RDAP client can already read. Answers without an API key. Example call: {"skill":"rdap","input":"2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478"}
topAsnsByPrefixCount — Top ASNs ranked by announced-prefix count. Answers without an API key. Example call: {"skill":"topAsnsByPrefixCount","input":10}
Verify a Whisper agent identity — Is this IPv6 address or hostname a real Whisper agent, and whose? Grades the full keyless trust chain: the reverse DNS record, the forward AAAA confirming it back to the same address, and the DANE-EE certificate pin published in DNSSEC-signed DNS. Returns is_whisper_agent with the evidence for the verdict either way, so a negative answer is an answer and not an error. Answers without an API key, and every leg of it is independently checkable from the DNS root with dig. Example call: {"skill":"verify","input":"2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478"}
lookupTlsFingerprint — Look up a TLS (JA3/JA4) fingerprint in the graph. Answers without an API key. Example call: {"skill":"lookupTlsFingerprint","input":"ja3:771,4865-4866-4867"}
lookupTorRelay — Look up Tor relay metadata for an address. Answers without an API key. Example call: {"skill":"lookupTorRelay","input":"185.220.101.1"}
topAsnsByPrefixCount — Top ASNs ranked by announced-prefix count. Answers without an API key. Example call: {"skill":"topAsnsByPrefixCount","input":10}