A lightweight RDAP and DNS-over-HTTPS client that lets Claude look up domain registrations, check name availability, fetch DNS records, and resolve IPs and ASNs without any API keys. Built on IANA bootstrap for automatic registry selection across all TLDs and RIRs. The six tools cover individual lookups (domain WHOIS, DNS records, IP netblocks, ASN details) plus a unified dossier call that runs registration and DNS queries in parallel. Useful for security triage, domain research, or network reconnaissance workflows where you need factual signals like registrar, nameservers, age, and privacy redaction status. Runs on stdio or streamable HTTP, surfaces partial failures as data rather than errors, and handles RDAP-less TLDs explicitly instead of breaking silently.
MCP_LOG_LEVELdefault: infoSets the minimum log level for output (e.g., 'debug', 'info', 'warn').
RDAP_TIMEOUT_MSdefault: 5000HTTP timeout for RDAP requests in milliseconds.
DOH_TIMEOUT_MSdefault: 3000HTTP timeout for DNS-over-HTTPS requests in milliseconds.
RDAP_MAX_RETRIESdefault: 2Max retry attempts on transient RDAP failures.
DOH_MAX_RETRIESdefault: 2Max retry attempts on transient DNS-over-HTTPS failures.
MCP_HTTP_HOSTdefault: 127.0.0.1The hostname for the HTTP server.
MCP_HTTP_PORTdefault: 3010The port to run the HTTP server on.
MCP_HTTP_ENDPOINT_PATHdefault: /mcpThe endpoint path for the MCP server.
MCP_PUBLIC_URLPublic origin override for deployments behind a TLS-terminating reverse proxy (e.g. https://mcp.example.com).
MCP_AUTH_MODEdefault: noneAuthentication mode to use: 'none', 'jwt', or 'oauth'.
Look up domain registration, check availability, fetch DNS records, and resolve IPs and ASNs via RDAP and DNS-over-HTTPS via MCP. STDIO or Streamable HTTP.
Six tools covering domain intelligence, DNS, and IP/ASN resolution:
| Tool | Description |
|---|---|
whois_lookup_domain | Full domain registration record — registrar, created/expiry dates, nameservers, EPP status, DNSSEC, registrant org |
whois_check_availability | Check whether a domain is registered or available for registration |
whois_get_dns | DNS records for any hostname via DNS-over-HTTPS (A, AAAA, MX, TXT, NS, CNAME, SOA, CAA, PTR) |
whois_lookup_ip | IP or CIDR netblock, org, country, abuse contact, and reverse DNS via RIR RDAP |
whois_lookup_asn | Resolve an ASN to its org name, country, and RIR source |
whois_get_dossier | One-call domain triage — registration + DNS in parallel, normalized into a single record with factual signals |
whois_lookup_domainLook up a domain's full RDAP registration record.
registrant_redacted: true explicitly when privacy redaction is in effect (standard post-GDPR for gTLDs)rdap_coverage: false for TLDs without RDAP coverage rather than silently failinglast_update_of_rdap_db event timestamp for data freshness transparencywhois_check_availabilityCheck whether a domain name is registered or available to register.
available: true) — exploits the RDAP spec's intended behavioravailable: false with registrar and expiry_date when registeredavailable: null with rdap_coverage: false for TLDs without RDAP — cannot determine availabilitywhois_get_dnsFetch DNS records via DNS-over-HTTPS.
1.1.1.1 primary, Google 8.8.8.8 fallback (used for CAA records where Cloudflare returns raw hex)cloudflare or google)nxdomain: true in result (not an error) when the domain doesn't exist in DNSwhois_lookup_ipLook up an IP address or CIDR block via RIR RDAP.
ptr: null on failure, not an errorwhois_lookup_asnResolve an ASN to its org name, country, and RIR.
AS15169 or bare integer 15169 formatname, org, country, rir, start_autnum, end_autnumwhois_get_dossierOne-call domain triage aggregating registration and DNS data in parallel.
Promise.allSettledage_days, privacy_redacted, registrar, ns_provider (from NS records), mx_provider (from MX records)source_error on the failed leg)ServiceUnavailable; individual leg failures are data, not errorsBuilt on @cyanheads/mcp-ts-core:
none, jwt, oauthin-memory, filesystem, Supabase, Cloudflare KV/R2/D1Domain and network intelligence:
Agent-friendly output:
rdap_coverage: false tells the agent the TLD lacks RDAP rather than returning a confusing errorregistrant_redacted: true rather than silently absent contact datawhois_get_dossier marks individual legs with source_error and continues; only both-legs-fail escalates to an errorage_days, privacy_redacted, ns_provider, mx_provider are real data; agents chain into threat-intel or risk servers for enrichmentNo API keys or accounts required. Add the following to your MCP client configuration file.
{
"mcpServers": {
"whois-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/whois-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"whois-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/whois-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"whois-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/whois-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
git clone https://github.com/cyanheads/whois-mcp-server.git
cd whois-mcp-server
bun install
cp .env.example .env
# All vars are optional — defaults work for most use cases
| Variable | Description | Default |
|---|---|---|
RDAP_TIMEOUT_MS | HTTP timeout for RDAP requests in milliseconds. | 5000 |
DOH_TIMEOUT_MS | HTTP timeout for DNS-over-HTTPS requests in milliseconds. | 3000 |
RDAP_MAX_RETRIES | Max retry attempts on transient RDAP failures. | 2 |
DOH_MAX_RETRIES | Max retry attempts on transient DoH failures. | 2 |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for HTTP server. | 3010 |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
See .env.example for the full list of optional overrides.
Build and run:
bun run rebuild
bun run start:stdio
# or
bun run start:http
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security
bun run test # Vitest test suite
bun run lint:mcp # Validate MCP definitions against spec
docker build -t whois-mcp-server .
docker run --rm -p 3010:3010 whois-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/whois-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| Path | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools and inits services. |
src/config/ | Server-specific environment variable parsing and validation (Zod). |
src/services/rdap/ | RDAP client — IANA bootstrap cache, domain/IP/ASN lookup, retry. |
src/services/doh/ | DNS-over-HTTPS client — Cloudflare primary, Google fallback. |
src/mcp-server/tools/ | Tool definitions (*.tool.ts). |
tests/ | Vitest tests mirroring src/. |
docs/ | Design and API reference documents. |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storage (IANA bootstrap cache)src/index.ts tools arrayIssues and pull requests are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.