MCP server
Every MCP client that connects to a server it downloaded from npm is trusting a stranger with tool-calling access to whatever the model can reach.
Most servers give it no way to check who it's actually talking to — or to prove who it is when another agent connects.
The Model Context Protocol standardized how a client and a server talk (JSON-RPC 2.0 over stdio, tools/list, tools/call), but it left trust as someone else's problem. A server can claim to be "the finance-approval tool" in its tools/list description; nothing stops it from lying, and nothing lets the calling model check. Whisper ships one MCP server, io.github.whisper-sec/whisper, that closes exactly that gap: two keyless tools any MCP client can call to verify a real network identity against the DNSSEC root — no account, no key, no trust in Whisper's word required — plus, when your API key is present, the same control-plane verbs the CLI and SDKs expose, as tools an LLM can call directly: register an agent, read logs, set policy, revoke, get egress config. One binary, one registry entry, stdio in, JSON out.
Why MCP servers need an identity primitive, not just a directory listing
tools/listis self-asserted. A server'snameanddescriptionfields are exactly as trustworthy as a bearer token pasted into a prompt — the server wrote them itself. There is no field in the MCP spec that lets a client cryptographically confirm which server, or which agent behind it, it's actually connected to.- Registries index metadata, not identity. The MCP Registry (
server.json, published via GitHub Actions OIDC) proves a server's publisher controls the named GitHub repo — a supply-chain fact. It says nothing about the runtime identity of whichever process ends up handling a given tool call, especially once a server proxies to other agents. - The fix is the same one two agents use to trust each other. Whisper's answer here is exactly the agent-to-agent trust model applied to MCP: give every agent a real, routable IPv6
/128whose forward DNS, reverse DNS, DANETLSA, and RDAP registration all agree — checkable by anyone, with tools that predate MCP by decades. Thewhisper_verifytool just puts that check one tool-call away for any model that can reach an MCP server.
Put whisper_verify in front of any inbound MCP tool call you don't already trust — a marketplace router dispatching to third-party servers, an orchestrator accepting sub-agent results, a server itself checking who's calling it. One round trip turns "trust the description field" into a fact the model can re-derive.
The tool set: two keyless, six key-gated
whisper mcp starts a stdio JSON-RPC server implementing the core MCP methods (initialize, tools/list, tools/call, ping) — the set that's stable across every spec revision from 2024-11-05 on. It echoes back whatever protocolVersion the client sends at initialize, so any conformant client (older or newer) negotiates cleanly. Its tool catalogue is two-tier by construction, per the same Postel's-Law design every Whisper integration follows:
| Tool | Gate | Does |
|---|---|---|
whisper_verify |
keyless | Full trust chain (reverse-DNS + DANE-EE TLSA + DNSSEC + JWS) for an address or FQDN → verdict JSON |
whisper_rdap |
keyless | RDAP registration record for a /128 — operator, tenant, issued-since |
whisper_register |
key | Create an agent: name in, routable /128 + DNS name out |
whisper_list |
key | List your tenant's agents, DNS records, or identities |
whisper_policy |
key | Read or set your tenant's resolver policy (block/allow/default) |
whisper_logs |
key | Query an agent's DNS/connection/allocation history |
whisper_revoke |
key | Irreversibly withdraw an agent's /128, reverse-DNS, and keys |
whisper_egress_config |
key | Return the proxy env + whisper connect/run command to source a workload from an agent's /128 |
The server decides which half to advertise by resolving the standard key ladder (WHISPER_API_KEY/WHISPER_KEY env, or a saved whisper login credential) once at startup: no credential resolves → tools/list returns only the two keyless tools; a credential resolves → all eight. A client that calls a control tool without a key gets a normal MCP tool error (isError: true) naming the exact fix, never a silent 500 — the model can read it and act.
Add it to a client
With stock tools — MCP has no special transport magic; it's newline-delimited JSON-RPC over a pipe, so you can drive it with nothing but a shell:
# start the server and hand it a raw initialize + tools/list, by hand
{
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}'
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
} | whisper mcp | jq -c '.result.tools[]?.name // .result.serverInfo'
# call the keyless verify tool directly, no client needed
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"whisper_verify","arguments":{"target":"2a04:2a01:eb5a:ca74:cef2:2a:323d:40d4"}}}' \
| whisper mcp | jq -r '.result.content[0].text' | jq '{is_whisper_agent, dane_ok}'
Wiring a real client is just hand-editing its config file — every MCP client uses the same {"command", "args"} shape, only the top-level key and path differ:
// ~/.cursor/mcp.json, ~/.codeium/windsurf/mcp_config.json, or Zed's settings.json
// (Zed's key is "context_servers"; VS Code's .vscode/mcp.json uses "servers" + "type":"stdio")
{
"mcpServers": {
"whisper": { "command": "whisper", "args": ["mcp"] }
}
}
With Whisper, whisper mcp install writes the project-level configs for you (.mcp.json for Claude Code, .cursor/mcp.json for Cursor) without clobbering any server already there, and prints the exact snippet + file path for every client that only supports a global config:
whisper init claude # zero-config: identity + MCP wiring in one call (see /docs/cli)
# — or, in an existing project —
whisper mcp install
# wrote .mcp.json (Claude Code)
# wrote .cursor/mcp.json (Cursor)
#
# other clients — paste the snippet into the file shown:
# Windsurf ~/.codeium/windsurf/mcp_config.json "mcpServers": { "whisper": {...} }
# Claude Desktop (mac) ~/Library/Application Support/Claude/claude_desktop_config.json
# VS Code (project) .vscode/mcp.json (key is "servers", not mcpServers)
# Zed ~/.config/zed/settings.json (key "context_servers")
# Goose / Continue ~/.config/goose/config.yaml / ~/.continue/config.yaml (YAML)
export WHISPER_API_KEY=whisper_live_… # set in the CLIENT's launch env to unlock the 6 control tools
Restart the client and ask it, in chat, to run whisper_verify against any address — that's the smoke test; a true/false is_whisper_agent back means the wiring is correct end to end.
Registry, packaging, and the wire protocol underneath
The server ships as a single mode of the same cross-compiled whisper binary documented on the CLI page — no separate install, no Python/Node runtime to manage. It's published two ways:
- Container image —
ghcr.io/whisper-sec/whisper(multi-arch, entrypointwhisper), the transport the MCP Registry entry points at:docker run -i ghcr.io/whisper-sec/whisper mcp. - MCP Registry entry —
io.github.whisper-sec/whisper, aserver.jsonin the publicwhisper-sec/whisper-clirepo, publishing via the registry's GitHub Actions OIDC flow (no separate namespace credential — ownership of the repo is the proof, the same supply-chain-attestation model the registry uses for every publisher). - Native binary — anywhere
whisperis already onPATH(Homebrew, Scoop,apt/dnf/apkviaget.whisper.online,go install),whisper mcpruns the identical server with zero container overhead.
Underneath, every call is plain JSON-RPC 2.0 over stdio: a request has {jsonrpc, id, method, params}, a notification omits id and gets no reply, and a tool failure is a normal tools/call result with isError: true and a human-readable content[0].text — never a transport-level error — so a model reading the response can see exactly what went wrong and retry sanely. That's the same clear-error-over-opaque-failure posture as the rest of Whisper's public surface: liberal in what the server accepts (any client, any recent protocol version it negotiates down to), conservative in what it emits (a typed, predictable result every time).
For the broader integration philosophy this server follows — keyless value with zero setup, full control behind a key, proven end-to-end rather than demoed — see Integrations.
Next: Agent-to-agent trust — the identity chain whisper_verify runs · CLI — the whisper binary this server ships inside.