npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@modular-intelligence/dns-recon

v1.0.0

Published

MCP server for DNS & WHOIS reconnaissance

Downloads

78

Readme

DNS Reconnaissance MCP Server

A Model Context Protocol (MCP) server for performing DNS and WHOIS reconnaissance tasks. Query DNS records, perform reverse lookups, retrieve WHOIS registration data, discover subdomains via certificate transparency, and check DNS propagation across global resolvers.

Overview

This MCP server provides a comprehensive toolkit for network reconnaissance and DNS enumeration. It wraps standard command-line tools (dig, whois) and the free Certificate Transparency API (crt.sh) to enable Claude and other MCP clients to:

  • Query various DNS record types (A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV, CAA)
  • Perform reverse DNS lookups
  • Retrieve WHOIS registration information for domains and IP addresses
  • Discover subdomains and certificate information via Certificate Transparency logs
  • Perform passive subdomain enumeration from multiple sources with optional DNS brute-force
  • Check DNS record propagation across global DNS resolvers
  • Attempt DNS zone transfers (AXFR)

All operations include input validation and security checks to prevent injection attacks and invalid queries.

Tools

| Tool | Description | Use Case | |------|-------------|----------| | dns_lookup | Query DNS records with dig | Find A, MX, NS, TXT and other DNS records | | dns_reverse | Reverse DNS lookup for IP | Identify hostname associated with an IP | | whois_lookup | WHOIS registration data | Get registrar, nameservers, and domain/IP details | | cert_transparency | Search Certificate Transparency logs | Discover subdomains via SSL/TLS certificates | | dns_zone_transfer | Attempt DNS AXFR zone transfer | Test for misconfigured nameservers (usually blocked) | | subdomain_enum | Multi-source passive subdomain enumeration | Discover subdomains from cert transparency with optional DNS brute-force | | dns_propagation | Check DNS propagation across global resolvers | Verify DNS record consistency and global propagation |

dns_lookup

Query DNS records for a domain using the dig command.

Input Schema:

{
  "domain": "string (required)",
  "record_type": "enum: A | AAAA | MX | NS | TXT | CNAME | SOA | PTR | SRV | CAA | ANY (default: A)",
  "nameserver": "string (optional, e.g., 8.8.8.8)"
}

Example Request:

{
  "domain": "example.com",
  "record_type": "MX"
}

Example Response:

{
  "domain": "example.com",
  "record_type": "MX",
  "records": [
    {
      "name": "example.com",
      "type": "MX",
      "ttl": 3600,
      "value": "10 mail.example.com"
    },
    {
      "name": "example.com",
      "type": "MX",
      "ttl": 3600,
      "value": "20 mail2.example.com"
    }
  ],
  "query_time_ms": 45,
  "server": "default"
}

Common Record Types:

  • A: IPv4 address
  • AAAA: IPv6 address
  • MX: Mail exchange server
  • NS: Nameserver
  • TXT: Text record (DKIM, SPF, DMARC, verification)
  • CNAME: Canonical name (alias)
  • SOA: Start of Authority
  • PTR: Pointer record (reverse DNS)
  • SRV: Service record
  • CAA: Certificate Authority Authorization
  • ANY: All record types

dns_reverse

Perform a reverse DNS lookup to find the hostname associated with an IP address.

Input Schema:

{
  "ip": "string (required, IPv4 address)"
}

Example Request:

{
  "ip": "93.184.216.34"
}

Example Response:

{
  "ip": "93.184.216.34",
  "hostname": "example.com",
  "query_time_ms": 32
}

Note: Many IP addresses do not have reverse DNS records configured. When no PTR record exists, hostname will be null.

whois_lookup

Retrieve WHOIS registration information for a domain or IP address.

Input Schema:

{
  "query": "string (required, domain or IP address)"
}

Example Request (Domain):

{
  "query": "example.com"
}

Example Response (Domain):

{
  "query": "example.com",
  "registrar": "VeriSign Global Registry Services",
  "creation_date": "1995-08-14T00:00:00Z",
  "expiration_date": "2025-08-13T23:59:59Z",
  "updated_date": "2022-08-14T00:00:00Z",
  "name_servers": [
    "a.iana-servers.net",
    "b.iana-servers.net"
  ],
  "status": [
    "clientDeleteProhibited",
    "clientTransferProhibited",
    "clientUpdateProhibited"
  ],
  "raw": "[Full WHOIS output truncated to 3000 characters...]"
}

Example Request (IP Address):

{
  "query": "93.184.216.0"
}

Example Response (IP):

{
  "query": "93.184.216.0",
  "registrar": "ARIN",
  "creation_date": "2010-06-18T00:00:00Z",
  "expiration_date": null,
  "updated_date": "2010-06-18T00:00:00Z",
  "name_servers": [],
  "status": [],
  "raw": "[Full WHOIS output truncated to 3000 characters...]"
}

Note: The WHOIS response includes parsed fields (registrar, dates, nameservers, status) as well as the raw WHOIS output. Parsing varies by registry and type.

cert_transparency

Search Certificate Transparency (CT) logs via crt.sh to discover subdomains and certificate information.

Input Schema:

{
  "domain": "string (required)",
  "include_expired": "boolean (default: false)"
}

Example Request:

{
  "domain": "example.com",
  "include_expired": false
}

Example Response:

{
  "domain": "example.com",
  "certificate_count": 42,
  "certificates": [
    {
      "issuer_name": "Let's Encrypt Authority X3",
      "common_name": "example.com",
      "name_value": "example.com\nwww.example.com\nmail.example.com",
      "not_before": "2023-11-15T10:30:00Z",
      "not_after": "2024-02-13T10:29:59Z",
      "serial_number": "abc123def456"
    },
    {
      "issuer_name": "DigiCert Global CA G2",
      "common_name": "*.example.com",
      "name_value": "*.example.com\nexample.com",
      "not_before": "2023-01-10T00:00:00Z",
      "not_after": "2024-01-10T23:59:59Z",
      "serial_number": "xyz789uvw012"
    }
  ],
  "unique_subdomains": [
    "api.example.com",
    "blog.example.com",
    "example.com",
    "mail.example.com",
    "www.example.com"
  ]
}

About Certificate Transparency:

Certificate Transparency is a system where publicly-issued SSL/TLS certificates are logged in append-only ledgers. The crt.sh website (run by Comodo) provides free search access to these logs. This is a legitimate, legal, and widely-used reconnaissance technique. No API key is required; the service is free and public.

Use Cases:

  • Discover subdomains without executing network queries
  • Find certificate issuance history
  • Identify new services that may not be DNS enumerated
  • Monitoring unauthorized certificate issuance

subdomain_enum

Perform multi-source passive subdomain enumeration using Certificate Transparency logs and optional DNS brute-force.

Input Parameters:

{
  domain: string                          // Required: Domain to enumerate
  use_bruteforce: boolean                 // Optional: Enable DNS brute-force (default: false)
  max_results: number                     // Optional: Maximum results to return 1-500 (default: 100)
}

Example Request:

{
  "domain": "example.com",
  "use_bruteforce": false,
  "max_results": 100
}

Example Output:

{
  "domain": "example.com",
  "total_found": 12,
  "sources": {
    "crt.sh": 12,
    "dns_bruteforce": 0
  },
  "subdomains": [
    "api.example.com",
    "blog.example.com",
    "cdn.example.com",
    "dev.example.com",
    "example.com",
    "mail.example.com",
    "staging.example.com",
    "static.example.com",
    "support.example.com",
    "test.example.com",
    "wiki.example.com",
    "www.example.com"
  ]
}

With Brute-Force Example Request:

{
  "domain": "example.com",
  "use_bruteforce": true,
  "max_results": 50
}

With Brute-Force Example Output:

{
  "domain": "example.com",
  "total_found": 18,
  "sources": {
    "crt.sh": 12,
    "dns_bruteforce": 6
  },
  "subdomains": [
    "admin.example.com",
    "api.example.com",
    "app.example.com",
    "blog.example.com",
    "cdn.example.com",
    "dashboard.example.com",
    "dev.example.com",
    "docs.example.com",
    "example.com",
    "ftp.example.com",
    "mail.example.com",
    "staging.example.com",
    "static.example.com",
    "support.example.com",
    "test.example.com",
    "wiki.example.com",
    "www.example.com"
  ]
}

How It Works:

The tool uses multiple passive enumeration sources:

  1. Certificate Transparency (crt.sh): Queries public CT logs for SSL/TLS certificates issued to the domain and extracts all Subject Alternative Names (SANs). This is the primary source and requires no DNS queries.

  2. DNS Brute-Force (Optional): If enabled, attempts to resolve common subdomain names (www, mail, api, admin, etc.) by querying Google and Cloudflare DNS. This actively probes for resolvable subdomains.

The results are merged, deduplicated, sorted alphabetically, and limited by the max_results parameter.

dns_propagation

Check DNS record propagation across multiple global resolvers to verify record consistency and propagation status.

Input Parameters:

{
  domain: string                                              // Required: Domain to check
  record_type: "A" | "AAAA" | "MX" | "NS" | "TXT" | "CNAME"  // Required: DNS record type (default: A)
}

Example Request:

{
  "domain": "example.com",
  "record_type": "A"
}

Example Output:

{
  "domain": "example.com",
  "record_type": "A",
  "is_consistent": true,
  "responding_resolvers": 8,
  "total_resolvers": 8,
  "propagation_percentage": 100,
  "results": [
    {
      "resolver": "Google",
      "ip": "8.8.8.8",
      "location": "Global",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 12
    },
    {
      "resolver": "Google Secondary",
      "ip": "8.8.4.4",
      "location": "Global",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 15
    },
    {
      "resolver": "Cloudflare",
      "ip": "1.1.1.1",
      "location": "Global",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 11
    },
    {
      "resolver": "Cloudflare Secondary",
      "ip": "1.0.0.1",
      "location": "Global",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 14
    },
    {
      "resolver": "OpenDNS",
      "ip": "208.67.222.222",
      "location": "US",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 28
    },
    {
      "resolver": "Quad9",
      "ip": "9.9.9.9",
      "location": "Global",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 13
    },
    {
      "resolver": "Level3",
      "ip": "4.2.2.1",
      "location": "US",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 32
    },
    {
      "resolver": "Comodo",
      "ip": "8.26.56.26",
      "location": "US",
      "records": [
        "93.184.216.34"
      ],
      "latency_ms": 26
    }
  ]
}

Inconsistent Records Example:

{
  "domain": "example.com",
  "record_type": "MX",
  "is_consistent": false,
  "responding_resolvers": 7,
  "total_resolvers": 8,
  "propagation_percentage": 87,
  "results": [
    {
      "resolver": "Google",
      "ip": "8.8.8.8",
      "location": "Global",
      "records": [
        "10 mail1.example.com",
        "20 mail2.example.com"
      ],
      "latency_ms": 14
    },
    {
      "resolver": "Cloudflare",
      "ip": "1.1.1.1",
      "location": "Global",
      "records": [
        "10 mail-new.example.com"
      ],
      "latency_ms": 12
    }
  ]
}

Global Resolvers Included:

The tool queries the following public DNS resolvers distributed globally:

  • Google (8.8.8.8, 8.8.4.4) - Global
  • Cloudflare (1.1.1.1, 1.0.0.1) - Global
  • OpenDNS (208.67.222.222) - US
  • Quad9 (9.9.9.9) - Global
  • Level3 (4.2.2.1) - US
  • Comodo (8.26.56.26) - US

Use Cases:

  • Verify DNS record propagation after updates
  • Check for DNS inconsistencies across resolvers
  • Detect if a new DNS record has reached all major resolvers
  • Monitor DNS cache status globally
  • Troubleshoot DNS configuration issues

dns_zone_transfer

Attempt a DNS zone transfer (AXFR) against a nameserver. Zone transfers are typically restricted, but misconfigured servers may allow them.

Input Schema:

{
  "domain": "string (required)",
  "nameserver": "string (required, IP or nameserver domain)"
}

Example Request:

{
  "domain": "example.com",
  "nameserver": "ns1.example.com"
}

Example Response (Successful Transfer):

{
  "domain": "example.com",
  "nameserver": "ns1.example.com",
  "success": true,
  "record_count": 28,
  "records": [
    {
      "name": "example.com",
      "type": "SOA",
      "ttl": 3600,
      "value": "ns1.example.com. hostmaster.example.com. 2023101401 10800 3600 604800 86400"
    },
    {
      "name": "www",
      "type": "A",
      "ttl": 3600,
      "value": "93.184.216.34"
    },
    {
      "name": "mail",
      "type": "A",
      "ttl": 3600,
      "value": "93.184.216.35"
    }
  ],
  "message": "Zone transfer successful: 28 records retrieved"
}

Example Response (Transfer Refused):

{
  "domain": "example.com",
  "nameserver": "8.8.8.8",
  "success": false,
  "record_count": 0,
  "records": [],
  "message": "Zone transfer refused by nameserver (this is expected — most servers restrict AXFR)"
}

Important Notes:

  • Zone transfers are rarely permitted on modern nameservers as they expose the entire zone file
  • Most responses will be "refused" — this is expected and indicates proper security
  • Successful transfers are rare and indicate a misconfiguration worth investigating
  • Only attempt against nameservers you are authorized to test

Prerequisites

This server requires:

  1. dig (DNS lookup utility)

    • Included in bind-tools or dnsutils package
    • macOS: Included by default
    • Linux: sudo apt-get install dnsutils (Debian/Ubuntu) or sudo yum install bind-utils (RedHat/CentOS)
  2. whois (WHOIS client)

    • macOS: Included by default
    • Linux: sudo apt-get install whois (most distributions)
  3. Node.js/Bun Runtime

    • Bun 1.0+ recommended for optimal performance
    • Or Node.js 18+ with compatible runtime

No API keys are required. The crt.sh Certificate Transparency API is completely free and public.

Installation

1. Install Bun

If you don't have Bun installed, install it from bun.sh:

curl -fsSL https://bun.sh/install | bash

2. Clone or navigate to the server directory

cd /path/to/dns-recon

3. Install dependencies

bun install

4. Build the server

bun run build

This creates a compiled binary in the dist/ directory.

5. Verify installation

# Test that dig and whois are available
dig -v
whois -v

# Test the server startup (will hang until interrupted with Ctrl+C)
bun run start

Usage

Via Claude Desktop

Add this to your claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "dns-recon": {
      "command": "bun",
      "args": ["run", "/absolute/path/to/dns-recon/src/index.ts"]
    }
  }
}

Or with the built binary:

{
  "mcpServers": {
    "dns-recon": {
      "command": "bun",
      "args": ["/absolute/path/to/dns-recon/dist/index.js"]
    }
  }
}

Via Claude Code (MCP Settings)

Create or update ~/.mcp/settings.json:

{
  "servers": {
    "dns-recon": {
      "command": "bun",
      "args": ["run", "/absolute/path/to/dns-recon/src/index.ts"],
      "env": {}
    }
  }
}

Stdio Transport

The server uses stdio transport (stdin/stdout) for MCP communication. This is the standard transport for MCP servers and is used by Claude Desktop and compatible clients.

Testing Manually

Use the test-client.js pattern or invoke tools programmatically:

# Start the server
bun run start &

# The server will wait for MCP protocol messages on stdin
# Each tool can be invoked via the standard MCP tool_call interface

Examples

Query A Records

Find the IPv4 address of a domain:

User: "Get the A records for example.com"

Response:

{
  "domain": "example.com",
  "record_type": "A",
  "records": [
    {
      "name": "example.com",
      "type": "A",
      "ttl": 3600,
      "value": "93.184.216.34"
    }
  ],
  "query_time_ms": 42,
  "server": "default"
}

Discover Subdomains

Find subdomains via certificate transparency:

User: "Discover subdomains of example.com using certificate transparency"

Response:

{
  "domain": "example.com",
  "certificate_count": 15,
  "unique_subdomains": [
    "api.example.com",
    "example.com",
    "staging.example.com",
    "www.example.com"
  ],
  "certificates": [...]
}

Enumerate Subdomains with Brute-Force

Find all subdomains using passive and active techniques:

User: "Enumerate subdomains for example.com with DNS brute-force"

Response:

{
  "domain": "example.com",
  "total_found": 18,
  "sources": {
    "crt.sh": 12,
    "dns_bruteforce": 6
  },
  "subdomains": [
    "admin.example.com",
    "api.example.com",
    "app.example.com",
    "blog.example.com",
    "cdn.example.com",
    "dashboard.example.com",
    "dev.example.com",
    "docs.example.com",
    "example.com",
    "ftp.example.com",
    "mail.example.com",
    "staging.example.com",
    "static.example.com",
    "support.example.com",
    "test.example.com",
    "wiki.example.com",
    "www.example.com"
  ]
}

Check DNS Propagation

Verify DNS record propagation globally:

User: "Check if A records for example.com have propagated to all major DNS resolvers"

Response:

{
  "domain": "example.com",
  "record_type": "A",
  "is_consistent": true,
  "responding_resolvers": 8,
  "total_resolvers": 8,
  "propagation_percentage": 100,
  "results": [
    {
      "resolver": "Google",
      "ip": "8.8.8.8",
      "location": "Global",
      "records": ["93.184.216.34"],
      "latency_ms": 12
    },
    {
      "resolver": "Cloudflare",
      "ip": "1.1.1.1",
      "location": "Global",
      "records": ["93.184.216.34"],
      "latency_ms": 11
    }
  ]
}

Check Mail Configuration

Find MX records for a domain:

User: "What are the mail servers for example.com?"

Response:

{
  "domain": "example.com",
  "record_type": "MX",
  "records": [
    {
      "name": "example.com",
      "type": "MX",
      "ttl": 3600,
      "value": "10 mail.example.com"
    },
    {
      "name": "example.com",
      "type": "MX",
      "ttl": 3600,
      "value": "20 mail2.example.com"
    }
  ],
  "query_time_ms": 35,
  "server": "default"
}

Retrieve Domain Registration Info

Get WHOIS information:

User: "Who registered example.com and when?"

Response:

{
  "query": "example.com",
  "registrar": "VeriSign Global Registry Services",
  "creation_date": "1995-08-14T00:00:00Z",
  "expiration_date": "2025-08-13T23:59:59Z",
  "updated_date": "2022-08-14T00:00:00Z",
  "name_servers": [
    "a.iana-servers.net",
    "b.iana-servers.net"
  ],
  "status": ["clientDeleteProhibited"],
  "raw": "[raw WHOIS data]"
}

Reverse DNS Lookup

Find hostname from IP:

User: "What domain is hosted at 93.184.216.34?"

Response:

{
  "ip": "93.184.216.34",
  "hostname": "example.com",
  "query_time_ms": 28
}

Security Considerations

Input Validation

All inputs are validated before execution:

  • Domain names must match the pattern [a-zA-Z0-9][a-zA-Z0-9.\-]+\.[a-zA-Z]{2,} and not exceed 253 characters
  • IPv4 addresses must match standard dotted-decimal notation with octets 0-255
  • Nameservers can be either valid IP addresses or domain names (same validation as above)
  • Record types are restricted to a whitelist: A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV, CAA, ANY

Command Injection Prevention

  • All inputs are passed as separate arguments to execFile, not through shell interpretation
  • Special characters are not expanded or interpreted
  • No shell metacharacters (;, |, &, >, <) can be injected

Network Limitations

  • Commands have a 30-second timeout (except zone transfers which use 15 seconds)
  • Output is buffered with a 5MB limit to prevent memory exhaustion
  • Only standard, authorized network tools (dig, whois) are invoked

WHOIS and Privacy

  • WHOIS lookups retrieve publicly available information
  • Some registries implement GDPR privacy masking for personal details
  • Use responsibly and comply with your local regulations

Rate Limiting

  • This server does not implement rate limiting
  • When integrating with Claude or automation, respect the rate limits of:
    • Your configured DNS servers (typically very lenient)
    • The whois registry (varies, typically 1-2 requests per second)
    • crt.sh (very lenient, no documented rate limit)

Legal and Ethical Use

DNS reconnaissance and WHOIS lookups are completely legal, public operations. However:

  • Only perform reconnaissance on systems you own or have explicit permission to test
  • Zone transfer attempts should only be made against infrastructure you're authorized to test
  • Use this server for authorized security testing, research, and legitimate business purposes
  • Do not use for harassment, unauthorized access attempts, or illegal surveillance

Troubleshooting

"Command not found: dig"

Ensure bind-tools/dnsutils is installed:

  • macOS: Should be pre-installed; try /usr/bin/dig
  • Linux: Install with sudo apt-get install dnsutils or equivalent

"Command not found: whois"

Ensure whois is installed:

  • macOS: Should be pre-installed; try /usr/bin/whois
  • Linux: Install with sudo apt-get install whois

"Invalid domain name format"

Domain must:

  • Start with alphanumeric character
  • Contain only alphanumerics, dots, and hyphens
  • End with at least 2-letter TLD
  • Not exceed 253 characters

Valid: example.com, sub.example.co.uk, test-domain.org Invalid: -example.com, example, example..com, example.c

"Invalid IPv4 address format"

IP must be four decimal numbers 0-255 separated by dots.

Valid: 93.184.216.34, 8.8.8.8, 1.1.1.1 Invalid: 256.1.1.1, 1.1.1, 192.168.0.1.1

"Command timed out"

The operation exceeded the timeout limit (30 seconds for most queries, 15 seconds for zone transfers). This typically indicates:

  • A very slow DNS server
  • Network connectivity issues
  • A nameserver that doesn't respond quickly

Try:

  • Specifying a different nameserver
  • Checking your internet connection
  • Using a public DNS server like 8.8.8.8

"crt.sh API error"

The Certificate Transparency API is temporarily unavailable. Try again in a few moments. This is rare as crt.sh has excellent uptime.

Development

Project Structure

dns-recon/
├── src/
│   ├── index.ts              # Main server setup and tool registration
│   ├── types.ts              # TypeScript interfaces for responses
│   ├── schemas.ts            # Zod validation schemas
│   ├── security.ts           # Input validation functions
│   ├── cli-executor.ts       # Command execution wrapper
│   └── tools/
│       ├── dns-lookup.ts     # dig-based DNS queries
│       ├── dns-reverse.ts    # Reverse DNS lookups
│       ├── whois-lookup.ts   # WHOIS data retrieval
│       ├── cert-transparency.ts  # crt.sh integration
│       ├── dns-zone-transfer.ts  # AXFR zone transfers
│       ├── subdomain-enum.ts     # Passive subdomain enumeration
│       └── dns-propagation.ts    # DNS propagation checking
├── dist/                     # Compiled output (generated by `bun build`)
├── package.json              # Dependencies and scripts
└── README.md                 # This file

Adding a New Tool

  1. Create a new file in src/tools/ with a schema and function
  2. Export the schema and function
  3. Import in src/index.ts
  4. Register with server.tool() in main

Example:

// src/tools/my-tool.ts
import { z } from "zod";
import { domainSchema } from "../schemas.js";

export const myToolSchema = z.object({
  domain: domainSchema,
});

export async function myTool(input: z.infer<typeof myToolSchema>) {
  // Implementation
  return { result: "..." };
}

Then in src/index.ts:

import { myToolSchema, myTool } from "./tools/my-tool.js";

server.tool("my_tool", "Description", myToolSchema.shape, toolHandler(myTool));

Testing

The server uses stdio transport, so testing requires:

  1. Starting the server
  2. Sending MCP protocol messages to stdin
  3. Reading responses from stdout

Or use Claude Desktop/Claude Code with the config above.

Performance

  • DNS lookups: Typically 20-100ms depending on server and query complexity
  • Reverse DNS: Typically 20-50ms
  • WHOIS lookups: Typically 200-500ms due to internet latency
  • Certificate Transparency: Typically 100-300ms (via HTTPS to crt.sh)
  • Subdomain enumeration: Typically 500-2000ms (depends on CT log size and brute-force)
  • DNS propagation: Typically 500-3000ms (queries 8 resolvers in parallel)
  • Zone transfers: Variable, 15-second timeout

Most operations complete within sub-second timeframes for typical domains.

License

MIT

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

See LICENSE file for full text.