# Domain Security (npm · domain-security-mcp-server)

Audit a domain's email and web security: SPF, DKIM, DMARC, MTA-STS, DNSSEC, TLS, WHOIS. No API keys.

- Trust score: 85/100 (high trust)
- Change this week: +3
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-09-24

## Components

- npm · `domain-security-mcp-server`: 85/100 (this document), [markdown](https://verifymcp.io/servers/ortamarco-domain-security-mcp-server/domain-security-mcp-server.md), [page](https://verifymcp.io/servers/ortamarco-domain-security-mcp-server/domain-security-mcp-server)

## Channel facts

- Registry: `npm`
- Package: `domain-security-mcp-server`
- Version: `1.2.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-09-24.

- **Supply Chain Security**: 98/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - No install/post-install scripts declared.
  - 24 of 78 dependencies flagged as unhealthy (1 deprecated).
- **Provenance & Transparency**: 97/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to OrtaMarco/domain-security-mcp-server).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 9 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 70/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 4346 tokens (~228/item across 19 items; 19 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 43/100
  - Stability observed for 13 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 19 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 20 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

## Install

### How do I install the Domain Security MCP server?

Domain Security runs locally as an npm package, launched with npx -y domain-security-mcp-server. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add ortamarco-domain-security-mcp-server -- npx -y domain-security-mcp-server
```

### Cursor

```json
{
  "mcpServers": {
    "ortamarco-domain-security-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "domain-security-mcp-server"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "ortamarco-domain-security-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "domain-security-mcp-server"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add ortamarco-domain-security-mcp-server -- npx -y domain-security-mcp-server
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ortamarco-domain-security-mcp-server": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "domain-security-mcp-server"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ortamarco-domain-security-mcp-server --command npx --arg -y --arg domain-security-mcp-server
```

### Hermes

```yaml
mcp_servers:
  ortamarco-domain-security-mcp-server:
    command: "npx"
    args: ["-y", "domain-security-mcp-server"]
```

### Netclaw

```json
{
  "McpServers": {
    "ortamarco-domain-security-mcp-server": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "domain-security-mcp-server"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add ortamarco-domain-security-mcp-server -t stdio -c npx -a -y domain-security-mcp-server
```

### Other

```json
{
  "mcpServers": {
    "ortamarco-domain-security-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "domain-security-mcp-server"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-09-22 (score 85, +1)

No change was recorded against any check on this day. Stability & Change Management went from 33 to 37. That category is still filling its 30-day observation window: 10 days of observed history at the previous scan, 11 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-20 (score 84, +1)

No change was recorded against any check on this day. Stability & Change Management went from 27 to 30. That category is still filling its 30-day observation window: 8 days of observed history at the previous scan, 9 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-18 (score 83, +1)

No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-16 (score 82, +1)

No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-09-15 (score 81, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-09-14 (score 66, 0)

- [security regression] Malware scan: pass → unverified
- [security improvement] CVE-2026-69192 no longer affects this package
- [security improvement] CVE-2026-42338 no longer affects this package
- [security improvement] Known CVEs: fail → pass
- [security improvement] Provenance: fail → pass
- [security] The attested source repository moved: OrtaMarco/domain-security-mcp-server
- [functional improvement] Stability: unverified → 0.10
- [functional] Package version: 1.2.0 → 1.2.1

### 2026-09-13 (score 66, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-09-11 (score 51)

First indexed and scored.

## MCP tools (19)

### `email_auth_audit` (~441 tokens)

Email Authentication Audit

Headline tool. Audits a domain's email-authentication posture in one call — SPF, DKIM, DMARC and MX — then returns a 0–100 score, an A–F grade and a prioritised list of fixes. Use this first; reach for the per-record tools (spf_check, dmarc_check, dkim_check) only when you need the full detail of one mechanism.

Args:
  \- domain (string): the domain to audit.
  \- dkim_selectors (string[], optional): DKIM selectors to probe. If omitted, common provider selectors are tried (absence is then inconclusive).
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns (JSON):
  {
    "domain": string,
    "grade": "A".."F",
    "score": number,             // 0-100
    "has_mx": boolean,
    "mx_hosts": string[],
    "spf":  { found, record, all_qualifier, lookup_count, exceeds_lookup_limit, findings[] },
    "dmarc":{ found, policy, tags, findings[] },
    "dkim": { any_found, selectors[], findings[] },
    "top_recommendations": string[]
  }

Examples:
  \- "Is example.com protected against email spoofing?" -> email_auth_audit(domain="example.com")
  \- "Audit acme.com, our DKIM selector is 'k1'" -> email_auth_audit(domain="acme.com", dkim_selectors=["k1"])

Errors: returns an error only if the domain is malformed; missing records are reported as findings, not errors.

Input parameters:

- `dkim_selectors` (array): Optional DKIM selectors to check (e.g. ['google','selector1']). If omitted, a list of common provider selectors is probed.
- `domain` (string, required): Domain to audit, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `dkim` (object)
- `dmarc` (object)
- `domain` (string)
- `grade` (string)
- `has_mx` (boolean)
- `mx_hosts` (array)
- `score` (number)
- `spf` (object)
- `top_recommendations` (array)

### `spf_check` (~192 tokens)

SPF Record Check

Fetch and analyse a domain's SPF record. Detects: missing/multiple records, the trailing 'all' qualifier (+all/?all/~all/-all), and counts DNS-querying terms recursively against the RFC 7208 limit of 10.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { found, record, multiple_records, all_qualifier, lookup_count, exceeds_lookup_limit, findings[] }.

Example: "Does sendgrid.net's SPF exceed the 10-lookup limit?" -> spf_check(domain="sendgrid.net").

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `all_qualifier` (string)
- `domain` (string)
- `exceeds_lookup_limit` (boolean)
- `findings` (array)
- `found` (boolean)
- `lookup_count` (number)
- `multiple_records` (boolean)
- `record` (string)

### `dmarc_check` (~182 tokens)

DMARC Record Check

Fetch and parse a domain's DMARC record (_dmarc.<domain>). Reports the policy (p=), subdomain policy (sp=), reporting addresses (rua/ruf), pct and alignment (aspf/adkim), and warns on monitor-only or partial deployments.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { found, record, policy, tags{}, findings[] }.

Example: "What is paypal.com's DMARC policy?" -> dmarc_check(domain="paypal.com").

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `domain` (string)
- `findings` (array)
- `found` (boolean)
- `policy` (string)
- `record` (string)
- `tags` (object)

### `dkim_check` (~280 tokens)

DKIM Record Check

Look up DKIM public keys at <selector>._domainkey.<domain>. Because DKIM selectors are arbitrary and undiscoverable, you should pass the selector(s) your mail provider uses for a definitive answer; otherwise a curated list of common selectors is probed and a miss is inconclusive.

Args:
  \- domain (string): the domain to check.
  \- selectors (string[], optional): DKIM selectors to probe.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { any_found, probed_selectors, selectors[{selector, found, record, key_type}], findings[] }.

Examples:
  \- "Does acme.com publish a DKIM key for selector 'google'?" -> dkim_check(domain="acme.com", selectors=["google"])
  \- "Find any DKIM keys for acme.com" -> dkim_check(domain="acme.com")

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
- `selectors` (array): DKIM selectors to check (e.g. ['google']). If omitted, common provider selectors are probed — absence is then inconclusive.

Output parameters:

- `any_found` (boolean)
- `domain` (string)
- `findings` (array)
- `probed_selectors` (number)
- `selectors` (array)

### `mta_sts_check` (~204 tokens)

MTA-STS Check

Check a domain's MTA-STS deployment: the _mta-sts TXT record AND the policy file at https://mta-sts.<domain>/.well-known/mta-sts.txt. Reports the enforcement mode (enforce/testing/none) and the listed MX hosts. MTA-STS forces TLS for inbound SMTP and blocks downgrade attacks.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { dns_record_found, policy_found, mode, policy{}, findings[] }.

Example: "Does gmail.com enforce MTA-STS?" -> mta_sts_check(domain="gmail.com").

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `dns_record_found` (boolean)
- `domain` (string)
- `findings` (array)
- `mode` (string)
- `policy` (object)
- `policy_found` (boolean)

### `tls_rpt_check` (~155 tokens)

TLS-RPT Check

Check a domain's TLS-RPT record (_smtp._tls.<domain> TXT). TLS-RPT lets you receive reports about TLS delivery failures to your domain.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { found, record, findings[] }.

Example: "Does microsoft.com publish TLS-RPT?" -> tls_rpt_check(domain="microsoft.com").

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `domain` (string)
- `findings` (array)
- `found` (boolean)
- `record` (string)

### `bimi_check` (~168 tokens)

BIMI Check

Check a domain's BIMI record (default._bimi.<domain> TXT), which points to the brand logo (and optional VMC) displayed next to authenticated mail. BIMI requires an enforced DMARC policy to take effect.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { found, record, findings[] }.

Example: "Does cnn.com have BIMI set up?" -> bimi_check(domain="cnn.com").

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `domain` (string)
- `findings` (array)
- `found` (boolean)
- `record` (string)

### `dns_lookup` (~221 tokens)

DNS Lookup

Resolve all common DNS record types (A, AAAA, CNAME, MX, NS, TXT, SOA) for a domain in one call, using public resolvers (Cloudflare/Google/Quad9).

Args:
  \- domain (string): the domain to query, e.g. "example.com".
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: a map of record type -> list of records. Each record has { type, host, value, priority? }.

Examples:
  \- "What are the MX records for stripe.com?" -> dns_lookup(domain="stripe.com")
  \- Use ssl_certificate for TLS details, whois_lookup for registration data.

Errors: returns an error if the domain is malformed or has no resolvable records.

Input parameters:

- `domain` (string, required): Domain to query, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `domain` (string)
- `records` (object)

### `reverse_dns` (~179 tokens)

Reverse DNS (PTR)

Resolve the PTR (reverse DNS) records for an IP address — the hostname(s) the IP maps back to.

Args:
  \- ip (string): IPv4 or IPv6 address.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { ip, hostnames: string[] }.

Example: "What hostname does 8.8.8.8 reverse to?" -> reverse_dns(ip="8.8.8.8").
Errors: returns an error if the IP is invalid or has no PTR record.

Input parameters:

- `ip` (string, required): IPv4 or IPv6 address, e.g. '1.1.1.1'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `hostnames` (array)
- `ip` (string)

### `ip_geolocation` (~248 tokens)

IP Geolocation

Geolocate an IP address (country, region, city, coordinates, time zone) using the offline DB-IP Lite database, plus its reverse-DNS hostname. No external API.

Args:
  \- ip (string): IPv4 or IPv6 address.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { ip, country_iso, country_name, region, city, latitude, longitude, time_zone, hostname }.

Example: "Where is 151.101.1.69 located?" -> ip_geolocation(ip="151.101.1.69").
Note: geolocation is approximate (city-level at best) and offline data may lag reality. The time zone is estimated from the coordinates.
Data: IP Geolocation by DB-IP (https://db-ip.com), licensed CC BY 4.0 — credit it when showing these results.

Input parameters:

- `ip` (string, required): IPv4 or IPv6 address, e.g. '1.1.1.1'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `city` (string)
- `country_iso` (string)
- `country_name` (string)
- `hostname` (string)
- `ip` (string)
- `latitude` (number)
- `longitude` (number)
- `region` (string)
- `time_zone` (string)

### `ssl_certificate` (~242 tokens)

SSL/TLS Certificate Inspector

Inspect the TLS certificate served by a host: issuer, subject, validity window, days-until-expiry, SANs, serial and SHA-256 fingerprint. Flags expired or soon-to-expire certificates.

Args:
  \- domain (string): host to connect to.
  \- port (number): TLS port (default 443).
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: certificate fields plus { days_until_expiry, expired, expires_soon, trusted, hostname_matches, authorization_error }. An untrusted certificate (self-signed, unknown root, wrong host) is still inspected and reported, never silently passed.

Example: "When does github.com's certificate expire?" -> ssl_certificate(domain="github.com").
Errors: returns an error if the host is unreachable or serves no certificate.

Input parameters:

- `domain` (string, required): Domain (or host) to inspect, e.g. 'example.com'.
- `port` (integer): TLS port (default 443).
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `authorization_error` (string)
- `days_until_expiry` (number)
- `expired` (boolean)
- `expires_soon` (boolean)
- `fingerprint_sha256` (string)
- `host` (string)
- `hostname_matches` (boolean)
- `issuer_common_name` (string)
- `issuer_organization` (string)
- `port` (number)
- `serial_number` (string)
- `subject_alt_names` (array)
- `subject_common_name` (string)
- `trusted` (boolean)
- `valid_from` (string)
- `valid_to` (string)

### `whois_lookup` (~221 tokens)

WHOIS Lookup

Look up domain registration data over the raw WHOIS protocol (port 43): registrar, creation/update/expiry dates, name servers and domain status. Resolves the correct WHOIS server via IANA and follows registrar referrals. No API key.

Args:
  \- domain (string): the domain to look up.
  \- response_format ('markdown' | 'json'): output format (default 'markdown'). JSON includes the raw WHOIS text.

Returns: { domain, registrar, created, updated, expires, name_servers[], status[], whois_server }.

Example: "Who is the registrar for openai.com and when does it expire?" -> whois_lookup(domain="openai.com").
Errors: returns an error if no WHOIS server answers (some ccTLDs restrict or rate-limit WHOIS).

Input parameters:

- `domain` (string, required): Domain to look up, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `created` (string)
- `domain` (string)
- `expires` (string)
- `name_servers` (array)
- `raw` (string)
- `registrant_org` (string)
- `registrar` (string)
- `status` (array)
- `updated` (string)
- `whois_server` (string)

### `http_security_headers` (~239 tokens)

HTTP Security Headers

Fetch a URL and grade its HTTP security headers (HSTS, Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, COOP). Returns a 0–100 score, an A–F grade, and per-header notes.

Args:
  \- url (string): URL or host to check (scheme defaults to https://).
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { url, final_url, status, grade, score, checks[{header, present, value, note}], missing[] }.

Example: "Grade the security headers on https://news.ycombinator.com" -> http_security_headers(url="https://news.ycombinator.com").
Errors: returns an error if the URL is invalid or the host is unreachable.

Input parameters:

- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
- `url` (string, required): URL or host to check, e.g. 'https://example.com'.

Output parameters:

- `checks` (array)
- `final_url` (string)
- `grade` (string)
- `missing` (array)
- `score` (number)
- `status` (number)
- `url` (string)

### `dnssec_check` (~170 tokens)

DNSSEC Check

Check whether a domain is protected by DNSSEC. Queries DS and DNSKEY records over DNS-over-HTTPS and reads the resolver's Authenticated Data (AD) flag to confirm the chain of trust validates.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { enabled, validated, ds_records, dnskey_records, findings[] }.

Example: "Is cloudflare.com DNSSEC-signed?" -> dnssec_check(domain="cloudflare.com").

Input parameters:

- `domain` (string, required): Domain to check, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `dnskey_records` (number)
- `domain` (string)
- `ds_records` (number)
- `enabled` (boolean)
- `findings` (array)
- `validated` (boolean)

### `caa_check` (~161 tokens)

CAA Record Check

Check a domain's CAA (Certification Authority Authorization) records — which CAs are allowed to issue TLS certificates for it. Absence means any CA may issue.

Args:
  \- domain (string): the domain to check.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { found, issue[], issuewild[], iodef[] }.

Example: "Which CAs can issue certs for google.com?" -> caa_check(domain="google.com").

Input parameters:

- `domain` (string, required): Domain to query, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `domain` (string)
- `found` (boolean)
- `iodef` (array)
- `issue` (array)
- `issuewild` (array)

### `mx_lookup` (~142 tokens)

MX Lookup

Look up a domain's mail servers (MX records) with priority and the IPs they resolve to.

Args:
  \- domain (string): the domain to query.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: array of { exchange, priority, ips[] }.

Example: "What are the mail servers for github.com?" -> mx_lookup(domain="github.com").

Input parameters:

- `domain` (string, required): Domain to query, e.g. 'example.com'.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `domain` (string)
- `records` (array)

### `blacklist_check` (~232 tokens)

DNSBL Blacklist Check

Check whether an IPv4 address (or a domain's A records) appears on email DNS blocklists (DNSBLs). Only open-access lists are queried (SpamCop, UCEPROTECT-1, DroneBL, s5h); Spamhaus and Barracuda refuse public-resolver queries and are excluded.

Args:
  \- query (string): an IPv4 address or a domain.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { ips[], listedCount, checked, results[{ip, hits[{list, listed, reason, error}]}], note }. A list that did not answer carries an `error` and is not counted as clean.

Example: "Is 203.0.113.5 blacklisted?" -> blacklist_check(query="203.0.113.5").

Input parameters:

- `query` (string, required): An IPv4 address or a domain to check against DNSBLs.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `checked` (number)
- `ips` (array)
- `listedCount` (number)
- `note` (string)
- `query` (string)
- `results` (array)

### `dns_propagation` (~202 tokens)

DNS Propagation Check

Compare a domain's DNS records across multiple public resolvers worldwide (Cloudflare, Google, Quad9, OpenDNS, AdGuard) to see whether a change has propagated.

Args:
  \- domain (string): the domain to check.
  \- type ('A'|'AAAA'|'CNAME'|'MX'|'NS'|'TXT'): record type (default 'A').
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { type, consistent, resolvers[{name, server, values[], error}] }.

Example: "Has the A record for example.com propagated?" -> dns_propagation(domain="example.com").

Input parameters:

- `domain` (string, required): Domain to check.
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.
- `type` (string): Record type (default 'A').

Output parameters:

- `consistent` (boolean)
- `domain` (string)
- `resolvers` (array)
- `type` (string)

### `analyze_email_headers` (~194 tokens)

Email Header Analyzer

Parse raw email headers and report the SPF/DKIM/DMARC verdicts (from Authentication-Results), key fields (From, Subject, Date, Message-ID, Return-Path) and the Received hop chain with per-hop delays and total transit time.

Args:
  \- headers (string): the raw email headers.
  \- response_format ('markdown' | 'json'): output format (default 'markdown').

Returns: { auth{spf,dkim,dmarc}, fields{}, hops[{index,from,by,date,delaySec}], totalSec }.

Example: paste the headers from "Show original" in Gmail to trace a message's path and authentication.

Input parameters:

- `headers` (string, required): The raw email headers to analyze (RFC 5322).
- `response_format` (string): Output format: 'markdown' for a human-readable summary (default) or 'json' for the full structured payload.

Output parameters:

- `auth` (object)
- `fields` (object)
- `hops` (array)
- `totalSec` (number|null)

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/ortamarco-domain-security-mcp-server/domain-security-mcp-server#diagnostics

## Score history

- 2026-09-24: 85
- 2026-09-23: 85
- 2026-09-22: 85
- 2026-09-21: 84
- 2026-09-20: 84
- 2026-09-19: 83
- 2026-09-18: 83
- 2026-09-17: 82
- 2026-09-16: 82
- 2026-09-15: 81
- 2026-09-14: 66
- 2026-09-13: 66
- 2026-09-12: 51
- 2026-09-11: 51

## Common questions

### What is the Domain Security MCP server?

Domain Security is an MCP server listed in the public MCP registry as io.github.OrtaMarco/domain-security-mcp-server. Audit a domain's email and web security: SPF, DKIM, DMARC, MTA-STS, DNSSEC, TLS, WHOIS. No API keys. This page covers its npm package (domain-security-mcp-server).

### Is the Domain Security MCP server safe to use?

Domain Security scores 85 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 24 September 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Domain Security MCP server expose?

Domain Security exposes 19 tools: email_auth_audit, spf_check, dmarc_check, dkim_check, mta_sts_check, and 14 more. Their descriptions and schemas cost roughly 4,073 tokens of context every time the server is loaded.

### Is the Domain Security MCP server still maintained?

Domain Security is still listed as active in the MCP registry. We last reached this channel on 24 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the Domain Security MCP server under?

Domain Security declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- npm package: https://www.npmjs.com/package/domain-security-mcp-server
- Socket report: https://socket.dev/npm/package/domain-security-mcp-server
- Repository: https://github.com/OrtaMarco/domain-security-mcp-server
- Changelog RSS feed: https://verifymcp.io/servers/ortamarco-domain-security-mcp-server/domain-security-mcp-server.xml
- Changelog JSON feed: https://verifymcp.io/servers/ortamarco-domain-security-mcp-server/domain-security-mcp-server.json
- HTML version of this page: https://verifymcp.io/servers/ortamarco-domain-security-mcp-server/domain-security-mcp-server
