@paulgit/mcp-dns-tools 2.2.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -180,6 +180,46 @@ npm test
180
180
  npm run build
181
181
  ```
182
182
 
183
+ ### Releases
184
+
185
+ Releases are prepared by `.forgejo/workflows/release.yml` when a protected tag matching `v*.*.*` is pushed. The workflow:
186
+
187
+ 1. Requires the tag, `package.json`, `package-lock.json`, and `server.json` versions to match.
188
+ 2. Runs linting, strict type checks, the build, tests, and the production dependency audit.
189
+ 3. Packs the npm tarball and records its npm SHA-1 shasum.
190
+ 4. Uses the runner's Trivy installation and a daily vulnerability database cache.
191
+ 5. Rejects releases with fixed HIGH or CRITICAL vulnerabilities.
192
+ 6. Generates an unfiltered CycloneDX vulnerability disclosure report (VDR) and derives an inventory-only SBOM from it.
193
+ 7. Stages the exact checksummed tarball on npm.
194
+ 8. Creates or updates a draft Forgejo release containing the tarball, checksums, SBOM, and VDR.
195
+ 9. Sends a Pushover notification containing the npm stage ID and approval link.
196
+
197
+ Configure a Forgejo Actions secret named `NPM_TOKEN` using a granular npm token with read/write access restricted to `@paulgit/mcp-dns-tools`. The token does not need to bypass 2FA because the workflow uses npm staged publishing.
198
+
199
+ Configure `PUSHOVER_APP_TOKEN` and `PUSHOVER_USER_KEY` to receive release notifications. A successfully staged release links to the [npm staged-packages page](https://www.npmjs.com/settings/paulgit/staged-packages/); failures link to the Forgejo workflow run.
200
+
201
+ Workflow reruns do not attempt to publish an immutable npm version again. The workflow reuses a pending stage when its shasum matches the tarball, treats an already published version with the same shasum as complete, and fails on any mismatch.
202
+
203
+ To test the release pipeline without creating an npm stage, Forgejo release, or release assets:
204
+
205
+ 1. Open **Actions** in Forgejo and select the **Release** workflow.
206
+ 2. Select **Run workflow** and choose the branch or tag to test.
207
+ 3. Leave **Stage the npm package and create or update Forgejo release assets** disabled.
208
+ 4. Run the workflow.
209
+
210
+ The dry-run still packs and checksums the package, runs the vulnerability gate, generates and validates the SBOM and VDR, and sends a Pushover result linking to the Forgejo workflow run. Generated files remain inside the temporary runner container and are not uploaded. Enabling the publish option on a manual run requires selecting an existing release tag.
211
+
212
+ After the workflow succeeds, review and approve the staged package:
213
+
214
+ ```bash
215
+ npm stage list @paulgit/mcp-dns-tools
216
+ npm stage view <stage-id>
217
+ npm stage download <stage-id>
218
+ npm stage approve <stage-id>
219
+ ```
220
+
221
+ Approval requires 2FA and makes the package public. Publish the corresponding draft release in Forgejo after approving the npm stage.
222
+
183
223
  ### Tool routing smoke test
184
224
 
185
225
  After changing tool metadata, run these prompts in each supported MCP client with and without the optional skill installed:
package/dist/index.js CHANGED
@@ -53,6 +53,16 @@ var RegistrationLookupError = class extends Error {
53
53
  this.name = "RegistrationLookupError";
54
54
  }
55
55
  };
56
+ function ensureRegistrationErrorSource(error, source) {
57
+ if (!(error instanceof RegistrationLookupError) || error.source !== void 0)
58
+ return error;
59
+ return new RegistrationLookupError(
60
+ error.message,
61
+ error.kind,
62
+ source,
63
+ error.reason
64
+ );
65
+ }
56
66
  var bootstrapCache = /* @__PURE__ */ new Map();
57
67
  var blockedAddresses = new net.BlockList();
58
68
  var syntheticHttpsProxyAddresses = new net.BlockList();
@@ -324,7 +334,12 @@ function validateHttpsUrl(value) {
324
334
  async function fetchJson(initialUrl, maximumBytes) {
325
335
  let url = validateHttpsUrl(initialUrl);
326
336
  for (let redirects = 0; redirects <= MAX_REDIRECTS; redirects += 1) {
327
- const addresses = await resolvePublicHostname(url.hostname, true);
337
+ let addresses;
338
+ try {
339
+ addresses = await resolvePublicHostname(url.hostname, true);
340
+ } catch (error) {
341
+ throw ensureRegistrationErrorSource(error, url.href);
342
+ }
328
343
  const dispatcher = new Agent({
329
344
  connect: { lookup: pinnedLookup(addresses) }
330
345
  });
@@ -404,10 +419,12 @@ async function fetchJson(initialUrl, maximumBytes) {
404
419
  "RDAP_TIMEOUT"
405
420
  );
406
421
  }
407
- if (error instanceof RegistrationLookupError) throw error;
422
+ const sourcedError = ensureRegistrationErrorSource(error, url.href);
423
+ if (sourcedError instanceof RegistrationLookupError) throw sourcedError;
408
424
  throw new RegistrationLookupError(
409
- `Request to ${url.hostname} failed: ${errorMessage(error)}`,
410
- "network"
425
+ `Request to ${url.hostname} failed: ${errorMessage(sourcedError)}`,
426
+ "network",
427
+ url.href
411
428
  );
412
429
  } finally {
413
430
  clearTimeout(timeout);
@@ -665,6 +682,9 @@ function normaliseRegistrationDomain(domain) {
665
682
  }
666
683
  return ascii;
667
684
  }
685
+ function ianaWhoisDiscoveryQuery(domain) {
686
+ return domain.split(".").at(-1) ?? domain;
687
+ }
668
688
  function parseWhoisEndpoint(value, allowWebScheme = false) {
669
689
  const candidate = value.includes("://") ? value : `whois://${value}`;
670
690
  let url;
@@ -815,7 +835,7 @@ async function whoisQuery(endpoint, query) {
815
835
  });
816
836
  });
817
837
  }
818
- async function legacyWhois(query) {
838
+ async function legacyWhois(query, discoveryQuery = query) {
819
839
  let endpoint = { host: "whois.iana.org", port: 43 };
820
840
  const visited = /* @__PURE__ */ new Set();
821
841
  let response = "";
@@ -832,7 +852,7 @@ async function legacyWhois(query) {
832
852
  }
833
853
  visited.add(key);
834
854
  try {
835
- response = (await whoisQuery(endpoint, query)).trim();
855
+ response = (await whoisQuery(endpoint, index === 0 ? discoveryQuery : query)).trim();
836
856
  } catch (error) {
837
857
  throw new RegistrationLookupError(
838
858
  errorMessage(error),
@@ -921,7 +941,8 @@ async function legacyWhois(query) {
921
941
  ].join("\n");
922
942
  }
923
943
  function fallbackWarning(error) {
924
- return `${reasonForError("RDAP", error)}: ${errorMessage(error)}; used WHOIS fallback`;
944
+ const source = error instanceof RegistrationLookupError && error.source ? ` at ${error.source}` : "";
945
+ return `${reasonForError("RDAP", error)}${source}: ${errorMessage(error)}; used WHOIS fallback`;
925
946
  }
926
947
  async function domainRegistrationLookupResult(domain) {
927
948
  const normalised = normaliseRegistrationDomain(domain);
@@ -974,7 +995,10 @@ Reason: RDAP_NOT_FOUND`,
974
995
  rdapError = error;
975
996
  }
976
997
  try {
977
- const result = await legacyWhois(normalised);
998
+ const result = await legacyWhois(
999
+ normalised,
1000
+ ianaWhoisDiscoveryQuery(normalised)
1001
+ );
978
1002
  return {
979
1003
  text: rdapError ? `${result}
980
1004
 
@@ -1220,7 +1244,7 @@ import { z } from "zod";
1220
1244
  var package_default = {
1221
1245
  name: "@paulgit/mcp-dns-tools",
1222
1246
  mcpName: "it.paulg/dns-tools",
1223
- version: "2.2.0",
1247
+ version: "2.2.1",
1224
1248
  description: "MCP server for DNS lookups, including CAA checks, reverse DNS, and RDAP-first domain or IP registration data with WHOIS fallback; zero auth, zero config",
1225
1249
  type: "module",
1226
1250
  publishConfig: {
@@ -1230,7 +1254,7 @@ var package_default = {
1230
1254
  node: ">=24"
1231
1255
  },
1232
1256
  bin: {
1233
- "mcp-dns-tools": "./dist/index.js"
1257
+ "mcp-dns-tools": "dist/index.js"
1234
1258
  },
1235
1259
  files: [
1236
1260
  "dist",
@@ -1303,6 +1327,10 @@ var package_default = {
1303
1327
  "*.{json,md,yml,yaml}": [
1304
1328
  "prettier --write"
1305
1329
  ]
1330
+ },
1331
+ allowScripts: {
1332
+ "esbuild@0.27.2": true,
1333
+ "fsevents@2.3.3": true
1306
1334
  }
1307
1335
  };
1308
1336
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/dns.ts","../src/registration.ts","../src/server.ts","../package.json"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { parseCliArgs } from \"./cli.js\";\nimport { configureDnsServers } from \"./dns.js\";\nimport { createMcpServer } from \"./server.js\";\n\nconfigureDnsServers();\n\nasync function main() {\n parseCliArgs(process.argv.slice(2));\n const server = createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n","import { parseArgs } from \"node:util\";\n\nexport interface CliOptions {\n transport: \"stdio\";\n}\n\nexport function parseCliArgs(args: string[]): CliOptions {\n const { values } = parseArgs({\n args,\n options: {\n transport: {\n type: \"string\",\n default: \"stdio\",\n },\n },\n strict: true,\n });\n\n if (values.transport !== \"stdio\") {\n throw new Error(\n `Unsupported transport: ${values.transport}. Only stdio is supported.`,\n );\n }\n\n return { transport: \"stdio\" };\n}\n","import dns from \"node:dns/promises\";\nimport { setServers } from \"node:dns\";\nimport type { CaaRecord } from \"node:dns\";\nimport net from \"node:net\";\nimport type { RegistrationLookupResult } from \"./registration.js\";\nimport {\n domainRegistrationLookup,\n domainRegistrationLookupResult,\n ipRegistrationLookup,\n ipRegistrationLookupResult,\n} from \"./registration.js\";\n\nexport type { RegistrationLookupResult };\n\nexport type RecordType =\n | \"A\"\n | \"AAAA\"\n | \"MX\"\n | \"TXT\"\n | \"CNAME\"\n | \"NS\"\n | \"SOA\"\n | \"SRV\"\n | \"CAA\"\n | \"PTR\";\n\ninterface MxRecord {\n exchange: string;\n priority: number;\n}\n\ninterface SoaRecord {\n nsname: string;\n hostmaster: string;\n serial: number;\n refresh: number;\n retry: number;\n expire: number;\n minttl: number;\n}\n\ninterface SrvRecord {\n priority: number;\n weight: number;\n port: number;\n name: string;\n}\n\nexport function configureDnsServers(env = process.env): void {\n const raw = env.DNS_SERVERS;\n if (!raw) return;\n const servers = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => net.isIP(s) !== 0);\n if (servers.length > 0) {\n setServers(servers);\n }\n}\n\nfunction mapDnsError(error: unknown, type: string, target: string): string {\n const code = (error as NodeJS.ErrnoException).code;\n switch (code) {\n case \"ENODATA\":\n return `No ${type} records found for ${target}.`;\n case \"ENOTFOUND\":\n return `Domain not found: ${target}`;\n case \"EREFUSED\":\n return `DNS server refused the ${type} query for ${target}. The local resolver may not support this record type; set DNS_SERVERS to use a different resolver.`;\n case \"ETIMEOUT\":\n return `DNS query for ${target} (${type}) timed out.`;\n default:\n return `DNS lookup failed for ${target} (${type}): ${code ?? \"unknown error\"}`;\n }\n}\n\nconst DOMAIN_RE =\n /^(?=.{1,253}$)[a-zA-Z0-9_]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9_]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?)*\\.?$/;\n\nfunction assertValidDomain(domain: string): void {\n if (!DOMAIN_RE.test(domain)) {\n throw new Error(\"Invalid domain\");\n }\n}\n\nexport async function dnsLookup(\n domain: string,\n type: RecordType,\n): Promise<string> {\n assertValidDomain(domain);\n let records: unknown;\n try {\n records = await dns.resolve(domain, type);\n } catch (error) {\n return mapDnsError(error, type, domain);\n }\n\n switch (type) {\n case \"MX\": {\n const mx = records as MxRecord[];\n if (mx.length === 0) return \"No MX records found.\";\n return mx\n .sort((a, b) => a.priority - b.priority)\n .map((r) => `${r.priority} ${r.exchange}`)\n .join(\"\\n\");\n }\n case \"TXT\": {\n const txt = records as string[][];\n if (txt.length === 0) return \"No TXT records found.\";\n return txt.map((entries) => entries.join(\"\")).join(\"\\n\");\n }\n case \"CAA\": {\n const caa = records as CaaRecord[];\n if (caa.length === 0) return \"No CAA records found.\";\n const formatted = caa.flatMap(({ critical, ...tags }) =>\n Object.entries(tags)\n .filter(\n (entry): entry is [string, string] =>\n entry[0] !== \"type\" && typeof entry[1] === \"string\",\n )\n .map(([tag, value]) => `${critical} ${tag} ${JSON.stringify(value)}`),\n );\n return formatted.length > 0\n ? formatted.join(\"\\n\")\n : \"No CAA records found.\";\n }\n case \"SOA\": {\n const soa = records as SoaRecord[];\n const s = soa[0];\n if (!s) return \"No SOA record found.\";\n return [\n `nsname: ${s.nsname}`,\n `hostmaster: ${s.hostmaster}`,\n `serial: ${s.serial}`,\n `refresh: ${s.refresh}`,\n `retry: ${s.retry}`,\n `expire: ${s.expire}`,\n `minttl: ${s.minttl}`,\n ].join(\"\\n\");\n }\n case \"SRV\": {\n const srv = records as SrvRecord[];\n if (srv.length === 0) return \"No SRV records found.\";\n return srv\n .map((r) => `${r.priority} ${r.weight} ${r.port} ${r.name}`)\n .join(\"\\n\");\n }\n default: {\n const arr = records as string[];\n if (arr.length === 0) return `No ${type} records found.`;\n return arr.join(\"\\n\");\n }\n }\n}\n\nexport async function reverseDns(ip: string): Promise<string> {\n if (net.isIP(ip) === 0) {\n throw new Error(\"Invalid IP address\");\n }\n let hostnames: string[];\n try {\n hostnames = await dns.reverse(ip);\n } catch (error) {\n return mapDnsError(error, \"PTR\", ip);\n }\n return hostnames.length > 0 ? hostnames.join(\"\\n\") : \"No PTR records found.\";\n}\n\nexport async function resolveAll(domain: string): Promise<string> {\n assertValidDomain(domain);\n const types: { name: string; type: RecordType }[] = [\n { name: \"A\", type: \"A\" },\n { name: \"AAAA\", type: \"AAAA\" },\n { name: \"MX\", type: \"MX\" },\n { name: \"TXT\", type: \"TXT\" },\n { name: \"CAA\", type: \"CAA\" },\n { name: \"NS\", type: \"NS\" },\n { name: \"CNAME\", type: \"CNAME\" },\n ];\n\n const results: string[] = [];\n for (const { name, type } of types) {\n try {\n const records = await dnsLookup(domain, type);\n results.push(`=== ${name} ===\\n${records}`);\n } catch {\n results.push(`=== ${name} ===\\n(no records or error)`);\n }\n }\n return results.join(\"\\n\\n\");\n}\n\nexport async function checkNameservers(domain: string): Promise<string> {\n assertValidDomain(domain);\n let nameservers: string[];\n try {\n nameservers = await dns.resolveNs(domain);\n } catch (error) {\n return mapDnsError(error, \"NS\", domain);\n }\n return nameservers.length > 0\n ? nameservers.join(\"\\n\")\n : \"No nameserver records found.\";\n}\n\nexport async function whoisLookup(domain: string): Promise<string> {\n return await domainRegistrationLookup(domain);\n}\n\nexport async function whoisLookupResult(\n domain: string,\n): Promise<RegistrationLookupResult> {\n return await domainRegistrationLookupResult(domain);\n}\n\nexport async function ipWhois(ip: string): Promise<string> {\n return await ipRegistrationLookup(ip);\n}\n\nexport async function ipWhoisResult(\n ip: string,\n): Promise<RegistrationLookupResult> {\n return await ipRegistrationLookupResult(ip);\n}\n","import dns from \"node:dns/promises\";\nimport net from \"node:net\";\nimport { domainToASCII } from \"node:url\";\nimport { Agent, fetch as undiciFetch } from \"undici\";\n\nconst RDAP_DNS_BOOTSTRAP = \"https://data.iana.org/rdap/dns.json\";\nconst RDAP_IPV4_BOOTSTRAP = \"https://data.iana.org/rdap/ipv4.json\";\nconst RDAP_IPV6_BOOTSTRAP = \"https://data.iana.org/rdap/ipv6.json\";\nconst BOOTSTRAP_TTL_MS = 24 * 60 * 60 * 1000;\nconst REQUEST_TIMEOUT_MS = 10_000;\nconst MAX_REDIRECTS = 3;\nconst MAX_RDAP_BYTES = 1024 * 1024;\nconst MAX_BOOTSTRAP_BYTES = 2 * 1024 * 1024;\nconst MAX_WHOIS_BYTES = 1024 * 1024;\nconst MAX_WHOIS_QUERIES = 3;\n\ninterface BootstrapData {\n services: unknown[];\n}\n\ninterface BootstrapCacheEntry {\n data: BootstrapData;\n expiresAt: number;\n}\n\ninterface RdapResponse {\n data: Record<string, unknown>;\n source: string;\n}\n\ninterface WhoisEndpoint {\n host: string;\n port: number;\n}\n\ninterface ResolvedAddress {\n address: string;\n family: 4 | 6;\n}\n\nexport interface RegistrationLookupResult {\n text: string;\n failed: boolean;\n}\n\nexport type RegistrationReason =\n | \"RDAP_NOT_AVAILABLE\"\n | \"RDAP_NOT_FOUND\"\n | \"RDAP_RATE_LIMITED\"\n | \"RDAP_TIMEOUT\"\n | \"RDAP_NETWORK_ERROR\"\n | \"RDAP_HTTP_ERROR\"\n | \"RDAP_INVALID_RESPONSE\"\n | \"RDAP_DESTINATION_REJECTED\"\n | \"WHOIS_NOT_ADVERTISED\"\n | \"WHOIS_NOT_FOUND\"\n | \"WHOIS_CONNECTION_REFUSED\"\n | \"WHOIS_CONNECTION_RESET\"\n | \"WHOIS_TIMEOUT\"\n | \"WHOIS_DNS_FAILURE\"\n | \"WHOIS_EMPTY_RESPONSE\"\n | \"WHOIS_RATE_LIMITED\"\n | \"WHOIS_SERVICE_RETIRED\"\n | \"WHOIS_WEB_ONLY\"\n | \"WHOIS_UNSUPPORTED_RESPONSE\"\n | \"WHOIS_INVALID_ENCODING\"\n | \"REFERRAL_REJECTED\"\n | \"REFERRAL_LOOP\"\n | \"REFERRAL_LIMIT_REACHED\"\n | \"RESPONSE_TOO_LARGE\"\n | \"UNKNOWN_ERROR\";\n\ninterface RegistrationWarning {\n reason: RegistrationReason;\n detail: string;\n}\n\nclass RegistrationLookupError extends Error {\n constructor(\n message: string,\n readonly kind:\n | \"invalid-response\"\n | \"network\"\n | \"not-found\"\n | \"rate-limited\"\n | \"security\"\n | \"unsupported\",\n readonly source?: string,\n readonly reason?: RegistrationReason,\n ) {\n super(message);\n this.name = \"RegistrationLookupError\";\n }\n}\n\nconst bootstrapCache = new Map<string, BootstrapCacheEntry>();\n\nconst blockedAddresses = new net.BlockList();\nconst syntheticHttpsProxyAddresses = new net.BlockList();\n// Some sandboxed network transports map public hosts into this benchmarking range.\nsyntheticHttpsProxyAddresses.addSubnet(\"198.18.0.0\", 15, \"ipv4\");\nfor (const [address, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n blockedAddresses.addSubnet(address, prefix, \"ipv4\");\n}\nfor (const [address, prefix] of [\n [\"::\", 128],\n [\"::1\", 128],\n [\"64:ff9b:1::\", 48],\n [\"100::\", 64],\n [\"2001:db8::\", 32],\n [\"fc00::\", 7],\n [\"fe80::\", 10],\n [\"fec0::\", 10],\n [\"ff00::\", 8],\n] as const) {\n blockedAddresses.addSubnet(address, prefix, \"ipv6\");\n}\n\nexport function resetRegistrationCaches(): void {\n bootstrapCache.clear();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stringValue(value: unknown): string | undefined {\n if (typeof value === \"string\" && value.trim()) return value.trim();\n if (Array.isArray(value)) {\n const values = value\n .map((entry) => stringValue(entry))\n .filter((entry): entry is string => entry !== undefined);\n return values.length > 0 ? values.join(\", \") : undefined;\n }\n return undefined;\n}\n\nfunction stringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0,\n );\n}\n\nfunction isBlockedAddress(address: string): boolean {\n const family = net.isIP(address);\n if (family === 4) return blockedAddresses.check(address, \"ipv4\");\n if (family === 6) return blockedAddresses.check(address, \"ipv6\");\n return true;\n}\n\nasync function resolvePublicHostname(\n hostname: string,\n allowSyntheticNetworkProxy = false,\n): Promise<ResolvedAddress[]> {\n const normalised = hostname\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\")\n .toLowerCase();\n if (\n !normalised ||\n normalised === \"localhost\" ||\n normalised.endsWith(\".local\")\n ) {\n throw new RegistrationLookupError(\n `Refusing registration-data connection to ${hostname}`,\n \"security\",\n );\n }\n\n if (net.isIP(normalised) !== 0) {\n if (isBlockedAddress(normalised)) {\n throw new RegistrationLookupError(\n `Refusing registration-data connection to non-public address ${hostname}`,\n \"security\",\n );\n }\n return [\n {\n address: normalised,\n family: net.isIP(normalised) as 4 | 6,\n },\n ];\n }\n\n let addresses: { address: string; family: number }[];\n try {\n addresses = await dns.lookup(normalised, {\n all: true,\n verbatim: true,\n });\n } catch (error) {\n throw new RegistrationLookupError(\n `Unable to resolve registration-data service ${hostname}: ${errorMessage(error)}`,\n \"network\",\n );\n }\n\n const resolved = addresses.filter(\n (entry): entry is ResolvedAddress =>\n entry.family === 4 || entry.family === 6,\n );\n if (\n resolved.length === 0 ||\n resolved.some(\n (entry) =>\n isBlockedAddress(entry.address) &&\n !(\n allowSyntheticNetworkProxy &&\n entry.family === 4 &&\n syntheticHttpsProxyAddresses.check(entry.address, \"ipv4\")\n ),\n )\n ) {\n throw new RegistrationLookupError(\n `Refusing registration-data connection to ${hostname}: destination is not public`,\n \"security\",\n );\n }\n return resolved;\n}\n\nfunction pinnedLookup(addresses: ResolvedAddress[]): net.LookupFunction {\n return (_hostname, options, callback): void => {\n const requestedFamily = options.family ?? 0;\n const candidates = addresses.filter(\n (entry) => requestedFamily === 0 || entry.family === requestedFamily,\n );\n if (candidates.length === 0) {\n const error = new Error(\n `No validated address for requested family ${requestedFamily}`,\n ) as NodeJS.ErrnoException;\n error.code = \"EAI_ADDRFAMILY\";\n callback(error, \"\");\n return;\n }\n if (options.all) {\n callback(null, candidates);\n return;\n }\n const [selected] = candidates;\n if (!selected) {\n callback(new Error(\"No validated address available\"), \"\");\n return;\n }\n callback(null, selected.address, selected.family);\n };\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"unknown error\";\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return error instanceof Error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n}\n\nfunction reasonForError(\n protocol: \"RDAP\" | \"WHOIS\",\n error: unknown,\n): RegistrationReason {\n if (error instanceof RegistrationLookupError && error.reason)\n return error.reason;\n\n const message = errorMessage(error).toLowerCase();\n const code = errorCode(error);\n if (message.includes(\"exceeds\") && message.includes(\"bytes\"))\n return \"RESPONSE_TOO_LARGE\";\n if (message.includes(\"referral loop\")) return \"REFERRAL_LOOP\";\n if (message.includes(\"referral limit\")) return \"REFERRAL_LIMIT_REACHED\";\n\n if (protocol === \"RDAP\") {\n if (error instanceof RegistrationLookupError && error.kind === \"not-found\")\n return \"RDAP_NOT_FOUND\";\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"rate-limited\"\n )\n return \"RDAP_RATE_LIMITED\";\n if (message.includes(\"timed out\") || code === \"ETIMEDOUT\")\n return \"RDAP_TIMEOUT\";\n if (message.includes(\"http \")) return \"RDAP_HTTP_ERROR\";\n if (error instanceof RegistrationLookupError && error.kind === \"security\")\n return \"RDAP_DESTINATION_REJECTED\";\n if (\n error instanceof RegistrationLookupError &&\n (error.kind === \"invalid-response\" || error.kind === \"unsupported\")\n )\n return error.kind === \"unsupported\"\n ? \"RDAP_NOT_AVAILABLE\"\n : \"RDAP_INVALID_RESPONSE\";\n return \"RDAP_NETWORK_ERROR\";\n }\n\n if (code === \"ECONNREFUSED\") return \"WHOIS_CONNECTION_REFUSED\";\n if (code === \"ECONNRESET\") return \"WHOIS_CONNECTION_RESET\";\n if (code === \"ENOTFOUND\" || code === \"EAI_AGAIN\") return \"WHOIS_DNS_FAILURE\";\n if (message.includes(\"unable to resolve registration-data service\"))\n return \"WHOIS_DNS_FAILURE\";\n if (message.includes(\"timed out\") || code === \"ETIMEDOUT\")\n return \"WHOIS_TIMEOUT\";\n if (message.includes(\"no whois data\")) return \"WHOIS_EMPTY_RESPONSE\";\n if (error instanceof RegistrationLookupError && error.kind === \"unsupported\")\n return \"WHOIS_NOT_ADVERTISED\";\n if (error instanceof RegistrationLookupError && error.kind === \"rate-limited\")\n return \"WHOIS_RATE_LIMITED\";\n if (error instanceof RegistrationLookupError && error.kind === \"security\")\n return \"REFERRAL_REJECTED\";\n return \"UNKNOWN_ERROR\";\n}\n\nfunction warningText(warning: RegistrationWarning): string {\n return `${warning.reason}: ${warning.detail}`;\n}\n\nfunction failureSuggestion(\n rdapReason: RegistrationReason,\n whoisReason: RegistrationReason,\n): string {\n if (whoisReason === \"WHOIS_WEB_ONLY\")\n return \"Use the registry's web-based registration lookup service.\";\n if (\n rdapReason === \"RDAP_RATE_LIMITED\" ||\n whoisReason === \"WHOIS_RATE_LIMITED\"\n )\n return \"Retry later and reduce lookup frequency.\";\n if (whoisReason === \"WHOIS_SERVICE_RETIRED\")\n return \"Use the registry's RDAP or web-based replacement service.\";\n if (\n whoisReason === \"WHOIS_CONNECTION_REFUSED\" ||\n whoisReason === \"WHOIS_CONNECTION_RESET\" ||\n whoisReason === \"WHOIS_TIMEOUT\" ||\n whoisReason === \"WHOIS_DNS_FAILURE\"\n )\n return \"Check outbound HTTPS and TCP port 43 access, then retry.\";\n if (\n whoisReason === \"WHOIS_NOT_ADVERTISED\" ||\n whoisReason === \"WHOIS_UNSUPPORTED_RESPONSE\"\n )\n return \"Consult the TLD registry website for its supported lookup service.\";\n if (whoisReason === \"REFERRAL_REJECTED\" || whoisReason === \"REFERRAL_LOOP\")\n return \"Use the last authoritative source shown or consult the registry website.\";\n return \"Retry later or consult the registry's registration-data service.\";\n}\n\nfunction formatLookupFailure(\n queryType: \"Domain\" | \"IP\",\n query: string,\n rdapError: unknown,\n whoisError: unknown,\n): string {\n const rdapReason = reasonForError(\"RDAP\", rdapError);\n const whoisReason = reasonForError(\"WHOIS\", whoisError);\n const rdapSource =\n rdapError instanceof RegistrationLookupError ? rdapError.source : undefined;\n const whoisSource =\n whoisError instanceof RegistrationLookupError\n ? whoisError.source\n : undefined;\n return [\n \"Status: failed\",\n `${queryType}: ${query}`,\n \"RDAP status: failed\",\n `RDAP reason: ${rdapReason}`,\n ...(rdapSource ? [`RDAP source: ${rdapSource}`] : []),\n `RDAP detail: ${errorMessage(rdapError)}`,\n \"WHOIS status: failed\",\n `WHOIS reason: ${whoisReason}`,\n ...(whoisSource ? [`WHOIS source: ${whoisSource}`] : []),\n `WHOIS detail: ${errorMessage(whoisError)}`,\n `Suggestion: ${failureSuggestion(rdapReason, whoisReason)}`,\n ].join(\"\\n\");\n}\n\nasync function readResponseBody(\n response: Response,\n maximumBytes: number,\n): Promise<string> {\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && Number(contentLength) > maximumBytes) {\n await response.body?.cancel();\n throw new RegistrationLookupError(\n `Registration-data response exceeds ${maximumBytes} bytes`,\n \"invalid-response\",\n );\n }\n\n if (!response.body) return \"\";\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > maximumBytes) {\n try {\n await reader.cancel();\n } catch {\n // The size-limit error below is more useful than a cancellation error.\n }\n throw new RegistrationLookupError(\n `Registration-data response exceeds ${maximumBytes} bytes`,\n \"invalid-response\",\n );\n }\n chunks.push(value);\n }\n\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nfunction validateHttpsUrl(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new RegistrationLookupError(\n `Invalid RDAP service URL: ${value}`,\n \"invalid-response\",\n );\n }\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n (url.port && url.port !== \"443\")\n ) {\n throw new RegistrationLookupError(\n `Refusing non-standard RDAP service URL: ${value}`,\n \"security\",\n );\n }\n return url;\n}\n\nasync function fetchJson(\n initialUrl: string,\n maximumBytes: number,\n): Promise<{ data: Record<string, unknown>; source: string }> {\n let url = validateHttpsUrl(initialUrl);\n\n for (let redirects = 0; redirects <= MAX_REDIRECTS; redirects += 1) {\n const addresses = await resolvePublicHostname(url.hostname, true);\n const dispatcher = new Agent({\n connect: { lookup: pinnedLookup(addresses) },\n });\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const response = (await undiciFetch(url, {\n headers: {\n accept: \"application/rdap+json, application/json\",\n \"user-agent\": \"mcp-dns-tools/registration-lookup\",\n },\n dispatcher,\n redirect: \"manual\",\n signal: controller.signal,\n })) as unknown as Response;\n\n if ([301, 302, 303, 307, 308].includes(response.status)) {\n const location = response.headers.get(\"location\");\n if (!location) {\n throw new RegistrationLookupError(\n `RDAP redirect from ${url.hostname} has no location`,\n \"invalid-response\",\n );\n }\n if (redirects === MAX_REDIRECTS) {\n throw new RegistrationLookupError(\n \"RDAP redirect limit exceeded\",\n \"invalid-response\",\n );\n }\n await response.body?.cancel();\n url = validateHttpsUrl(new URL(location, url).href);\n continue;\n }\n\n const body = await readResponseBody(response, maximumBytes);\n if (response.status === 404) {\n throw new RegistrationLookupError(\n \"Registration data not found\",\n \"not-found\",\n url.href,\n );\n }\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n throw new RegistrationLookupError(\n `RDAP service rate limited the request${retryAfter ? `; retry after ${retryAfter}` : \"\"}`,\n \"rate-limited\",\n );\n }\n if (!response.ok) {\n throw new RegistrationLookupError(\n `RDAP service returned HTTP ${response.status}`,\n \"network\",\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n throw new RegistrationLookupError(\n `RDAP service ${url.hostname} returned invalid JSON`,\n \"invalid-response\",\n );\n }\n if (!isRecord(parsed)) {\n throw new RegistrationLookupError(\n `RDAP service ${url.hostname} returned an invalid object`,\n \"invalid-response\",\n );\n }\n return { data: parsed, source: url.href };\n } catch (error) {\n if (controller.signal.aborted) {\n throw new RegistrationLookupError(\n `Request to ${url.hostname} timed out`,\n \"network\",\n url.href,\n \"RDAP_TIMEOUT\",\n );\n }\n if (error instanceof RegistrationLookupError) throw error;\n throw new RegistrationLookupError(\n `Request to ${url.hostname} failed: ${errorMessage(error)}`,\n \"network\",\n );\n } finally {\n clearTimeout(timeout);\n await dispatcher.close();\n }\n }\n\n throw new RegistrationLookupError(\"RDAP request failed\", \"network\");\n}\n\nasync function getBootstrap(url: string): Promise<BootstrapData> {\n const cached = bootstrapCache.get(url);\n if (cached && cached.expiresAt > Date.now()) return cached.data;\n\n const response = await fetchJson(url, MAX_BOOTSTRAP_BYTES);\n const services = response.data.services;\n if (!Array.isArray(services)) {\n throw new RegistrationLookupError(\n \"IANA RDAP bootstrap response has no services array\",\n \"invalid-response\",\n );\n }\n const data = { services };\n bootstrapCache.set(url, { data, expiresAt: Date.now() + BOOTSTRAP_TTL_MS });\n return data;\n}\n\nfunction bootstrapServices(\n data: BootstrapData,\n): { entries: string[]; urls: string[] }[] {\n const services: { entries: string[]; urls: string[] }[] = [];\n for (const service of data.services) {\n if (!Array.isArray(service) || service.length !== 2) continue;\n const entries = stringArray(service[0]).map((entry) => entry.toLowerCase());\n const urls = stringArray(service[1]).filter((url) =>\n url.startsWith(\"https://\"),\n );\n if (entries.length > 0 && urls.length > 0) services.push({ entries, urls });\n }\n return services;\n}\n\nfunction domainServiceUrls(data: BootstrapData, domain: string): string[] {\n let longestMatch = -1;\n let urls: string[] = [];\n for (const service of bootstrapServices(data)) {\n for (const entry of service.entries) {\n if (domain !== entry && !domain.endsWith(`.${entry}`)) continue;\n const labels = entry.split(\".\").length;\n if (labels > longestMatch) {\n longestMatch = labels;\n urls = [...service.urls];\n } else if (labels === longestMatch) {\n urls.push(...service.urls);\n }\n }\n }\n return [...new Set(urls)];\n}\n\nfunction ipServiceUrls(data: BootstrapData, ip: string): string[] {\n const family = net.isIP(ip);\n const type = family === 4 ? \"ipv4\" : \"ipv6\";\n let longestPrefix = -1;\n let urls: string[] = [];\n\n for (const service of bootstrapServices(data)) {\n for (const entry of service.entries) {\n const [network, rawPrefix] = entry.split(\"/\");\n const prefix = Number(rawPrefix);\n if (!network || !Number.isInteger(prefix) || net.isIP(network) !== family)\n continue;\n try {\n const block = new net.BlockList();\n block.addSubnet(network, prefix, type);\n if (!block.check(ip, type)) continue;\n } catch {\n continue;\n }\n if (prefix > longestPrefix) {\n longestPrefix = prefix;\n urls = [...service.urls];\n } else if (prefix === longestPrefix) {\n urls.push(...service.urls);\n }\n }\n }\n return [...new Set(urls)];\n}\n\nasync function queryFirstRdapService(\n baseUrls: string[],\n path: string,\n): Promise<RdapResponse> {\n let lastError: unknown;\n for (const baseUrl of baseUrls) {\n try {\n const base = validateHttpsUrl(baseUrl);\n if (!base.pathname.endsWith(\"/\")) base.pathname += \"/\";\n const queryUrl = new URL(path, base);\n return await fetchJson(queryUrl.href, MAX_RDAP_BYTES);\n } catch (error) {\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"not-found\"\n ) {\n throw error;\n }\n lastError = error;\n }\n }\n throw (\n lastError ??\n new RegistrationLookupError(\"No usable RDAP service\", \"unsupported\")\n );\n}\n\nfunction relatedRdapUrl(data: Record<string, unknown>): string | undefined {\n if (!Array.isArray(data.links)) return undefined;\n for (const value of data.links) {\n if (!isRecord(value) || value.rel !== \"related\") continue;\n const href = stringValue(value.href);\n const type = stringValue(value.type);\n if (href && type?.toLowerCase().includes(\"application/rdap+json\"))\n return href;\n }\n return undefined;\n}\n\nfunction eventLines(data: Record<string, unknown>): string[] {\n if (!Array.isArray(data.events)) return [];\n const labels: Record<string, string> = {\n registration: \"Registered\",\n expiration: \"Expires\",\n \"last changed\": \"Updated\",\n \"last update of RDAP database\": \"RDAP database updated\",\n };\n const lines: string[] = [];\n for (const event of data.events) {\n if (!isRecord(event)) continue;\n const action = stringValue(event.eventAction);\n const date = stringValue(event.eventDate);\n if (action && date) lines.push(`${labels[action] ?? action}: ${date}`);\n }\n return lines;\n}\n\nfunction vcardFields(entity: Record<string, unknown>): Map<string, string[]> {\n const fields = new Map<string, string[]>();\n if (!Array.isArray(entity.vcardArray) || !Array.isArray(entity.vcardArray[1]))\n return fields;\n for (const property of entity.vcardArray[1]) {\n if (!Array.isArray(property) || property.length < 4) continue;\n const name = stringValue(property[0])?.toLowerCase();\n const value = stringValue(property[3]);\n if (!name || !value) continue;\n fields.set(name, [...(fields.get(name) ?? []), value]);\n }\n return fields;\n}\n\nfunction entityLines(data: Record<string, unknown>): string[] {\n if (!Array.isArray(data.entities)) return [];\n const lines: string[] = [];\n const visit = (entity: unknown): void => {\n if (!isRecord(entity)) return;\n const roles = stringArray(entity.roles);\n const fields = vcardFields(entity);\n const name = fields.get(\"fn\")?.[0] ?? fields.get(\"org\")?.[0];\n const handle = stringValue(entity.handle);\n const identity = name ?? handle;\n if (identity) {\n const publicIds = Array.isArray(entity.publicIds)\n ? entity.publicIds\n .map((value) => {\n if (!isRecord(value)) return undefined;\n const type = stringValue(value.type);\n const identifier = stringValue(value.identifier);\n return type && identifier ? `${type} ${identifier}` : undefined;\n })\n .filter((value): value is string => value !== undefined)\n : [];\n const details = [\n ...publicIds,\n ...(fields.get(\"email\") ?? []).map((value) => `email ${value}`),\n ...(fields.get(\"tel\") ?? []).map((value) => `telephone ${value}`),\n ];\n lines.push(\n `Entity${roles.length > 0 ? ` (${roles.join(\", \")})` : \"\"}: ${identity}${details.length > 0 ? `; ${details.join(\"; \")}` : \"\"}`,\n );\n }\n if (Array.isArray(entity.entities)) entity.entities.forEach(visit);\n };\n data.entities.forEach(visit);\n return [...new Set(lines)];\n}\n\nfunction noticeTitles(data: Record<string, unknown>): string[] {\n if (!Array.isArray(data.notices)) return [];\n return data.notices\n .map((notice) => (isRecord(notice) ? stringValue(notice.title) : undefined))\n .filter((title): title is string => title !== undefined);\n}\n\nfunction formatDomainRdap(\n responses: RdapResponse[],\n requestedDomain: string,\n warnings: string[],\n): string {\n const data: Record<string, unknown> = Object.assign(\n {},\n ...responses\n .slice()\n .reverse()\n .map((response) => response.data),\n );\n data.entities = responses.flatMap((response) =>\n Array.isArray(response.data.entities) ? response.data.entities : [],\n );\n data.notices = responses.flatMap((response) =>\n Array.isArray(response.data.notices) ? response.data.notices : [],\n );\n data.events = responses.flatMap((response) =>\n Array.isArray(response.data.events) ? response.data.events : [],\n );\n const lines = [\n \"Protocol: RDAP\",\n ...responses.map((response) => `Source: ${response.source}`),\n `Domain: ${stringValue(data.unicodeName) ?? stringValue(data.ldhName) ?? requestedDomain}`,\n ];\n const handle = stringValue(data.handle);\n if (handle) lines.push(`Registry ID: ${handle}`);\n lines.push(...eventLines(data));\n const statuses = stringArray(data.status);\n if (statuses.length > 0) lines.push(`Status: ${statuses.join(\", \")}`);\n\n if (Array.isArray(data.nameservers)) {\n const nameservers = data.nameservers\n .map((value) =>\n isRecord(value)\n ? (stringValue(value.unicodeName) ?? stringValue(value.ldhName))\n : undefined,\n )\n .filter((value): value is string => value !== undefined);\n if (nameservers.length > 0)\n lines.push(`Nameservers: ${nameservers.join(\", \")}`);\n }\n if (isRecord(data.secureDNS)) {\n const signed = data.secureDNS.delegationSigned;\n if (typeof signed === \"boolean\")\n lines.push(`DNSSEC: ${signed ? \"signed\" : \"unsigned\"}`);\n }\n lines.push(...entityLines(data));\n const notices = noticeTitles(data);\n if (notices.length > 0) lines.push(`Notices: ${notices.join(\"; \")}`);\n lines.push(...warnings.map((warning) => `Warning: ${warning}`));\n return lines.join(\"\\n\");\n}\n\nfunction formatIpRdap(response: RdapResponse, ip: string): string {\n const { data } = response;\n const lines = [\"Protocol: RDAP\", `Source: ${response.source}`, `IP: ${ip}`];\n for (const [label, key] of [\n [\"Network\", \"name\"],\n [\"Handle\", \"handle\"],\n [\"Start address\", \"startAddress\"],\n [\"End address\", \"endAddress\"],\n [\"IP version\", \"ipVersion\"],\n [\"Type\", \"type\"],\n [\"Country\", \"country\"],\n [\"Parent handle\", \"parentHandle\"],\n ] as const) {\n const value = stringValue(data[key]);\n if (value) lines.push(`${label}: ${value}`);\n }\n const statuses = stringArray(data.status);\n if (statuses.length > 0) lines.push(`Status: ${statuses.join(\", \")}`);\n lines.push(...eventLines(data), ...entityLines(data));\n const notices = noticeTitles(data);\n if (notices.length > 0) lines.push(`Notices: ${notices.join(\"; \")}`);\n return lines.join(\"\\n\");\n}\n\nexport function normaliseRegistrationDomain(domain: string): string {\n const candidate = domain.trim().replace(/\\.$/, \"\");\n const containsControlCharacter = [...candidate].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || codePoint === 0x7f;\n });\n if (!candidate || containsControlCharacter) {\n throw new Error(\"Invalid domain\");\n }\n const ascii = domainToASCII(candidate).toLowerCase();\n if (!ascii || ascii.length > 253) throw new Error(\"Invalid domain\");\n const labels = ascii.split(\".\");\n if (\n labels.some(\n (label) =>\n label.length === 0 ||\n label.length > 63 ||\n !/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label),\n )\n ) {\n throw new Error(\"Invalid domain\");\n }\n return ascii;\n}\n\nfunction parseWhoisEndpoint(\n value: string,\n allowWebScheme = false,\n): WhoisEndpoint {\n const candidate = value.includes(\"://\") ? value : `whois://${value}`;\n let url: URL;\n try {\n url = new URL(candidate);\n } catch {\n throw new RegistrationLookupError(\n `Invalid WHOIS referral: ${value}`,\n \"invalid-response\",\n undefined,\n \"REFERRAL_REJECTED\",\n );\n }\n const webScheme = url.protocol === \"http:\" || url.protocol === \"https:\";\n const port = webScheme ? 43 : url.port ? Number(url.port) : 43;\n if (\n (url.protocol !== \"whois:\" && !(allowWebScheme && webScheme)) ||\n !url.hostname ||\n url.username ||\n url.password ||\n (url.pathname && url.pathname !== \"/\") ||\n url.search ||\n url.hash ||\n (!webScheme && url.port && url.port !== \"43\")\n ) {\n throw new RegistrationLookupError(\n `Refusing unsafe WHOIS referral: ${value}`,\n \"security\",\n undefined,\n \"REFERRAL_REJECTED\",\n );\n }\n return { host: url.hostname.replace(/^\\[|\\]$/g, \"\").toLowerCase(), port };\n}\n\nfunction whoisReferral(response: string): WhoisEndpoint | undefined {\n for (const [pattern, allowWebScheme] of [\n [/^refer:[ \\t]*(\\S+)/im, false],\n [/^whois:[ \\t]*(\\S+)/im, false],\n [/^Registrar WHOIS Server:[ \\t]*(\\S+)/im, true],\n [/^ReferralServer:[ \\t]*(\\S+)/im, false],\n ] as const) {\n const match = response.match(pattern);\n if (match?.[1]) return parseWhoisEndpoint(match[1].trim(), allowWebScheme);\n }\n return undefined;\n}\n\nfunction inspectWhoisResponse(response: string): {\n notFound: boolean;\n warnings: RegistrationWarning[];\n} {\n const hasRegistrationData =\n /^(?:Domain Name|Domain|domain|NetRange|CIDR|inetnum|network|route):[ \\t]*\\S+/imu.test(\n response,\n );\n if (\n !hasRegistrationData &&\n /(?:rate limit|query limit|quota exceeded|too many quer(?:y|ies)|maximum number of quer(?:y|ies)|try again later)/iu.test(\n response,\n )\n ) {\n throw new RegistrationLookupError(\n \"WHOIS service rate limited the request\",\n \"rate-limited\",\n undefined,\n \"WHOIS_RATE_LIMITED\",\n );\n }\n if (\n !hasRegistrationData &&\n /(?:whois service (?:has been |is )?(?:retired|discontinued)|whois is no longer available)/iu.test(\n response,\n )\n ) {\n throw new RegistrationLookupError(\n \"WHOIS service reports that it has been retired\",\n \"unsupported\",\n undefined,\n \"WHOIS_SERVICE_RETIRED\",\n );\n }\n if (\n !hasRegistrationData &&\n /(?:web[- ]based whois|web whois|visit .{0,80}whois)/isu.test(response)\n ) {\n throw new RegistrationLookupError(\n \"Registry directs queries to a web-based WHOIS service\",\n \"unsupported\",\n undefined,\n \"WHOIS_WEB_ONLY\",\n );\n }\n if (\n !hasRegistrationData &&\n /(?:invalid query|malformed query|unsupported query|syntax error|^usage:)/imu.test(\n response,\n )\n ) {\n throw new RegistrationLookupError(\n \"WHOIS service rejected the query syntax\",\n \"invalid-response\",\n undefined,\n \"WHOIS_UNSUPPORTED_RESPONSE\",\n );\n }\n\n const warnings: RegistrationWarning[] = [];\n if (response.includes(\"\\uFFFD\")) {\n warnings.push({\n reason: \"WHOIS_INVALID_ENCODING\",\n detail: \"WHOIS response contains bytes that are not valid UTF-8\",\n });\n }\n return {\n notFound:\n !hasRegistrationData &&\n /(?:no match for|not found|no entries found|no object found)/iu.test(\n response,\n ),\n warnings,\n };\n}\n\nfunction whoisQueryValue(host: string, query: string): string {\n if (host === \"whois.jprs.jp\" && !query.endsWith(\"/e\")) return `${query}/e`;\n if (host === \"whois.denic.de\") return `-T dn,ace ${query}`;\n return query;\n}\n\nasync function whoisQuery(\n endpoint: WhoisEndpoint,\n query: string,\n): Promise<string> {\n const addresses = await resolvePublicHostname(endpoint.host, true);\n return await new Promise((resolve, reject) => {\n let settled = false;\n let total = 0;\n const chunks: Buffer[] = [];\n const timeoutError = (): RegistrationLookupError =>\n new RegistrationLookupError(\n \"WHOIS query timed out\",\n \"network\",\n undefined,\n \"WHOIS_TIMEOUT\",\n );\n const socket = net.createConnection(\n { ...endpoint, lookup: pinnedLookup(addresses) },\n () => {\n socket.write(`${whoisQueryValue(endpoint.host, query)}\\r\\n`);\n },\n );\n const deadline = setTimeout(\n () => socket.destroy(timeoutError()),\n REQUEST_TIMEOUT_MS,\n );\n const finish = (error?: Error): void => {\n if (settled) return;\n settled = true;\n clearTimeout(deadline);\n if (error) reject(error);\n else resolve(Buffer.concat(chunks).toString(\"utf-8\"));\n };\n socket.on(\"data\", (chunk: Buffer) => {\n total += chunk.byteLength;\n if (total > MAX_WHOIS_BYTES) {\n socket.destroy(\n new RegistrationLookupError(\n `WHOIS response exceeds ${MAX_WHOIS_BYTES} bytes`,\n \"invalid-response\",\n undefined,\n \"RESPONSE_TOO_LARGE\",\n ),\n );\n return;\n }\n chunks.push(chunk);\n });\n socket.on(\"end\", () => finish());\n socket.on(\"error\", (error) => finish(error));\n socket.setTimeout(REQUEST_TIMEOUT_MS, () => {\n socket.destroy(timeoutError());\n });\n });\n}\n\nasync function legacyWhois(query: string): Promise<string> {\n let endpoint = { host: \"whois.iana.org\", port: 43 };\n const visited = new Set<string>();\n let response = \"\";\n const warnings: RegistrationWarning[] = [];\n\n for (let index = 0; index < MAX_WHOIS_QUERIES; index += 1) {\n const key = `${endpoint.host}:${endpoint.port}`;\n if (visited.has(key)) {\n throw new RegistrationLookupError(\n \"WHOIS referral loop detected\",\n \"invalid-response\",\n `whois://${endpoint.host}:43`,\n \"REFERRAL_LOOP\",\n );\n }\n visited.add(key);\n try {\n response = (await whoisQuery(endpoint, query)).trim();\n } catch (error) {\n throw new RegistrationLookupError(\n errorMessage(error),\n error instanceof RegistrationLookupError ? error.kind : \"network\",\n `whois://${endpoint.host}:43`,\n reasonForError(\"WHOIS\", error),\n );\n }\n\n let referral: WhoisEndpoint | undefined;\n try {\n referral = whoisReferral(response);\n } catch (error) {\n if (index === 0) throw error;\n warnings.push({\n reason: reasonForError(\"WHOIS\", error),\n detail: errorMessage(error),\n });\n break;\n }\n if (!referral) {\n if (index === 0) {\n throw new RegistrationLookupError(\n \"IANA does not advertise a WHOIS service for this query\",\n \"unsupported\",\n \"whois://whois.iana.org:43\",\n \"WHOIS_NOT_ADVERTISED\",\n );\n }\n break;\n }\n const referralKey = `${referral.host}:${referral.port}`;\n if (visited.has(referralKey)) {\n if (referralKey === key) break;\n throw new RegistrationLookupError(\n \"WHOIS referral loop detected\",\n \"invalid-response\",\n `whois://${endpoint.host}:43`,\n \"REFERRAL_LOOP\",\n );\n }\n if (index === MAX_WHOIS_QUERIES - 1) {\n warnings.push({\n reason: \"REFERRAL_LIMIT_REACHED\",\n detail: `WHOIS referral limit of ${MAX_WHOIS_QUERIES} queries reached`,\n });\n break;\n }\n try {\n await resolvePublicHostname(referral.host, true);\n } catch (error) {\n if (index === 0) throw error;\n warnings.push({\n reason: reasonForError(\"WHOIS\", error),\n detail: errorMessage(error),\n });\n break;\n }\n endpoint = referral;\n }\n\n if (!response)\n throw new RegistrationLookupError(\n \"No WHOIS data returned\",\n \"network\",\n `whois://${endpoint.host}:43`,\n \"WHOIS_EMPTY_RESPONSE\",\n );\n let inspection: ReturnType<typeof inspectWhoisResponse>;\n try {\n inspection = inspectWhoisResponse(response);\n } catch (error) {\n throw new RegistrationLookupError(\n errorMessage(error),\n error instanceof RegistrationLookupError\n ? error.kind\n : \"invalid-response\",\n `whois://${endpoint.host}:43`,\n reasonForError(\"WHOIS\", error),\n );\n }\n warnings.push(...inspection.warnings);\n return [\n \"Protocol: WHOIS\",\n `Source: whois://${endpoint.host}:43`,\n ...(inspection.notFound\n ? [\"Status: not registered or not found\", \"Reason: WHOIS_NOT_FOUND\"]\n : []),\n ...warnings.map((warning) => `Warning: ${warningText(warning)}`),\n \"\",\n response,\n ].join(\"\\n\");\n}\n\nfunction fallbackWarning(error: unknown): string {\n return `${reasonForError(\"RDAP\", error)}: ${errorMessage(error)}; used WHOIS fallback`;\n}\n\nexport async function domainRegistrationLookupResult(\n domain: string,\n): Promise<RegistrationLookupResult> {\n const normalised = normaliseRegistrationDomain(domain);\n let rdapError: unknown;\n try {\n const bootstrap = await getBootstrap(RDAP_DNS_BOOTSTRAP);\n const urls = domainServiceUrls(bootstrap, normalised);\n if (urls.length > 0) {\n try {\n const registry = await queryFirstRdapService(\n urls,\n `domain/${encodeURIComponent(normalised)}`,\n );\n const responses = [registry];\n const warnings: string[] = [];\n const related = relatedRdapUrl(registry.data);\n if (related) {\n try {\n responses.push(await fetchJson(related, MAX_RDAP_BYTES));\n } catch (error) {\n warnings.push(\n `${reasonForError(\"RDAP\", error)}: registrar RDAP lookup failed: ${errorMessage(error)}`,\n );\n }\n }\n return {\n text: formatDomainRdap(responses, normalised, warnings),\n failed: false,\n };\n } catch (error) {\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"not-found\"\n ) {\n return {\n text: `Protocol: RDAP\\nSource: ${error.source ?? \"authoritative RDAP service\"}\\nDomain: ${normalised}\\nStatus: not registered or not found\\nReason: RDAP_NOT_FOUND`,\n failed: false,\n };\n }\n rdapError = error;\n }\n } else {\n rdapError = new RegistrationLookupError(\n \"IANA has no RDAP bootstrap service for this TLD\",\n \"unsupported\",\n );\n }\n } catch (error) {\n rdapError = error;\n }\n\n try {\n const result = await legacyWhois(normalised);\n return {\n text: rdapError\n ? `${result}\\n\\nWarning: ${fallbackWarning(rdapError)}`\n : result,\n failed: false,\n };\n } catch (whoisError) {\n if (rdapError) {\n return {\n text: formatLookupFailure(\"Domain\", normalised, rdapError, whoisError),\n failed: true,\n };\n }\n return {\n text: formatLookupFailure(\n \"Domain\",\n normalised,\n new RegistrationLookupError(\n \"RDAP was not attempted\",\n \"unsupported\",\n undefined,\n \"RDAP_NOT_AVAILABLE\",\n ),\n whoisError,\n ),\n failed: true,\n };\n }\n}\n\nexport async function domainRegistrationLookup(\n domain: string,\n): Promise<string> {\n return (await domainRegistrationLookupResult(domain)).text;\n}\n\nexport async function ipRegistrationLookupResult(\n ip: string,\n): Promise<RegistrationLookupResult> {\n const family = net.isIP(ip);\n if (family === 0) throw new Error(\"Invalid IP address\");\n let rdapError: unknown;\n try {\n const bootstrap = await getBootstrap(\n family === 4 ? RDAP_IPV4_BOOTSTRAP : RDAP_IPV6_BOOTSTRAP,\n );\n const urls = ipServiceUrls(bootstrap, ip);\n if (urls.length > 0) {\n try {\n const response = await queryFirstRdapService(\n urls,\n `ip/${encodeURIComponent(ip)}`,\n );\n return { text: formatIpRdap(response, ip), failed: false };\n } catch (error) {\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"not-found\"\n ) {\n return {\n text: `Protocol: RDAP\\nSource: ${error.source ?? \"authoritative RDAP service\"}\\nIP: ${ip}\\nStatus: registration data not found\\nReason: RDAP_NOT_FOUND`,\n failed: false,\n };\n }\n rdapError = error;\n }\n } else {\n rdapError = new RegistrationLookupError(\n \"IANA has no RDAP bootstrap service for this address\",\n \"unsupported\",\n );\n }\n } catch (error) {\n rdapError = error;\n }\n\n try {\n const result = await legacyWhois(ip);\n return {\n text: rdapError\n ? `${result}\\n\\nWarning: ${fallbackWarning(rdapError)}`\n : result,\n failed: false,\n };\n } catch (whoisError) {\n if (rdapError) {\n return {\n text: formatLookupFailure(\"IP\", ip, rdapError, whoisError),\n failed: true,\n };\n }\n return {\n text: formatLookupFailure(\n \"IP\",\n ip,\n new RegistrationLookupError(\n \"RDAP was not attempted\",\n \"unsupported\",\n undefined,\n \"RDAP_NOT_AVAILABLE\",\n ),\n whoisError,\n ),\n failed: true,\n };\n }\n}\n\nexport async function ipRegistrationLookup(ip: string): Promise<string> {\n return (await ipRegistrationLookupResult(ip)).text;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport {\n dnsLookup,\n reverseDns,\n resolveAll,\n checkNameservers,\n whoisLookupResult,\n ipWhoisResult,\n} from \"./dns.js\";\n\nconst recordTypeSchema = z\n .enum([\"A\", \"AAAA\", \"MX\", \"TXT\", \"CNAME\", \"NS\", \"SOA\", \"SRV\", \"CAA\", \"PTR\"])\n .default(\"A\");\n\nconst readOnlyAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n};\n\nexport function createMcpServer(): McpServer {\n const server = new McpServer(\n {\n name: \"mcp-dns-tools\",\n version: packageJson.version,\n },\n {\n instructions:\n \"When the user names one DNS record type, call dns_lookup and pass that type, except for NS or nameserver-only requests, which must use check_nameservers. For CAA requests, call dns_lookup with type CAA. Use resolve_all only when the user asks for all records, multiple record types, a DNS overview, or a general investigation. Never use resolve_all for one named record type. Use whois for domain registration, registrar, registration status, or registration-date questions. Use ip_whois for IP allocation and network ownership questions.\",\n },\n );\n\n server.registerTool(\n \"dns_lookup\",\n {\n title: \"DNS record lookup\",\n description:\n \"Use this when the user requests one specific DNS record type, except for NS or nameserver requests, which must use check_nameservers. For CAA or certificate authority issuance questions, call this tool with type CAA. Supports A, AAAA, MX, TXT, CNAME, SOA, SRV, CAA, PTR, and NS for backwards compatibility. Do not use resolve_all when the user names one record type.\",\n inputSchema: {\n domain: z\n .string()\n .describe(\"Domain name to look up (e.g. example.com)\"),\n type: recordTypeSchema.describe(\n \"Specific record type to return: A, AAAA, MX, TXT, CNAME, NS, SOA, SRV, CAA, or PTR. Use CAA for certificate authority issuance policy.\",\n ),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain, type }) => {\n const result = await dnsLookup(domain, type);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"reverse_dns\",\n {\n title: \"Reverse DNS lookup\",\n description: \"Perform a reverse DNS (PTR) lookup on an IP address.\",\n inputSchema: {\n ip: z.string().describe(\"IP address (e.g. 8.8.8.8)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ ip }) => {\n const result = await reverseDns(ip);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"resolve_all\",\n {\n title: \"DNS overview\",\n description:\n \"Use this only when the user requests all common DNS records, multiple record types, a DNS overview, or a general domain investigation. Returns A, AAAA, MX, TXT, CAA, NS, and CNAME. Do not use this for one named record type.\",\n inputSchema: {\n domain: z\n .string()\n .describe(\"Domain name to resolve (e.g. example.com)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain }) => {\n const result = await resolveAll(domain);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"check_nameservers\",\n {\n title: \"Nameserver lookup\",\n description:\n \"Use this whenever the user requests NS records, nameservers, authoritative nameservers, or domain delegation nameservers.\",\n inputSchema: {\n domain: z.string().describe(\"Domain name (e.g. example.com)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain }) => {\n const result = await checkNameservers(domain);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"whois\",\n {\n title: \"Domain registration lookup\",\n description:\n \"Query authoritative domain registration data, including registrar, status, dates, nameservers, and DNSSEC. Uses IANA RDAP discovery over HTTPS and follows a registrar RDAP link when available, with bounded legacy WHOIS fallback for TLDs without working RDAP. Supports Unicode domain names. Failures identify each attempted protocol, endpoint, stable reason code, detail, and suggested next action.\",\n inputSchema: {\n domain: z\n .string()\n .describe(\"Domain name for registration lookup (e.g. example.com)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain }) => {\n const result = await whoisLookupResult(domain);\n return {\n content: [{ type: \"text\" as const, text: result.text }],\n isError: result.failed,\n };\n },\n );\n\n server.registerTool(\n \"ip_whois\",\n {\n title: \"IP registration lookup\",\n description:\n \"Query authoritative IPv4 or IPv6 allocation and network ownership data. Uses IANA RDAP bootstrap discovery over HTTPS, with bounded legacy WHOIS fallback to the appropriate Regional Internet Registry. Failures identify each attempted protocol, endpoint, stable reason code, detail, and suggested next action.\",\n inputSchema: {\n ip: z\n .string()\n .describe(\"IP address (e.g. 8.8.8.8 or 2001:4860:4860::8888)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ ip }) => {\n const result = await ipWhoisResult(ip);\n return {\n content: [{ type: \"text\" as const, text: result.text }],\n isError: result.failed,\n };\n },\n );\n\n return server;\n}\n","{\n \"name\": \"@paulgit/mcp-dns-tools\",\n \"mcpName\": \"it.paulg/dns-tools\",\n \"version\": \"2.2.0\",\n \"description\": \"MCP server for DNS lookups, including CAA checks, reverse DNS, and RDAP-first domain or IP registration data with WHOIS fallback; zero auth, zero config\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24\"\n },\n \"bin\": {\n \"mcp-dns-tools\": \"./dist/index.js\"\n },\n \"files\": [\n \"dist\",\n \"skills\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"eslint . && prettier --check .\",\n \"format\": \"prettier --write .\",\n \"audit:deps\": \"npm audit --omit=dev --audit-level=high\",\n \"prepack\": \"npm run build\",\n \"prepublishOnly\": \"npm run lint && npm run typecheck && npm test\",\n \"prepare\": \"husky\"\n },\n \"keywords\": [\n \"mcp\",\n \"mcp-server\",\n \"model-context-protocol\",\n \"dns\",\n \"whois\",\n \"domain\",\n \"network\",\n \"lookup\",\n \"nameserver\",\n \"caa\",\n \"tls\",\n \"certificate-authority\",\n \"ai\",\n \"llm\",\n \"claude\",\n \"cursor\"\n ],\n \"author\": \"Paul Git (https://code.paulg.it/paulgit)\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://code.paulg.it/paulgit/mcp-dns-tools.git\"\n },\n \"bugs\": {\n \"url\": \"https://code.paulg.it/paulgit/mcp-dns-tools/issues\"\n },\n \"homepage\": \"https://code.paulg.it/paulgit/mcp-dns-tools#readme\",\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.26.0\",\n \"undici\": \"^8.10.0\",\n \"zod\": \"^3.25.0\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.0.0\",\n \"@types/node\": \"^22.0.0\",\n \"eslint\": \"^9.0.0\",\n \"eslint-config-prettier\": \"^10.0.0\",\n \"husky\": \"^9.0.0\",\n \"lint-staged\": \"^15.0.0\",\n \"prettier\": \"^3.0.0\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.7.0\",\n \"typescript-eslint\": \"^8.0.0\",\n \"vitest\": \"^3.2.0\"\n },\n \"lint-staged\": {\n \"*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"*.{json,md,yml,yaml}\": [\n \"prettier --write\"\n ]\n }\n}\n"],"mappings":"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","names":["dns","net","net","dns"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli.ts","../src/dns.ts","../src/registration.ts","../src/server.ts","../package.json"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { parseCliArgs } from \"./cli.js\";\nimport { configureDnsServers } from \"./dns.js\";\nimport { createMcpServer } from \"./server.js\";\n\nconfigureDnsServers();\n\nasync function main() {\n parseCliArgs(process.argv.slice(2));\n const server = createMcpServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n});\n","import { parseArgs } from \"node:util\";\n\nexport interface CliOptions {\n transport: \"stdio\";\n}\n\nexport function parseCliArgs(args: string[]): CliOptions {\n const { values } = parseArgs({\n args,\n options: {\n transport: {\n type: \"string\",\n default: \"stdio\",\n },\n },\n strict: true,\n });\n\n if (values.transport !== \"stdio\") {\n throw new Error(\n `Unsupported transport: ${values.transport}. Only stdio is supported.`,\n );\n }\n\n return { transport: \"stdio\" };\n}\n","import dns from \"node:dns/promises\";\nimport { setServers } from \"node:dns\";\nimport type { CaaRecord } from \"node:dns\";\nimport net from \"node:net\";\nimport type { RegistrationLookupResult } from \"./registration.js\";\nimport {\n domainRegistrationLookup,\n domainRegistrationLookupResult,\n ipRegistrationLookup,\n ipRegistrationLookupResult,\n} from \"./registration.js\";\n\nexport type { RegistrationLookupResult };\n\nexport type RecordType =\n | \"A\"\n | \"AAAA\"\n | \"MX\"\n | \"TXT\"\n | \"CNAME\"\n | \"NS\"\n | \"SOA\"\n | \"SRV\"\n | \"CAA\"\n | \"PTR\";\n\ninterface MxRecord {\n exchange: string;\n priority: number;\n}\n\ninterface SoaRecord {\n nsname: string;\n hostmaster: string;\n serial: number;\n refresh: number;\n retry: number;\n expire: number;\n minttl: number;\n}\n\ninterface SrvRecord {\n priority: number;\n weight: number;\n port: number;\n name: string;\n}\n\nexport function configureDnsServers(env = process.env): void {\n const raw = env.DNS_SERVERS;\n if (!raw) return;\n const servers = raw\n .split(\",\")\n .map((s) => s.trim())\n .filter((s) => net.isIP(s) !== 0);\n if (servers.length > 0) {\n setServers(servers);\n }\n}\n\nfunction mapDnsError(error: unknown, type: string, target: string): string {\n const code = (error as NodeJS.ErrnoException).code;\n switch (code) {\n case \"ENODATA\":\n return `No ${type} records found for ${target}.`;\n case \"ENOTFOUND\":\n return `Domain not found: ${target}`;\n case \"EREFUSED\":\n return `DNS server refused the ${type} query for ${target}. The local resolver may not support this record type; set DNS_SERVERS to use a different resolver.`;\n case \"ETIMEOUT\":\n return `DNS query for ${target} (${type}) timed out.`;\n default:\n return `DNS lookup failed for ${target} (${type}): ${code ?? \"unknown error\"}`;\n }\n}\n\nconst DOMAIN_RE =\n /^(?=.{1,253}$)[a-zA-Z0-9_]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?(\\.[a-zA-Z0-9_]([a-zA-Z0-9_-]{0,61}[a-zA-Z0-9])?)*\\.?$/;\n\nfunction assertValidDomain(domain: string): void {\n if (!DOMAIN_RE.test(domain)) {\n throw new Error(\"Invalid domain\");\n }\n}\n\nexport async function dnsLookup(\n domain: string,\n type: RecordType,\n): Promise<string> {\n assertValidDomain(domain);\n let records: unknown;\n try {\n records = await dns.resolve(domain, type);\n } catch (error) {\n return mapDnsError(error, type, domain);\n }\n\n switch (type) {\n case \"MX\": {\n const mx = records as MxRecord[];\n if (mx.length === 0) return \"No MX records found.\";\n return mx\n .sort((a, b) => a.priority - b.priority)\n .map((r) => `${r.priority} ${r.exchange}`)\n .join(\"\\n\");\n }\n case \"TXT\": {\n const txt = records as string[][];\n if (txt.length === 0) return \"No TXT records found.\";\n return txt.map((entries) => entries.join(\"\")).join(\"\\n\");\n }\n case \"CAA\": {\n const caa = records as CaaRecord[];\n if (caa.length === 0) return \"No CAA records found.\";\n const formatted = caa.flatMap(({ critical, ...tags }) =>\n Object.entries(tags)\n .filter(\n (entry): entry is [string, string] =>\n entry[0] !== \"type\" && typeof entry[1] === \"string\",\n )\n .map(([tag, value]) => `${critical} ${tag} ${JSON.stringify(value)}`),\n );\n return formatted.length > 0\n ? formatted.join(\"\\n\")\n : \"No CAA records found.\";\n }\n case \"SOA\": {\n const soa = records as SoaRecord[];\n const s = soa[0];\n if (!s) return \"No SOA record found.\";\n return [\n `nsname: ${s.nsname}`,\n `hostmaster: ${s.hostmaster}`,\n `serial: ${s.serial}`,\n `refresh: ${s.refresh}`,\n `retry: ${s.retry}`,\n `expire: ${s.expire}`,\n `minttl: ${s.minttl}`,\n ].join(\"\\n\");\n }\n case \"SRV\": {\n const srv = records as SrvRecord[];\n if (srv.length === 0) return \"No SRV records found.\";\n return srv\n .map((r) => `${r.priority} ${r.weight} ${r.port} ${r.name}`)\n .join(\"\\n\");\n }\n default: {\n const arr = records as string[];\n if (arr.length === 0) return `No ${type} records found.`;\n return arr.join(\"\\n\");\n }\n }\n}\n\nexport async function reverseDns(ip: string): Promise<string> {\n if (net.isIP(ip) === 0) {\n throw new Error(\"Invalid IP address\");\n }\n let hostnames: string[];\n try {\n hostnames = await dns.reverse(ip);\n } catch (error) {\n return mapDnsError(error, \"PTR\", ip);\n }\n return hostnames.length > 0 ? hostnames.join(\"\\n\") : \"No PTR records found.\";\n}\n\nexport async function resolveAll(domain: string): Promise<string> {\n assertValidDomain(domain);\n const types: { name: string; type: RecordType }[] = [\n { name: \"A\", type: \"A\" },\n { name: \"AAAA\", type: \"AAAA\" },\n { name: \"MX\", type: \"MX\" },\n { name: \"TXT\", type: \"TXT\" },\n { name: \"CAA\", type: \"CAA\" },\n { name: \"NS\", type: \"NS\" },\n { name: \"CNAME\", type: \"CNAME\" },\n ];\n\n const results: string[] = [];\n for (const { name, type } of types) {\n try {\n const records = await dnsLookup(domain, type);\n results.push(`=== ${name} ===\\n${records}`);\n } catch {\n results.push(`=== ${name} ===\\n(no records or error)`);\n }\n }\n return results.join(\"\\n\\n\");\n}\n\nexport async function checkNameservers(domain: string): Promise<string> {\n assertValidDomain(domain);\n let nameservers: string[];\n try {\n nameservers = await dns.resolveNs(domain);\n } catch (error) {\n return mapDnsError(error, \"NS\", domain);\n }\n return nameservers.length > 0\n ? nameservers.join(\"\\n\")\n : \"No nameserver records found.\";\n}\n\nexport async function whoisLookup(domain: string): Promise<string> {\n return await domainRegistrationLookup(domain);\n}\n\nexport async function whoisLookupResult(\n domain: string,\n): Promise<RegistrationLookupResult> {\n return await domainRegistrationLookupResult(domain);\n}\n\nexport async function ipWhois(ip: string): Promise<string> {\n return await ipRegistrationLookup(ip);\n}\n\nexport async function ipWhoisResult(\n ip: string,\n): Promise<RegistrationLookupResult> {\n return await ipRegistrationLookupResult(ip);\n}\n","import dns from \"node:dns/promises\";\nimport net from \"node:net\";\nimport { domainToASCII } from \"node:url\";\nimport { Agent, fetch as undiciFetch } from \"undici\";\n\nconst RDAP_DNS_BOOTSTRAP = \"https://data.iana.org/rdap/dns.json\";\nconst RDAP_IPV4_BOOTSTRAP = \"https://data.iana.org/rdap/ipv4.json\";\nconst RDAP_IPV6_BOOTSTRAP = \"https://data.iana.org/rdap/ipv6.json\";\nconst BOOTSTRAP_TTL_MS = 24 * 60 * 60 * 1000;\nconst REQUEST_TIMEOUT_MS = 10_000;\nconst MAX_REDIRECTS = 3;\nconst MAX_RDAP_BYTES = 1024 * 1024;\nconst MAX_BOOTSTRAP_BYTES = 2 * 1024 * 1024;\nconst MAX_WHOIS_BYTES = 1024 * 1024;\nconst MAX_WHOIS_QUERIES = 3;\n\ninterface BootstrapData {\n services: unknown[];\n}\n\ninterface BootstrapCacheEntry {\n data: BootstrapData;\n expiresAt: number;\n}\n\ninterface RdapResponse {\n data: Record<string, unknown>;\n source: string;\n}\n\ninterface WhoisEndpoint {\n host: string;\n port: number;\n}\n\ninterface ResolvedAddress {\n address: string;\n family: 4 | 6;\n}\n\nexport interface RegistrationLookupResult {\n text: string;\n failed: boolean;\n}\n\nexport type RegistrationReason =\n | \"RDAP_NOT_AVAILABLE\"\n | \"RDAP_NOT_FOUND\"\n | \"RDAP_RATE_LIMITED\"\n | \"RDAP_TIMEOUT\"\n | \"RDAP_NETWORK_ERROR\"\n | \"RDAP_HTTP_ERROR\"\n | \"RDAP_INVALID_RESPONSE\"\n | \"RDAP_DESTINATION_REJECTED\"\n | \"WHOIS_NOT_ADVERTISED\"\n | \"WHOIS_NOT_FOUND\"\n | \"WHOIS_CONNECTION_REFUSED\"\n | \"WHOIS_CONNECTION_RESET\"\n | \"WHOIS_TIMEOUT\"\n | \"WHOIS_DNS_FAILURE\"\n | \"WHOIS_EMPTY_RESPONSE\"\n | \"WHOIS_RATE_LIMITED\"\n | \"WHOIS_SERVICE_RETIRED\"\n | \"WHOIS_WEB_ONLY\"\n | \"WHOIS_UNSUPPORTED_RESPONSE\"\n | \"WHOIS_INVALID_ENCODING\"\n | \"REFERRAL_REJECTED\"\n | \"REFERRAL_LOOP\"\n | \"REFERRAL_LIMIT_REACHED\"\n | \"RESPONSE_TOO_LARGE\"\n | \"UNKNOWN_ERROR\";\n\ninterface RegistrationWarning {\n reason: RegistrationReason;\n detail: string;\n}\n\nclass RegistrationLookupError extends Error {\n constructor(\n message: string,\n readonly kind:\n | \"invalid-response\"\n | \"network\"\n | \"not-found\"\n | \"rate-limited\"\n | \"security\"\n | \"unsupported\",\n readonly source?: string,\n readonly reason?: RegistrationReason,\n ) {\n super(message);\n this.name = \"RegistrationLookupError\";\n }\n}\n\nfunction ensureRegistrationErrorSource(\n error: unknown,\n source: string,\n): unknown {\n if (!(error instanceof RegistrationLookupError) || error.source !== undefined)\n return error;\n return new RegistrationLookupError(\n error.message,\n error.kind,\n source,\n error.reason,\n );\n}\n\nconst bootstrapCache = new Map<string, BootstrapCacheEntry>();\n\nconst blockedAddresses = new net.BlockList();\nconst syntheticHttpsProxyAddresses = new net.BlockList();\n// Some sandboxed network transports map public hosts into this benchmarking range.\nsyntheticHttpsProxyAddresses.addSubnet(\"198.18.0.0\", 15, \"ipv4\");\nfor (const [address, prefix] of [\n [\"0.0.0.0\", 8],\n [\"10.0.0.0\", 8],\n [\"100.64.0.0\", 10],\n [\"127.0.0.0\", 8],\n [\"169.254.0.0\", 16],\n [\"172.16.0.0\", 12],\n [\"192.0.0.0\", 24],\n [\"192.0.2.0\", 24],\n [\"192.168.0.0\", 16],\n [\"198.18.0.0\", 15],\n [\"198.51.100.0\", 24],\n [\"203.0.113.0\", 24],\n [\"224.0.0.0\", 4],\n [\"240.0.0.0\", 4],\n] as const) {\n blockedAddresses.addSubnet(address, prefix, \"ipv4\");\n}\nfor (const [address, prefix] of [\n [\"::\", 128],\n [\"::1\", 128],\n [\"64:ff9b:1::\", 48],\n [\"100::\", 64],\n [\"2001:db8::\", 32],\n [\"fc00::\", 7],\n [\"fe80::\", 10],\n [\"fec0::\", 10],\n [\"ff00::\", 8],\n] as const) {\n blockedAddresses.addSubnet(address, prefix, \"ipv6\");\n}\n\nexport function resetRegistrationCaches(): void {\n bootstrapCache.clear();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stringValue(value: unknown): string | undefined {\n if (typeof value === \"string\" && value.trim()) return value.trim();\n if (Array.isArray(value)) {\n const values = value\n .map((entry) => stringValue(entry))\n .filter((entry): entry is string => entry !== undefined);\n return values.length > 0 ? values.join(\", \") : undefined;\n }\n return undefined;\n}\n\nfunction stringArray(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return value.filter(\n (entry): entry is string => typeof entry === \"string\" && entry.length > 0,\n );\n}\n\nfunction isBlockedAddress(address: string): boolean {\n const family = net.isIP(address);\n if (family === 4) return blockedAddresses.check(address, \"ipv4\");\n if (family === 6) return blockedAddresses.check(address, \"ipv6\");\n return true;\n}\n\nasync function resolvePublicHostname(\n hostname: string,\n allowSyntheticNetworkProxy = false,\n): Promise<ResolvedAddress[]> {\n const normalised = hostname\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\")\n .toLowerCase();\n if (\n !normalised ||\n normalised === \"localhost\" ||\n normalised.endsWith(\".local\")\n ) {\n throw new RegistrationLookupError(\n `Refusing registration-data connection to ${hostname}`,\n \"security\",\n );\n }\n\n if (net.isIP(normalised) !== 0) {\n if (isBlockedAddress(normalised)) {\n throw new RegistrationLookupError(\n `Refusing registration-data connection to non-public address ${hostname}`,\n \"security\",\n );\n }\n return [\n {\n address: normalised,\n family: net.isIP(normalised) as 4 | 6,\n },\n ];\n }\n\n let addresses: { address: string; family: number }[];\n try {\n addresses = await dns.lookup(normalised, {\n all: true,\n verbatim: true,\n });\n } catch (error) {\n throw new RegistrationLookupError(\n `Unable to resolve registration-data service ${hostname}: ${errorMessage(error)}`,\n \"network\",\n );\n }\n\n const resolved = addresses.filter(\n (entry): entry is ResolvedAddress =>\n entry.family === 4 || entry.family === 6,\n );\n if (\n resolved.length === 0 ||\n resolved.some(\n (entry) =>\n isBlockedAddress(entry.address) &&\n !(\n allowSyntheticNetworkProxy &&\n entry.family === 4 &&\n syntheticHttpsProxyAddresses.check(entry.address, \"ipv4\")\n ),\n )\n ) {\n throw new RegistrationLookupError(\n `Refusing registration-data connection to ${hostname}: destination is not public`,\n \"security\",\n );\n }\n return resolved;\n}\n\nfunction pinnedLookup(addresses: ResolvedAddress[]): net.LookupFunction {\n return (_hostname, options, callback): void => {\n const requestedFamily = options.family ?? 0;\n const candidates = addresses.filter(\n (entry) => requestedFamily === 0 || entry.family === requestedFamily,\n );\n if (candidates.length === 0) {\n const error = new Error(\n `No validated address for requested family ${requestedFamily}`,\n ) as NodeJS.ErrnoException;\n error.code = \"EAI_ADDRFAMILY\";\n callback(error, \"\");\n return;\n }\n if (options.all) {\n callback(null, candidates);\n return;\n }\n const [selected] = candidates;\n if (!selected) {\n callback(new Error(\"No validated address available\"), \"\");\n return;\n }\n callback(null, selected.address, selected.family);\n };\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : \"unknown error\";\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return error instanceof Error\n ? (error as NodeJS.ErrnoException).code\n : undefined;\n}\n\nfunction reasonForError(\n protocol: \"RDAP\" | \"WHOIS\",\n error: unknown,\n): RegistrationReason {\n if (error instanceof RegistrationLookupError && error.reason)\n return error.reason;\n\n const message = errorMessage(error).toLowerCase();\n const code = errorCode(error);\n if (message.includes(\"exceeds\") && message.includes(\"bytes\"))\n return \"RESPONSE_TOO_LARGE\";\n if (message.includes(\"referral loop\")) return \"REFERRAL_LOOP\";\n if (message.includes(\"referral limit\")) return \"REFERRAL_LIMIT_REACHED\";\n\n if (protocol === \"RDAP\") {\n if (error instanceof RegistrationLookupError && error.kind === \"not-found\")\n return \"RDAP_NOT_FOUND\";\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"rate-limited\"\n )\n return \"RDAP_RATE_LIMITED\";\n if (message.includes(\"timed out\") || code === \"ETIMEDOUT\")\n return \"RDAP_TIMEOUT\";\n if (message.includes(\"http \")) return \"RDAP_HTTP_ERROR\";\n if (error instanceof RegistrationLookupError && error.kind === \"security\")\n return \"RDAP_DESTINATION_REJECTED\";\n if (\n error instanceof RegistrationLookupError &&\n (error.kind === \"invalid-response\" || error.kind === \"unsupported\")\n )\n return error.kind === \"unsupported\"\n ? \"RDAP_NOT_AVAILABLE\"\n : \"RDAP_INVALID_RESPONSE\";\n return \"RDAP_NETWORK_ERROR\";\n }\n\n if (code === \"ECONNREFUSED\") return \"WHOIS_CONNECTION_REFUSED\";\n if (code === \"ECONNRESET\") return \"WHOIS_CONNECTION_RESET\";\n if (code === \"ENOTFOUND\" || code === \"EAI_AGAIN\") return \"WHOIS_DNS_FAILURE\";\n if (message.includes(\"unable to resolve registration-data service\"))\n return \"WHOIS_DNS_FAILURE\";\n if (message.includes(\"timed out\") || code === \"ETIMEDOUT\")\n return \"WHOIS_TIMEOUT\";\n if (message.includes(\"no whois data\")) return \"WHOIS_EMPTY_RESPONSE\";\n if (error instanceof RegistrationLookupError && error.kind === \"unsupported\")\n return \"WHOIS_NOT_ADVERTISED\";\n if (error instanceof RegistrationLookupError && error.kind === \"rate-limited\")\n return \"WHOIS_RATE_LIMITED\";\n if (error instanceof RegistrationLookupError && error.kind === \"security\")\n return \"REFERRAL_REJECTED\";\n return \"UNKNOWN_ERROR\";\n}\n\nfunction warningText(warning: RegistrationWarning): string {\n return `${warning.reason}: ${warning.detail}`;\n}\n\nfunction failureSuggestion(\n rdapReason: RegistrationReason,\n whoisReason: RegistrationReason,\n): string {\n if (whoisReason === \"WHOIS_WEB_ONLY\")\n return \"Use the registry's web-based registration lookup service.\";\n if (\n rdapReason === \"RDAP_RATE_LIMITED\" ||\n whoisReason === \"WHOIS_RATE_LIMITED\"\n )\n return \"Retry later and reduce lookup frequency.\";\n if (whoisReason === \"WHOIS_SERVICE_RETIRED\")\n return \"Use the registry's RDAP or web-based replacement service.\";\n if (\n whoisReason === \"WHOIS_CONNECTION_REFUSED\" ||\n whoisReason === \"WHOIS_CONNECTION_RESET\" ||\n whoisReason === \"WHOIS_TIMEOUT\" ||\n whoisReason === \"WHOIS_DNS_FAILURE\"\n )\n return \"Check outbound HTTPS and TCP port 43 access, then retry.\";\n if (\n whoisReason === \"WHOIS_NOT_ADVERTISED\" ||\n whoisReason === \"WHOIS_UNSUPPORTED_RESPONSE\"\n )\n return \"Consult the TLD registry website for its supported lookup service.\";\n if (whoisReason === \"REFERRAL_REJECTED\" || whoisReason === \"REFERRAL_LOOP\")\n return \"Use the last authoritative source shown or consult the registry website.\";\n return \"Retry later or consult the registry's registration-data service.\";\n}\n\nfunction formatLookupFailure(\n queryType: \"Domain\" | \"IP\",\n query: string,\n rdapError: unknown,\n whoisError: unknown,\n): string {\n const rdapReason = reasonForError(\"RDAP\", rdapError);\n const whoisReason = reasonForError(\"WHOIS\", whoisError);\n const rdapSource =\n rdapError instanceof RegistrationLookupError ? rdapError.source : undefined;\n const whoisSource =\n whoisError instanceof RegistrationLookupError\n ? whoisError.source\n : undefined;\n return [\n \"Status: failed\",\n `${queryType}: ${query}`,\n \"RDAP status: failed\",\n `RDAP reason: ${rdapReason}`,\n ...(rdapSource ? [`RDAP source: ${rdapSource}`] : []),\n `RDAP detail: ${errorMessage(rdapError)}`,\n \"WHOIS status: failed\",\n `WHOIS reason: ${whoisReason}`,\n ...(whoisSource ? [`WHOIS source: ${whoisSource}`] : []),\n `WHOIS detail: ${errorMessage(whoisError)}`,\n `Suggestion: ${failureSuggestion(rdapReason, whoisReason)}`,\n ].join(\"\\n\");\n}\n\nasync function readResponseBody(\n response: Response,\n maximumBytes: number,\n): Promise<string> {\n const contentLength = response.headers.get(\"content-length\");\n if (contentLength && Number(contentLength) > maximumBytes) {\n await response.body?.cancel();\n throw new RegistrationLookupError(\n `Registration-data response exceeds ${maximumBytes} bytes`,\n \"invalid-response\",\n );\n }\n\n if (!response.body) return \"\";\n const reader = response.body.getReader();\n const chunks: Uint8Array[] = [];\n let total = 0;\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n total += value.byteLength;\n if (total > maximumBytes) {\n try {\n await reader.cancel();\n } catch {\n // The size-limit error below is more useful than a cancellation error.\n }\n throw new RegistrationLookupError(\n `Registration-data response exceeds ${maximumBytes} bytes`,\n \"invalid-response\",\n );\n }\n chunks.push(value);\n }\n\n const body = new Uint8Array(total);\n let offset = 0;\n for (const chunk of chunks) {\n body.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return new TextDecoder().decode(body);\n}\n\nfunction validateHttpsUrl(value: string): URL {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new RegistrationLookupError(\n `Invalid RDAP service URL: ${value}`,\n \"invalid-response\",\n );\n }\n if (\n url.protocol !== \"https:\" ||\n url.username ||\n url.password ||\n (url.port && url.port !== \"443\")\n ) {\n throw new RegistrationLookupError(\n `Refusing non-standard RDAP service URL: ${value}`,\n \"security\",\n );\n }\n return url;\n}\n\nasync function fetchJson(\n initialUrl: string,\n maximumBytes: number,\n): Promise<{ data: Record<string, unknown>; source: string }> {\n let url = validateHttpsUrl(initialUrl);\n\n for (let redirects = 0; redirects <= MAX_REDIRECTS; redirects += 1) {\n let addresses: ResolvedAddress[];\n try {\n addresses = await resolvePublicHostname(url.hostname, true);\n } catch (error) {\n throw ensureRegistrationErrorSource(error, url.href);\n }\n const dispatcher = new Agent({\n connect: { lookup: pinnedLookup(addresses) },\n });\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n try {\n const response = (await undiciFetch(url, {\n headers: {\n accept: \"application/rdap+json, application/json\",\n \"user-agent\": \"mcp-dns-tools/registration-lookup\",\n },\n dispatcher,\n redirect: \"manual\",\n signal: controller.signal,\n })) as unknown as Response;\n\n if ([301, 302, 303, 307, 308].includes(response.status)) {\n const location = response.headers.get(\"location\");\n if (!location) {\n throw new RegistrationLookupError(\n `RDAP redirect from ${url.hostname} has no location`,\n \"invalid-response\",\n );\n }\n if (redirects === MAX_REDIRECTS) {\n throw new RegistrationLookupError(\n \"RDAP redirect limit exceeded\",\n \"invalid-response\",\n );\n }\n await response.body?.cancel();\n url = validateHttpsUrl(new URL(location, url).href);\n continue;\n }\n\n const body = await readResponseBody(response, maximumBytes);\n if (response.status === 404) {\n throw new RegistrationLookupError(\n \"Registration data not found\",\n \"not-found\",\n url.href,\n );\n }\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"retry-after\");\n throw new RegistrationLookupError(\n `RDAP service rate limited the request${retryAfter ? `; retry after ${retryAfter}` : \"\"}`,\n \"rate-limited\",\n );\n }\n if (!response.ok) {\n throw new RegistrationLookupError(\n `RDAP service returned HTTP ${response.status}`,\n \"network\",\n );\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(body);\n } catch {\n throw new RegistrationLookupError(\n `RDAP service ${url.hostname} returned invalid JSON`,\n \"invalid-response\",\n );\n }\n if (!isRecord(parsed)) {\n throw new RegistrationLookupError(\n `RDAP service ${url.hostname} returned an invalid object`,\n \"invalid-response\",\n );\n }\n return { data: parsed, source: url.href };\n } catch (error) {\n if (controller.signal.aborted) {\n throw new RegistrationLookupError(\n `Request to ${url.hostname} timed out`,\n \"network\",\n url.href,\n \"RDAP_TIMEOUT\",\n );\n }\n const sourcedError = ensureRegistrationErrorSource(error, url.href);\n if (sourcedError instanceof RegistrationLookupError) throw sourcedError;\n throw new RegistrationLookupError(\n `Request to ${url.hostname} failed: ${errorMessage(sourcedError)}`,\n \"network\",\n url.href,\n );\n } finally {\n clearTimeout(timeout);\n await dispatcher.close();\n }\n }\n\n throw new RegistrationLookupError(\"RDAP request failed\", \"network\");\n}\n\nasync function getBootstrap(url: string): Promise<BootstrapData> {\n const cached = bootstrapCache.get(url);\n if (cached && cached.expiresAt > Date.now()) return cached.data;\n\n const response = await fetchJson(url, MAX_BOOTSTRAP_BYTES);\n const services = response.data.services;\n if (!Array.isArray(services)) {\n throw new RegistrationLookupError(\n \"IANA RDAP bootstrap response has no services array\",\n \"invalid-response\",\n );\n }\n const data = { services };\n bootstrapCache.set(url, { data, expiresAt: Date.now() + BOOTSTRAP_TTL_MS });\n return data;\n}\n\nfunction bootstrapServices(\n data: BootstrapData,\n): { entries: string[]; urls: string[] }[] {\n const services: { entries: string[]; urls: string[] }[] = [];\n for (const service of data.services) {\n if (!Array.isArray(service) || service.length !== 2) continue;\n const entries = stringArray(service[0]).map((entry) => entry.toLowerCase());\n const urls = stringArray(service[1]).filter((url) =>\n url.startsWith(\"https://\"),\n );\n if (entries.length > 0 && urls.length > 0) services.push({ entries, urls });\n }\n return services;\n}\n\nfunction domainServiceUrls(data: BootstrapData, domain: string): string[] {\n let longestMatch = -1;\n let urls: string[] = [];\n for (const service of bootstrapServices(data)) {\n for (const entry of service.entries) {\n if (domain !== entry && !domain.endsWith(`.${entry}`)) continue;\n const labels = entry.split(\".\").length;\n if (labels > longestMatch) {\n longestMatch = labels;\n urls = [...service.urls];\n } else if (labels === longestMatch) {\n urls.push(...service.urls);\n }\n }\n }\n return [...new Set(urls)];\n}\n\nfunction ipServiceUrls(data: BootstrapData, ip: string): string[] {\n const family = net.isIP(ip);\n const type = family === 4 ? \"ipv4\" : \"ipv6\";\n let longestPrefix = -1;\n let urls: string[] = [];\n\n for (const service of bootstrapServices(data)) {\n for (const entry of service.entries) {\n const [network, rawPrefix] = entry.split(\"/\");\n const prefix = Number(rawPrefix);\n if (!network || !Number.isInteger(prefix) || net.isIP(network) !== family)\n continue;\n try {\n const block = new net.BlockList();\n block.addSubnet(network, prefix, type);\n if (!block.check(ip, type)) continue;\n } catch {\n continue;\n }\n if (prefix > longestPrefix) {\n longestPrefix = prefix;\n urls = [...service.urls];\n } else if (prefix === longestPrefix) {\n urls.push(...service.urls);\n }\n }\n }\n return [...new Set(urls)];\n}\n\nasync function queryFirstRdapService(\n baseUrls: string[],\n path: string,\n): Promise<RdapResponse> {\n let lastError: unknown;\n for (const baseUrl of baseUrls) {\n try {\n const base = validateHttpsUrl(baseUrl);\n if (!base.pathname.endsWith(\"/\")) base.pathname += \"/\";\n const queryUrl = new URL(path, base);\n return await fetchJson(queryUrl.href, MAX_RDAP_BYTES);\n } catch (error) {\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"not-found\"\n ) {\n throw error;\n }\n lastError = error;\n }\n }\n throw (\n lastError ??\n new RegistrationLookupError(\"No usable RDAP service\", \"unsupported\")\n );\n}\n\nfunction relatedRdapUrl(data: Record<string, unknown>): string | undefined {\n if (!Array.isArray(data.links)) return undefined;\n for (const value of data.links) {\n if (!isRecord(value) || value.rel !== \"related\") continue;\n const href = stringValue(value.href);\n const type = stringValue(value.type);\n if (href && type?.toLowerCase().includes(\"application/rdap+json\"))\n return href;\n }\n return undefined;\n}\n\nfunction eventLines(data: Record<string, unknown>): string[] {\n if (!Array.isArray(data.events)) return [];\n const labels: Record<string, string> = {\n registration: \"Registered\",\n expiration: \"Expires\",\n \"last changed\": \"Updated\",\n \"last update of RDAP database\": \"RDAP database updated\",\n };\n const lines: string[] = [];\n for (const event of data.events) {\n if (!isRecord(event)) continue;\n const action = stringValue(event.eventAction);\n const date = stringValue(event.eventDate);\n if (action && date) lines.push(`${labels[action] ?? action}: ${date}`);\n }\n return lines;\n}\n\nfunction vcardFields(entity: Record<string, unknown>): Map<string, string[]> {\n const fields = new Map<string, string[]>();\n if (!Array.isArray(entity.vcardArray) || !Array.isArray(entity.vcardArray[1]))\n return fields;\n for (const property of entity.vcardArray[1]) {\n if (!Array.isArray(property) || property.length < 4) continue;\n const name = stringValue(property[0])?.toLowerCase();\n const value = stringValue(property[3]);\n if (!name || !value) continue;\n fields.set(name, [...(fields.get(name) ?? []), value]);\n }\n return fields;\n}\n\nfunction entityLines(data: Record<string, unknown>): string[] {\n if (!Array.isArray(data.entities)) return [];\n const lines: string[] = [];\n const visit = (entity: unknown): void => {\n if (!isRecord(entity)) return;\n const roles = stringArray(entity.roles);\n const fields = vcardFields(entity);\n const name = fields.get(\"fn\")?.[0] ?? fields.get(\"org\")?.[0];\n const handle = stringValue(entity.handle);\n const identity = name ?? handle;\n if (identity) {\n const publicIds = Array.isArray(entity.publicIds)\n ? entity.publicIds\n .map((value) => {\n if (!isRecord(value)) return undefined;\n const type = stringValue(value.type);\n const identifier = stringValue(value.identifier);\n return type && identifier ? `${type} ${identifier}` : undefined;\n })\n .filter((value): value is string => value !== undefined)\n : [];\n const details = [\n ...publicIds,\n ...(fields.get(\"email\") ?? []).map((value) => `email ${value}`),\n ...(fields.get(\"tel\") ?? []).map((value) => `telephone ${value}`),\n ];\n lines.push(\n `Entity${roles.length > 0 ? ` (${roles.join(\", \")})` : \"\"}: ${identity}${details.length > 0 ? `; ${details.join(\"; \")}` : \"\"}`,\n );\n }\n if (Array.isArray(entity.entities)) entity.entities.forEach(visit);\n };\n data.entities.forEach(visit);\n return [...new Set(lines)];\n}\n\nfunction noticeTitles(data: Record<string, unknown>): string[] {\n if (!Array.isArray(data.notices)) return [];\n return data.notices\n .map((notice) => (isRecord(notice) ? stringValue(notice.title) : undefined))\n .filter((title): title is string => title !== undefined);\n}\n\nfunction formatDomainRdap(\n responses: RdapResponse[],\n requestedDomain: string,\n warnings: string[],\n): string {\n const data: Record<string, unknown> = Object.assign(\n {},\n ...responses\n .slice()\n .reverse()\n .map((response) => response.data),\n );\n data.entities = responses.flatMap((response) =>\n Array.isArray(response.data.entities) ? response.data.entities : [],\n );\n data.notices = responses.flatMap((response) =>\n Array.isArray(response.data.notices) ? response.data.notices : [],\n );\n data.events = responses.flatMap((response) =>\n Array.isArray(response.data.events) ? response.data.events : [],\n );\n const lines = [\n \"Protocol: RDAP\",\n ...responses.map((response) => `Source: ${response.source}`),\n `Domain: ${stringValue(data.unicodeName) ?? stringValue(data.ldhName) ?? requestedDomain}`,\n ];\n const handle = stringValue(data.handle);\n if (handle) lines.push(`Registry ID: ${handle}`);\n lines.push(...eventLines(data));\n const statuses = stringArray(data.status);\n if (statuses.length > 0) lines.push(`Status: ${statuses.join(\", \")}`);\n\n if (Array.isArray(data.nameservers)) {\n const nameservers = data.nameservers\n .map((value) =>\n isRecord(value)\n ? (stringValue(value.unicodeName) ?? stringValue(value.ldhName))\n : undefined,\n )\n .filter((value): value is string => value !== undefined);\n if (nameservers.length > 0)\n lines.push(`Nameservers: ${nameservers.join(\", \")}`);\n }\n if (isRecord(data.secureDNS)) {\n const signed = data.secureDNS.delegationSigned;\n if (typeof signed === \"boolean\")\n lines.push(`DNSSEC: ${signed ? \"signed\" : \"unsigned\"}`);\n }\n lines.push(...entityLines(data));\n const notices = noticeTitles(data);\n if (notices.length > 0) lines.push(`Notices: ${notices.join(\"; \")}`);\n lines.push(...warnings.map((warning) => `Warning: ${warning}`));\n return lines.join(\"\\n\");\n}\n\nfunction formatIpRdap(response: RdapResponse, ip: string): string {\n const { data } = response;\n const lines = [\"Protocol: RDAP\", `Source: ${response.source}`, `IP: ${ip}`];\n for (const [label, key] of [\n [\"Network\", \"name\"],\n [\"Handle\", \"handle\"],\n [\"Start address\", \"startAddress\"],\n [\"End address\", \"endAddress\"],\n [\"IP version\", \"ipVersion\"],\n [\"Type\", \"type\"],\n [\"Country\", \"country\"],\n [\"Parent handle\", \"parentHandle\"],\n ] as const) {\n const value = stringValue(data[key]);\n if (value) lines.push(`${label}: ${value}`);\n }\n const statuses = stringArray(data.status);\n if (statuses.length > 0) lines.push(`Status: ${statuses.join(\", \")}`);\n lines.push(...eventLines(data), ...entityLines(data));\n const notices = noticeTitles(data);\n if (notices.length > 0) lines.push(`Notices: ${notices.join(\"; \")}`);\n return lines.join(\"\\n\");\n}\n\nexport function normaliseRegistrationDomain(domain: string): string {\n const candidate = domain.trim().replace(/\\.$/, \"\");\n const containsControlCharacter = [...candidate].some((character) => {\n const codePoint = character.codePointAt(0) ?? 0;\n return codePoint <= 0x1f || codePoint === 0x7f;\n });\n if (!candidate || containsControlCharacter) {\n throw new Error(\"Invalid domain\");\n }\n const ascii = domainToASCII(candidate).toLowerCase();\n if (!ascii || ascii.length > 253) throw new Error(\"Invalid domain\");\n const labels = ascii.split(\".\");\n if (\n labels.some(\n (label) =>\n label.length === 0 ||\n label.length > 63 ||\n !/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/u.test(label),\n )\n ) {\n throw new Error(\"Invalid domain\");\n }\n return ascii;\n}\n\nfunction ianaWhoisDiscoveryQuery(domain: string): string {\n // IANA registry referrals are keyed by the DNS root TLD, not an effective\n // public suffix. For example, both example.co.uk and example.me.uk use uk.\n return domain.split(\".\").at(-1) ?? domain;\n}\n\nfunction parseWhoisEndpoint(\n value: string,\n allowWebScheme = false,\n): WhoisEndpoint {\n const candidate = value.includes(\"://\") ? value : `whois://${value}`;\n let url: URL;\n try {\n url = new URL(candidate);\n } catch {\n throw new RegistrationLookupError(\n `Invalid WHOIS referral: ${value}`,\n \"invalid-response\",\n undefined,\n \"REFERRAL_REJECTED\",\n );\n }\n const webScheme = url.protocol === \"http:\" || url.protocol === \"https:\";\n const port = webScheme ? 43 : url.port ? Number(url.port) : 43;\n if (\n (url.protocol !== \"whois:\" && !(allowWebScheme && webScheme)) ||\n !url.hostname ||\n url.username ||\n url.password ||\n (url.pathname && url.pathname !== \"/\") ||\n url.search ||\n url.hash ||\n (!webScheme && url.port && url.port !== \"43\")\n ) {\n throw new RegistrationLookupError(\n `Refusing unsafe WHOIS referral: ${value}`,\n \"security\",\n undefined,\n \"REFERRAL_REJECTED\",\n );\n }\n return { host: url.hostname.replace(/^\\[|\\]$/g, \"\").toLowerCase(), port };\n}\n\nfunction whoisReferral(response: string): WhoisEndpoint | undefined {\n for (const [pattern, allowWebScheme] of [\n [/^refer:[ \\t]*(\\S+)/im, false],\n [/^whois:[ \\t]*(\\S+)/im, false],\n [/^Registrar WHOIS Server:[ \\t]*(\\S+)/im, true],\n [/^ReferralServer:[ \\t]*(\\S+)/im, false],\n ] as const) {\n const match = response.match(pattern);\n if (match?.[1]) return parseWhoisEndpoint(match[1].trim(), allowWebScheme);\n }\n return undefined;\n}\n\nfunction inspectWhoisResponse(response: string): {\n notFound: boolean;\n warnings: RegistrationWarning[];\n} {\n const hasRegistrationData =\n /^(?:Domain Name|Domain|domain|NetRange|CIDR|inetnum|network|route):[ \\t]*\\S+/imu.test(\n response,\n );\n if (\n !hasRegistrationData &&\n /(?:rate limit|query limit|quota exceeded|too many quer(?:y|ies)|maximum number of quer(?:y|ies)|try again later)/iu.test(\n response,\n )\n ) {\n throw new RegistrationLookupError(\n \"WHOIS service rate limited the request\",\n \"rate-limited\",\n undefined,\n \"WHOIS_RATE_LIMITED\",\n );\n }\n if (\n !hasRegistrationData &&\n /(?:whois service (?:has been |is )?(?:retired|discontinued)|whois is no longer available)/iu.test(\n response,\n )\n ) {\n throw new RegistrationLookupError(\n \"WHOIS service reports that it has been retired\",\n \"unsupported\",\n undefined,\n \"WHOIS_SERVICE_RETIRED\",\n );\n }\n if (\n !hasRegistrationData &&\n /(?:web[- ]based whois|web whois|visit .{0,80}whois)/isu.test(response)\n ) {\n throw new RegistrationLookupError(\n \"Registry directs queries to a web-based WHOIS service\",\n \"unsupported\",\n undefined,\n \"WHOIS_WEB_ONLY\",\n );\n }\n if (\n !hasRegistrationData &&\n /(?:invalid query|malformed query|unsupported query|syntax error|^usage:)/imu.test(\n response,\n )\n ) {\n throw new RegistrationLookupError(\n \"WHOIS service rejected the query syntax\",\n \"invalid-response\",\n undefined,\n \"WHOIS_UNSUPPORTED_RESPONSE\",\n );\n }\n\n const warnings: RegistrationWarning[] = [];\n if (response.includes(\"\\uFFFD\")) {\n warnings.push({\n reason: \"WHOIS_INVALID_ENCODING\",\n detail: \"WHOIS response contains bytes that are not valid UTF-8\",\n });\n }\n return {\n notFound:\n !hasRegistrationData &&\n /(?:no match for|not found|no entries found|no object found)/iu.test(\n response,\n ),\n warnings,\n };\n}\n\nfunction whoisQueryValue(host: string, query: string): string {\n if (host === \"whois.jprs.jp\" && !query.endsWith(\"/e\")) return `${query}/e`;\n if (host === \"whois.denic.de\") return `-T dn,ace ${query}`;\n return query;\n}\n\nasync function whoisQuery(\n endpoint: WhoisEndpoint,\n query: string,\n): Promise<string> {\n const addresses = await resolvePublicHostname(endpoint.host, true);\n return await new Promise((resolve, reject) => {\n let settled = false;\n let total = 0;\n const chunks: Buffer[] = [];\n const timeoutError = (): RegistrationLookupError =>\n new RegistrationLookupError(\n \"WHOIS query timed out\",\n \"network\",\n undefined,\n \"WHOIS_TIMEOUT\",\n );\n const socket = net.createConnection(\n { ...endpoint, lookup: pinnedLookup(addresses) },\n () => {\n socket.write(`${whoisQueryValue(endpoint.host, query)}\\r\\n`);\n },\n );\n const deadline = setTimeout(\n () => socket.destroy(timeoutError()),\n REQUEST_TIMEOUT_MS,\n );\n const finish = (error?: Error): void => {\n if (settled) return;\n settled = true;\n clearTimeout(deadline);\n if (error) reject(error);\n else resolve(Buffer.concat(chunks).toString(\"utf-8\"));\n };\n socket.on(\"data\", (chunk: Buffer) => {\n total += chunk.byteLength;\n if (total > MAX_WHOIS_BYTES) {\n socket.destroy(\n new RegistrationLookupError(\n `WHOIS response exceeds ${MAX_WHOIS_BYTES} bytes`,\n \"invalid-response\",\n undefined,\n \"RESPONSE_TOO_LARGE\",\n ),\n );\n return;\n }\n chunks.push(chunk);\n });\n socket.on(\"end\", () => finish());\n socket.on(\"error\", (error) => finish(error));\n socket.setTimeout(REQUEST_TIMEOUT_MS, () => {\n socket.destroy(timeoutError());\n });\n });\n}\n\nasync function legacyWhois(\n query: string,\n discoveryQuery = query,\n): Promise<string> {\n let endpoint = { host: \"whois.iana.org\", port: 43 };\n const visited = new Set<string>();\n let response = \"\";\n const warnings: RegistrationWarning[] = [];\n\n for (let index = 0; index < MAX_WHOIS_QUERIES; index += 1) {\n const key = `${endpoint.host}:${endpoint.port}`;\n if (visited.has(key)) {\n throw new RegistrationLookupError(\n \"WHOIS referral loop detected\",\n \"invalid-response\",\n `whois://${endpoint.host}:43`,\n \"REFERRAL_LOOP\",\n );\n }\n visited.add(key);\n try {\n response = (\n await whoisQuery(endpoint, index === 0 ? discoveryQuery : query)\n ).trim();\n } catch (error) {\n throw new RegistrationLookupError(\n errorMessage(error),\n error instanceof RegistrationLookupError ? error.kind : \"network\",\n `whois://${endpoint.host}:43`,\n reasonForError(\"WHOIS\", error),\n );\n }\n\n let referral: WhoisEndpoint | undefined;\n try {\n referral = whoisReferral(response);\n } catch (error) {\n if (index === 0) throw error;\n warnings.push({\n reason: reasonForError(\"WHOIS\", error),\n detail: errorMessage(error),\n });\n break;\n }\n if (!referral) {\n if (index === 0) {\n throw new RegistrationLookupError(\n \"IANA does not advertise a WHOIS service for this query\",\n \"unsupported\",\n \"whois://whois.iana.org:43\",\n \"WHOIS_NOT_ADVERTISED\",\n );\n }\n break;\n }\n const referralKey = `${referral.host}:${referral.port}`;\n if (visited.has(referralKey)) {\n if (referralKey === key) break;\n throw new RegistrationLookupError(\n \"WHOIS referral loop detected\",\n \"invalid-response\",\n `whois://${endpoint.host}:43`,\n \"REFERRAL_LOOP\",\n );\n }\n if (index === MAX_WHOIS_QUERIES - 1) {\n warnings.push({\n reason: \"REFERRAL_LIMIT_REACHED\",\n detail: `WHOIS referral limit of ${MAX_WHOIS_QUERIES} queries reached`,\n });\n break;\n }\n try {\n await resolvePublicHostname(referral.host, true);\n } catch (error) {\n if (index === 0) throw error;\n warnings.push({\n reason: reasonForError(\"WHOIS\", error),\n detail: errorMessage(error),\n });\n break;\n }\n endpoint = referral;\n }\n\n if (!response)\n throw new RegistrationLookupError(\n \"No WHOIS data returned\",\n \"network\",\n `whois://${endpoint.host}:43`,\n \"WHOIS_EMPTY_RESPONSE\",\n );\n let inspection: ReturnType<typeof inspectWhoisResponse>;\n try {\n inspection = inspectWhoisResponse(response);\n } catch (error) {\n throw new RegistrationLookupError(\n errorMessage(error),\n error instanceof RegistrationLookupError\n ? error.kind\n : \"invalid-response\",\n `whois://${endpoint.host}:43`,\n reasonForError(\"WHOIS\", error),\n );\n }\n warnings.push(...inspection.warnings);\n return [\n \"Protocol: WHOIS\",\n `Source: whois://${endpoint.host}:43`,\n ...(inspection.notFound\n ? [\"Status: not registered or not found\", \"Reason: WHOIS_NOT_FOUND\"]\n : []),\n ...warnings.map((warning) => `Warning: ${warningText(warning)}`),\n \"\",\n response,\n ].join(\"\\n\");\n}\n\nfunction fallbackWarning(error: unknown): string {\n const source =\n error instanceof RegistrationLookupError && error.source\n ? ` at ${error.source}`\n : \"\";\n return `${reasonForError(\"RDAP\", error)}${source}: ${errorMessage(error)}; used WHOIS fallback`;\n}\n\nexport async function domainRegistrationLookupResult(\n domain: string,\n): Promise<RegistrationLookupResult> {\n const normalised = normaliseRegistrationDomain(domain);\n let rdapError: unknown;\n try {\n const bootstrap = await getBootstrap(RDAP_DNS_BOOTSTRAP);\n const urls = domainServiceUrls(bootstrap, normalised);\n if (urls.length > 0) {\n try {\n const registry = await queryFirstRdapService(\n urls,\n `domain/${encodeURIComponent(normalised)}`,\n );\n const responses = [registry];\n const warnings: string[] = [];\n const related = relatedRdapUrl(registry.data);\n if (related) {\n try {\n responses.push(await fetchJson(related, MAX_RDAP_BYTES));\n } catch (error) {\n warnings.push(\n `${reasonForError(\"RDAP\", error)}: registrar RDAP lookup failed: ${errorMessage(error)}`,\n );\n }\n }\n return {\n text: formatDomainRdap(responses, normalised, warnings),\n failed: false,\n };\n } catch (error) {\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"not-found\"\n ) {\n return {\n text: `Protocol: RDAP\\nSource: ${error.source ?? \"authoritative RDAP service\"}\\nDomain: ${normalised}\\nStatus: not registered or not found\\nReason: RDAP_NOT_FOUND`,\n failed: false,\n };\n }\n rdapError = error;\n }\n } else {\n rdapError = new RegistrationLookupError(\n \"IANA has no RDAP bootstrap service for this TLD\",\n \"unsupported\",\n );\n }\n } catch (error) {\n rdapError = error;\n }\n\n try {\n const result = await legacyWhois(\n normalised,\n ianaWhoisDiscoveryQuery(normalised),\n );\n return {\n text: rdapError\n ? `${result}\\n\\nWarning: ${fallbackWarning(rdapError)}`\n : result,\n failed: false,\n };\n } catch (whoisError) {\n if (rdapError) {\n return {\n text: formatLookupFailure(\"Domain\", normalised, rdapError, whoisError),\n failed: true,\n };\n }\n return {\n text: formatLookupFailure(\n \"Domain\",\n normalised,\n new RegistrationLookupError(\n \"RDAP was not attempted\",\n \"unsupported\",\n undefined,\n \"RDAP_NOT_AVAILABLE\",\n ),\n whoisError,\n ),\n failed: true,\n };\n }\n}\n\nexport async function domainRegistrationLookup(\n domain: string,\n): Promise<string> {\n return (await domainRegistrationLookupResult(domain)).text;\n}\n\nexport async function ipRegistrationLookupResult(\n ip: string,\n): Promise<RegistrationLookupResult> {\n const family = net.isIP(ip);\n if (family === 0) throw new Error(\"Invalid IP address\");\n let rdapError: unknown;\n try {\n const bootstrap = await getBootstrap(\n family === 4 ? RDAP_IPV4_BOOTSTRAP : RDAP_IPV6_BOOTSTRAP,\n );\n const urls = ipServiceUrls(bootstrap, ip);\n if (urls.length > 0) {\n try {\n const response = await queryFirstRdapService(\n urls,\n `ip/${encodeURIComponent(ip)}`,\n );\n return { text: formatIpRdap(response, ip), failed: false };\n } catch (error) {\n if (\n error instanceof RegistrationLookupError &&\n error.kind === \"not-found\"\n ) {\n return {\n text: `Protocol: RDAP\\nSource: ${error.source ?? \"authoritative RDAP service\"}\\nIP: ${ip}\\nStatus: registration data not found\\nReason: RDAP_NOT_FOUND`,\n failed: false,\n };\n }\n rdapError = error;\n }\n } else {\n rdapError = new RegistrationLookupError(\n \"IANA has no RDAP bootstrap service for this address\",\n \"unsupported\",\n );\n }\n } catch (error) {\n rdapError = error;\n }\n\n try {\n const result = await legacyWhois(ip);\n return {\n text: rdapError\n ? `${result}\\n\\nWarning: ${fallbackWarning(rdapError)}`\n : result,\n failed: false,\n };\n } catch (whoisError) {\n if (rdapError) {\n return {\n text: formatLookupFailure(\"IP\", ip, rdapError, whoisError),\n failed: true,\n };\n }\n return {\n text: formatLookupFailure(\n \"IP\",\n ip,\n new RegistrationLookupError(\n \"RDAP was not attempted\",\n \"unsupported\",\n undefined,\n \"RDAP_NOT_AVAILABLE\",\n ),\n whoisError,\n ),\n failed: true,\n };\n }\n}\n\nexport async function ipRegistrationLookup(ip: string): Promise<string> {\n return (await ipRegistrationLookupResult(ip)).text;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport packageJson from \"../package.json\" with { type: \"json\" };\nimport {\n dnsLookup,\n reverseDns,\n resolveAll,\n checkNameservers,\n whoisLookupResult,\n ipWhoisResult,\n} from \"./dns.js\";\n\nconst recordTypeSchema = z\n .enum([\"A\", \"AAAA\", \"MX\", \"TXT\", \"CNAME\", \"NS\", \"SOA\", \"SRV\", \"CAA\", \"PTR\"])\n .default(\"A\");\n\nconst readOnlyAnnotations = {\n readOnlyHint: true,\n destructiveHint: false,\n};\n\nexport function createMcpServer(): McpServer {\n const server = new McpServer(\n {\n name: \"mcp-dns-tools\",\n version: packageJson.version,\n },\n {\n instructions:\n \"When the user names one DNS record type, call dns_lookup and pass that type, except for NS or nameserver-only requests, which must use check_nameservers. For CAA requests, call dns_lookup with type CAA. Use resolve_all only when the user asks for all records, multiple record types, a DNS overview, or a general investigation. Never use resolve_all for one named record type. Use whois for domain registration, registrar, registration status, or registration-date questions. Use ip_whois for IP allocation and network ownership questions.\",\n },\n );\n\n server.registerTool(\n \"dns_lookup\",\n {\n title: \"DNS record lookup\",\n description:\n \"Use this when the user requests one specific DNS record type, except for NS or nameserver requests, which must use check_nameservers. For CAA or certificate authority issuance questions, call this tool with type CAA. Supports A, AAAA, MX, TXT, CNAME, SOA, SRV, CAA, PTR, and NS for backwards compatibility. Do not use resolve_all when the user names one record type.\",\n inputSchema: {\n domain: z\n .string()\n .describe(\"Domain name to look up (e.g. example.com)\"),\n type: recordTypeSchema.describe(\n \"Specific record type to return: A, AAAA, MX, TXT, CNAME, NS, SOA, SRV, CAA, or PTR. Use CAA for certificate authority issuance policy.\",\n ),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain, type }) => {\n const result = await dnsLookup(domain, type);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"reverse_dns\",\n {\n title: \"Reverse DNS lookup\",\n description: \"Perform a reverse DNS (PTR) lookup on an IP address.\",\n inputSchema: {\n ip: z.string().describe(\"IP address (e.g. 8.8.8.8)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ ip }) => {\n const result = await reverseDns(ip);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"resolve_all\",\n {\n title: \"DNS overview\",\n description:\n \"Use this only when the user requests all common DNS records, multiple record types, a DNS overview, or a general domain investigation. Returns A, AAAA, MX, TXT, CAA, NS, and CNAME. Do not use this for one named record type.\",\n inputSchema: {\n domain: z\n .string()\n .describe(\"Domain name to resolve (e.g. example.com)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain }) => {\n const result = await resolveAll(domain);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"check_nameservers\",\n {\n title: \"Nameserver lookup\",\n description:\n \"Use this whenever the user requests NS records, nameservers, authoritative nameservers, or domain delegation nameservers.\",\n inputSchema: {\n domain: z.string().describe(\"Domain name (e.g. example.com)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain }) => {\n const result = await checkNameservers(domain);\n return { content: [{ type: \"text\" as const, text: result }] };\n },\n );\n\n server.registerTool(\n \"whois\",\n {\n title: \"Domain registration lookup\",\n description:\n \"Query authoritative domain registration data, including registrar, status, dates, nameservers, and DNSSEC. Uses IANA RDAP discovery over HTTPS and follows a registrar RDAP link when available, with bounded legacy WHOIS fallback for TLDs without working RDAP. Supports Unicode domain names. Failures identify each attempted protocol, endpoint, stable reason code, detail, and suggested next action.\",\n inputSchema: {\n domain: z\n .string()\n .describe(\"Domain name for registration lookup (e.g. example.com)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ domain }) => {\n const result = await whoisLookupResult(domain);\n return {\n content: [{ type: \"text\" as const, text: result.text }],\n isError: result.failed,\n };\n },\n );\n\n server.registerTool(\n \"ip_whois\",\n {\n title: \"IP registration lookup\",\n description:\n \"Query authoritative IPv4 or IPv6 allocation and network ownership data. Uses IANA RDAP bootstrap discovery over HTTPS, with bounded legacy WHOIS fallback to the appropriate Regional Internet Registry. Failures identify each attempted protocol, endpoint, stable reason code, detail, and suggested next action.\",\n inputSchema: {\n ip: z\n .string()\n .describe(\"IP address (e.g. 8.8.8.8 or 2001:4860:4860::8888)\"),\n },\n annotations: readOnlyAnnotations,\n },\n async ({ ip }) => {\n const result = await ipWhoisResult(ip);\n return {\n content: [{ type: \"text\" as const, text: result.text }],\n isError: result.failed,\n };\n },\n );\n\n return server;\n}\n","{\n \"name\": \"@paulgit/mcp-dns-tools\",\n \"mcpName\": \"it.paulg/dns-tools\",\n \"version\": \"2.2.1\",\n \"description\": \"MCP server for DNS lookups, including CAA checks, reverse DNS, and RDAP-first domain or IP registration data with WHOIS fallback; zero auth, zero config\",\n \"type\": \"module\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24\"\n },\n \"bin\": {\n \"mcp-dns-tools\": \"dist/index.js\"\n },\n \"files\": [\n \"dist\",\n \"skills\"\n ],\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"lint\": \"eslint . && prettier --check .\",\n \"format\": \"prettier --write .\",\n \"audit:deps\": \"npm audit --omit=dev --audit-level=high\",\n \"prepack\": \"npm run build\",\n \"prepublishOnly\": \"npm run lint && npm run typecheck && npm test\",\n \"prepare\": \"husky\"\n },\n \"keywords\": [\n \"mcp\",\n \"mcp-server\",\n \"model-context-protocol\",\n \"dns\",\n \"whois\",\n \"domain\",\n \"network\",\n \"lookup\",\n \"nameserver\",\n \"caa\",\n \"tls\",\n \"certificate-authority\",\n \"ai\",\n \"llm\",\n \"claude\",\n \"cursor\"\n ],\n \"author\": \"Paul Git (https://code.paulg.it/paulgit)\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://code.paulg.it/paulgit/mcp-dns-tools.git\"\n },\n \"bugs\": {\n \"url\": \"https://code.paulg.it/paulgit/mcp-dns-tools/issues\"\n },\n \"homepage\": \"https://code.paulg.it/paulgit/mcp-dns-tools#readme\",\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.26.0\",\n \"undici\": \"^8.10.0\",\n \"zod\": \"^3.25.0\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.0.0\",\n \"@types/node\": \"^22.0.0\",\n \"eslint\": \"^9.0.0\",\n \"eslint-config-prettier\": \"^10.0.0\",\n \"husky\": \"^9.0.0\",\n \"lint-staged\": \"^15.0.0\",\n \"prettier\": \"^3.0.0\",\n \"tsup\": \"^8.0.0\",\n \"typescript\": \"^5.7.0\",\n \"typescript-eslint\": \"^8.0.0\",\n \"vitest\": \"^3.2.0\"\n },\n \"lint-staged\": {\n \"*.{ts,tsx,js}\": [\n \"eslint --fix\",\n \"prettier --write\"\n ],\n \"*.{json,md,yml,yaml}\": [\n \"prettier --write\"\n ]\n },\n \"allowScripts\": {\n \"esbuild@0.27.2\": true,\n \"fsevents@2.3.3\": true\n }\n}\n"],"mappings":"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","names":["dns","net","net","dns"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@paulgit/mcp-dns-tools",
3
3
  "mcpName": "it.paulg/dns-tools",
4
- "version": "2.2.0",
4
+ "version": "2.2.1",
5
5
  "description": "MCP server for DNS lookups, including CAA checks, reverse DNS, and RDAP-first domain or IP registration data with WHOIS fallback; zero auth, zero config",
6
6
  "type": "module",
7
7
  "publishConfig": {
@@ -11,7 +11,7 @@
11
11
  "node": ">=24"
12
12
  },
13
13
  "bin": {
14
- "mcp-dns-tools": "./dist/index.js"
14
+ "mcp-dns-tools": "dist/index.js"
15
15
  },
16
16
  "files": [
17
17
  "dist",
@@ -84,5 +84,9 @@
84
84
  "*.{json,md,yml,yaml}": [
85
85
  "prettier --write"
86
86
  ]
87
+ },
88
+ "allowScripts": {
89
+ "esbuild@0.27.2": true,
90
+ "fsevents@2.3.3": true
87
91
  }
88
92
  }