Whisper
One routable IPv6 per AI agent, verifiable from the DNS root. Keyless tools need no signup.
Should I use this
Quality & Safety
Findings (3)
- LOWin whisper_lookupTlsFingerprint
- LOWin whisper_lookupTorRelay
- LOWin whisper_topAsnsByPrefixCount
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": {
"whisper": {
"command": "npx",
"args": [
"@whisper-security/whisper-mcp"
]
}
}
}Runnable packages
0.219.3stdioRemote endpoints
https://whisper.online/mcpstreamable-httpWhat it can do
Tool inventory
Tools (17)
🟡whisper_signup(input)
Start or complete Whisper signup from an email address alone, and receive an API key that unlocks the provisioning and governance skills on this card. Send {"email":"..."} to start; a six-digit code arrives by email; send {"signup_id":"...","code":"123456"} to complete. No human step, no account needed first. Example call: {"skill":"signup","input":{"email":"[email protected]"}}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "object",
"description": "Arguments for this operation, as an object. The example passes {\"email\":\"[email protected]\"}."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"ok": {
"type": "boolean",
"description": "Whether the step succeeded."
},
"signup_id": {
"type": "string",
"description": "Returned by the first step. Send it back with the six-digit code from the email to finish."
},
"api_key": {
"type": "string",
"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."
},
"message": {
"type": "string",
"description": "What to do next, in a sentence."
}
},
"required": [
"ok"
],
"description": "The result of a signup step: an id to continue with, or the API key itself."
}🟢whisper_verify(input)
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"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"is_whisper_agent": {
"type": "boolean",
"description": "The verdict. False is an ANSWER, not a failure: the address or name is simply not a Whisper agent, and the evidence says which leg of the chain is missing."
},
"evidence": {
"type": "object",
"description": "What was checked and what was found: the address or fqdn as given, the PTR, and the forward record that did or did not confirm it."
},
"detail": {
"type": "string",
"description": "A sentence explaining a negative verdict. Absent on a positive one."
},
"fqdn": {
"type": "string",
"description": "The agent's canonical hostname, forward-confirmed against the address. Positive verdicts only."
},
"operator": {
"type": "string",
"description": "The opaque handle of the account that owns this agent."
},
"tenant": {
"type": "string",
"description": "The tenant handle, which also appears inside the fqdn."
},
"dane_ok": {
"type": "boolean",
"description": "Whether the certificate this address actually serves satisfies the DANE-EE pin published for it in DNSSEC-signed DNS. This is the leg that cannot be forged without the zone."
},
"jws_ok": {
"type": "boolean",
"description": "Whether a verifiable signed identity document can be produced for this agent."
},
"verified_at": {
"type": "string",
"description": "When this verdict was graded, ISO 8601."
}
},
"required": [
"is_whisper_agent",
"evidence"
],
"description": "Whether an address or hostname is a Whisper agent, with the evidence for the verdict either way. Every leg is independently checkable from the DNS root with dig."
}🟢whisper_rdap(input)
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"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes 2a04:2a01:b69a:6717:e3b0:51ff:3bf7:f478."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"objectClassName": {
"type": "string",
"description": "Always \"ip network\" for this tool (RFC 9083)."
},
"handle": {
"type": "string",
"description": "The registry handle for this address."
},
"name": {
"type": "string",
"description": "The label its owner gave it."
},
"type": {
"type": "string",
"description": "What kind of allocation this is."
},
"country": {
"type": "string",
"description": "Two-letter country code of the registration."
},
"ipVersion": {
"type": "string",
"description": "\"v6\" or \"v4\"."
},
"startAddress": {
"type": "string",
"description": "First address of the range."
},
"endAddress": {
"type": "string",
"description": "Last address of the range."
},
"status": {
"type": "array",
"description": "Registry status values for the object."
},
"entities": {
"type": "array",
"description": "The parties behind the registration, in RFC 9083 entity form."
},
"events": {
"type": "array",
"description": "Registration lifecycle events with their timestamps."
},
"remarks": {
"type": "array",
"description": "Free-text notes the registry publishes with the object."
},
"links": {
"type": "array",
"description": "Related RDAP and web resources."
},
"notices": {
"type": "array",
"description": "Service-level notices, including the terms of use."
},
"rdapConformance": {
"type": "array",
"description": "The RDAP extensions this answer conforms to."
}
},
"required": [
"objectClassName",
"handle"
],
"description": "The public registration record for one address, RFC 9083 shaped, byte-for-byte what the RDAP service serves at /ip/{address}."
}🟢whisper_identify(input)
Identify an indicator (domain, IP, hash, …) against the graph. Answers without an API key. Example call: {"skill":"identify","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_assess(input)
Assess the risk/policy posture of one or more indicators. Answers without an API key. Example call: {"skill":"assess","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_walk(input)
Walk the graph from an indicator across its relationships. Answers without an API key. Example call: {"skill":"walk","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}⚪whisper_watch(input)
Watch an indicator for change/activity over time. Answers without an API key. Example call: {"skill":"watch","input":{"action":"list"}}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "object",
"description": "Arguments for this operation, as an object. The example passes {\"action\":\"list\"}."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_explain(input)
Explain a verdict - the evidence and reasoning behind it. Answers without an API key. Example call: {"skill":"explain","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_variants(input)
Enumerate variants/permutations of an indicator. Answers without an API key. Example call: {"skill":"variants","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_origins(input)
Trace the origins/provenance of an indicator. Answers without an API key. Example call: {"skill":"origins","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_history(input)
Historical records for an indicator (incl. whois/bgp history). Answers without an API key. Example call: {"skill":"history","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_lookupTlsFingerprint(input)
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"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes ja3:771,4865-4866-4867."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_lookupTorRelay(input)
Look up Tor relay metadata for an address. Answers without an API key. Example call: {"skill":"lookupTorRelay","input":"185.220.101.1"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes 185.220.101.1."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_asset(input)
Resolve an asset and its catalog of attributes. Answers without an API key. Example call: {"skill":"asset","input":"example.com"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes example.com."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_threatintel(input, sub)
Threat-intelligence indicator family (candidate apex/CDN/hosting). A family verb: name the sub-verb as "sub" alongside the input. Sub-verbs: candidateCdnApex, candidateMultiTenantApex, candidateSharedHostingIp.. Answers without an API key. Example call: {"skill":"threatintel","sub":"candidateCdnApex","input":5}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "integer",
"description": "A row limit. The example passes 5."
},
"sub": {
"type": "string",
"description": "Which sub-verb of this family to run. The example runs \"candidateCdnApex\"."
}
},
"required": [
"sub",
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_psl(input, sub)
Public-suffix-list family (tld-plus-one, is-public-suffix, affiliation). A family verb: name the sub-verb as "sub" alongside the input. Sub-verbs: tldPlusOne, isPublicSuffix, affiliation.. Answers without an API key. Example call: {"skill":"psl","sub":"tldPlusOne","input":"a.b.example.co.uk"}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "string",
"description": "The indicator to look up: a domain, an IP address, an ASN or a file hash. The example passes a.b.example.co.uk."
},
"sub": {
"type": "string",
"description": "Which sub-verb of this family to run. The example runs \"tldPlusOne\"."
}
},
"required": [
"sub",
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}🟢whisper_topAsnsByPrefixCount(input)
Top ASNs ranked by announced-prefix count. Answers without an API key. Example call: {"skill":"topAsnsByPrefixCount","input":10}
Input Schema
{
"type": "object",
"properties": {
"input": {
"type": "integer",
"description": "A row limit. The example passes 10."
}
},
"required": [
"input"
]
}Output Schema
{
"type": "object",
"properties": {
"columns": {
"type": "array",
"items": {
"type": "string"
},
"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."
},
"rows": {
"type": "array",
"items": {
"type": "object"
},
"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."
},
"statistics": {
"type": "object",
"description": "What the query cost.",
"properties": {
"rowCount": {
"type": "integer",
"description": "How many rows came back."
},
"executionTimeMs": {
"type": "integer",
"description": "Milliseconds the graph spent answering."
}
},
"required": [
"rowCount"
]
}
},
"required": [
"columns",
"rows"
],
"description": "A tabular graph answer: the column names, the rows keyed by them, and the cost."
}Community
Evidence