MCP documentation menu

DNS Lookup Tools

DataPulse provides datapulse_live_dns for DNS lookups and datapulse_live_rdap for registration data (domains and IP addresses). Both return structured JSON and are always synchronous — no polling required.

Resolver: All DNS tools query through a DNSSEC-validating recursive resolver with the EDNS DO flag set. Responses are automatically validated. It applies no content filtering, with one deliberate exception: answers that point at private, link-local or IPv6 unique-local ranges (10/8, 172.16/12, 192.168/16, 169.254/16, fd00::/8, fe80::/10) are dropped, so a name such as 10.0.0.1.nip.io returns NOERROR with no answer and datapulse_domain_overview reports resolves: false. The same ranges are dropped when wrapped in an IPv6 form that carries an IPv4 address: IPv4-mapped (::ffff:10.0.0.1), the deprecated IPv4-compatible form (::10.0.0.1) and 6to4 (2002:a00:1::). Every NAT64 address (64:ff9b::/96, 64:ff9b:1::/48) is dropped, private inside or not. Loopback is not dropped in any form (127.0.0.1, ::1, ::ffff:127.0.0.1): domains sinkholed to it are worth seeing. The scraper’s own connection guard is separate and stricter: it refuses all of these, loopback included. The specific resolver is not exposed or configurable.

datapulse_live_dns

Parameters

ParameterTypeRequiredDescription
domainstringYesName to query (IDN supported). Its spelling is canonicalized — case, surrounding whitespace, every trailing dot, Unicode label separators, IDN to A-labels — and no labels are removed: www.example.com and example.com resolve independently. A single label (com) and underscore names (_dmarc.example.com) are accepted: both are fair DNS questions. When canonicalizing changed more than letter case, the response carries submitted_domain with what you sent. See datapulse_help(topic="normalization")
record_typestringNoSpecific record type to query. If omitted, queries A, AAAA, MX, NS, TXT, SOA, CNAME, CAA, DNSKEY, DS plus _dmarc TXT
forcebooleanNoForce a fresh lookup (default: false). DNS lookups are always live — cached only at the resolver layer, not the application layer — so this is rarely needed
fullbooleanNoReturn full raw DNS output (default: false — returns compact summary)
metadataobjectNoCustom key-value metadata stored with result

Supported Record Types

A, AAAA, CNAME, MX, NS, TXT, SOA, PTR, SRV, CAA, DNSKEY, DS, RRSIG, NSEC, TLSA, NAPTR, SSHFP

Default Behavior

When record_type is omitted, live_dns queries 10 record types (A, AAAA, MX, NS, TXT, SOA, CNAME, CAA, DNSKEY, DS) plus a _dmarc.<domain> TXT lookup, all in parallel, returning everything in a single response. This is ideal for general reconnaissance and provides DMARC policy visibility without a separate call.

When record_type is specified, only that single type is queried against the exact domain provided. The automatic DMARC subdomain lookup is not performed. Use this for:

  • Record types not in the default set: SRV, PTR, TLSA, NAPTR, SSHFP
  • Subdomain-specific queries: _sip._tcp.example.com (SRV)
  • Reverse DNS: x.x.x.x.in-addr.arpa (PTR)

Response Format (default: summary)

By default, returns a compact summary:

{
  "status": "ok",
  "dnssec_signed": true,
  "records": {
    "A": [{"name": "example.com.", "ttl": 3600, "data": {"address": "93.184.216.34"}}],
    "MX": [{"name": "example.com.", "ttl": 3600, "data": {"preference": 10, "exchange": "mail.example.com."}}]
  },
  "dmarc": {
    "status": "found",
    "record": "v=DMARC1; p=reject; rua=mailto:dmarc@example.com"
  },
  "query_time_ms": 42
}
  • status: "ok", "nxdomain", "servfail", or "error"
  • dnssec_signed: true if the AD (Authenticated Data) flag was set in any response
  • records: answer records grouped by type, with DNSSEC metadata (RRSIG, NSEC, NSEC3, NSEC3PARAM, DNSKEY, DS) stripped and duplicates removed
  • dmarc: DMARC policy from _dmarc.<domain> TXT lookup. status is "found" (with record containing the full DMARC value) or "none" (no DMARC record). Only present in default mode (omitted when record_type is specified)
  • query_time_ms: server-side query duration

For nxdomain, the records field contains the SOA record from the authorities section.

Full Response Format (full=true)

Set full=true to get the complete raw DNS output, including per-query flags, authorities, additionals, and RRSIG/NSEC records. This is useful for DNSSEC chain-of-trust inspection, debugging, or when you need authority/additional section data.

The full response includes DNS flags (qr, opcode, aa, tc, rd, ra, ad, cd, rcode) per query. The EDNS DO (DNSSEC OK) flag is set, so RRSIG records are returned alongside answers for signed zones.

Response Structure by status

statusrecordsMeaning
okRecords grouped by typeSuccessful lookup — at least one NOERROR response with answers
nxdomainSOA record (if available)Domain does not exist
servfailEmptyServer failure — often a DNSSEC validation failure, but may also be an upstream issue. To distinguish: query DNSKEY/DS with full=true to check the trust chain
errorEmptyLookup failed (connection error, malformed output, etc.)

With full=true, the raw rcode field in flags is available per query for finer-grained interpretation (e.g., NOERROR with empty answers = NODATA).

DNSSEC Inspection

The default summary includes a dnssec_signed boolean — true when the AD (Authenticated Data) flag was set, indicating the resolver validated the DNSSEC chain.

Scenariodnssec_signedMeaning
Unsigned zone (e.g., google.com)falseValidation N/A, no AD expected
Signed zone, validatedtrueData authenticated successfully
Signed zone, not validatedfalseNot necessarily bad (see note on negative responses below)
status: "servfail"N/AMay be DNSSEC failure or upstream issue — query DNSKEY/DS with full=true to check the trust chain

For full RRSIG details and per-query flags, use full=true.

To inspect the full DNSSEC chain, query DNSKEY and DS records with full=true — the compact summary strips DNSSEC record types (RRSIG, NSEC, NSEC3, DNSKEY, DS), so a summary-mode DNSKEY or DS query returns no records:

datapulse_live_dns(domain="example.com", record_type="DNSKEY", full=true)
datapulse_live_dns(domain="example.com", record_type="DS", full=true)

RRSIG key_tag Caveat

The key_tag field in RRSIG records is not globally unique. Managed DNS providers (e.g., Cloudflare) commonly reuse the same key material across customer zones, so unrelated domains may share identical key_tag values. This does not indicate shared keys between zones — it reflects the provider’s signing infrastructure. Do not use key_tag alone to infer cross-domain relationships.

Authorities and Additionals (full=true only)

These sections are only present in the full response (full=true). For successful lookups (NOERROR with answers), authorities is typically empty — this is normal. Recursive resolvers resolve NS referrals internally and only include authority records in negative responses (NXDOMAIN, NODATA). The additionals section is populated only when glue records are needed (e.g., NS queries where nameservers are in-bailiwick).

DNSSEC on Negative Responses

For NXDOMAIN under DNSSEC-signed zones, dnssec_signed (or ad in full mode) may still be false. Common causes include NSEC3 opt-out (the parent zone’s NSEC3 records use opt-out, meaning unsigned delegations don’t get authenticated denial) or resolver-specific behavior on negative responses. A false value on NXDOMAIN does not necessarily indicate a validation failure.

Hashes

datapulse_live_dns returns two identifiers, in both the summary and full=true output:

FieldWhat it hashesUse
dns_query_hashthe A-label domain with www. kept, plus the record type when one was requested (www.example.com + NUL + MX)the key the DNS row is stored under; datapulse_live_dns_bulk returns the same values as dns_query_hashes and per item in submitted[]
domain_hashthe www-stripped, lowercase, punycode domainthe canonical domain identifier; equal to domain_hash in datapulse_domain_overview, datapulse_live_domain_health and the scrape tools, so results join on it

www.example.com and example.com resolve independently, which is why the DNS key keeps www.; do not use dns_query_hash to join with the other tools.

datapulse_live_dns_bulk

Up to 1000 lookups per request, each {"domain": ..., "record_type"?, "force"?, "metadata"?}. This is async: it returns a receipt, not results. Retrieve each result afterward with datapulse_live_dns (same domain and record_type); a completed lookup returns instantly.

Every item is validated before anything is sent, and one bad item never costs you the batch. Six inputs — example.com, WWW.Example.COM. (A), foo.localhost, exa mple.com, a blank, and Example.com. — produce:

{
  "accepted": 2, "rejected": 1, "cached": 0,
  "batch_id": "b814d0c2-...",
  "job_ids": ["e8203c5c-...", "26f5c081-..."],
  "dns_query_hashes": ["a379a6f6...", "59809847..."],
  "errors": ["invalid_input"],
  "rejected_items": [{"index": 2, "query": "foo.localhost", "error": "invalid_input"}],
  "rejected_local": [
    {"index": 3, "query": "exa mple.com", "error": "invalid domain \"exa mple.com\": invalid domain format: ..."},
    {"index": 4, "query": "", "error": "invalid domain \"\": domain cannot be empty"}
  ],
  "duplicates": [{"index": 5, "query": "Example.com.", "first_index": 0}],
  "submitted": [
    {"index": 0, "query": "example.com", "domain_hash": "a379a6f6...", "dns_query_hash": "a379a6f6...", "job_id": "e8203c5c-..."},
    {"index": 1, "query": "www.example.com", "record_type": "A", "domain_hash": "a379a6f6...", "dns_query_hash": "59809847...", "job_id": "26f5c081-..."},
    {"index": 2, "query": "foo.localhost", "domain_hash": "ec087f74...", "dns_query_hash": "ec087f74..."}
  ]
}
  • Every index is the position in your domains array. The item fields are index, query and error in both rejection lists (query holds the domain).
  • accepted, cached and rejected are the API’s own counts over the items that were sent. rejected_items lists what the API refused, with its code.
  • rejected_local lists what was refused before the request (not a valid name, or blank) with the reason. These are not counted in rejected — the API never saw them. To find every failure, read both lists.
  • duplicates are items that canonicalize to an earlier item with the same record type; they are submitted once.
  • submitted is every item that was sent, in canonical form. Sent is not accepted: foo.localhost passed validation, was sent, and the API refused it, so it appears in submitted without a job_id and in rejected_items.
  • Every input is accounted for: accepted + cached + rejected + len(rejected_local) + len(duplicates) equals the number of items you passed (2 + 0 + 1 + 2 + 1 = 6 above).

Registration Lookup Tools

For comprehensive registration lookup guidance — including datapulse_live_rdap, domain and IP address lookups, response format, caching, status codes, GDPR, and TLD-specific notes — see datapulse_help(topic="rdap").

Tips

  1. Default mode for general recon — Omit record_type to get A, AAAA, MX, NS, TXT, SOA, CNAME, CAA, DNSKEY, DS plus DMARC in one call. The compact summary groups records by type, strips DNSSEC metadata, and surfaces the DMARC policy in a dedicated dmarc field
  2. Specific record types — Use record_type for SRV, PTR, TLSA, NAPTR, SSHFP, or when you only need one type (disables the automatic DMARC lookup)
  3. Full output for debugging — Use full=true when you need per-query flags, RRSIG details, authorities, or additionals
  4. DNSSEC inspection — The summary’s dnssec_signed field shows validation status; use full=true plus DNSKEY/DS queries to trace the full trust chain
  5. RRSIG key_tag is not unique — Managed DNS providers (Cloudflare, AWS, etc.) reuse signing keys across customer zones, so matching key_tag values indicates a shared provider, not a shared key
  6. IDN Support — All tools accept both Unicode (U-label, e.g., münchen.de) and Punycode (A-label, e.g., xn--mnchen-3ya.de). Responses always use A-label form
  7. Reverse DNS — Query PTR records on x.x.x.x.in-addr.arpa domains: datapulse_live_dns(domain="14.5.217.172.in-addr.arpa", record_type="PTR")

Generated from the live server (DataPulse MCP 1.0.0) on October 1, 2026. Your AI assistant reads this page by calling datapulse_help(topic="dns").