@dnsdoctor/mcp 1.2.0 → 1.3.0
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 +5 -3
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/instructions.txt +1 -1
- package/package.json +2 -2
- package/tools.json +88 -2
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DNS Doctor — Claude Code plugin
|
|
1
|
+
# DNS Doctor — Claude Code plugin & DNS skill (DMARC, SPF, DKIM)
|
|
2
2
|
|
|
3
3
|
Diagnose and fix a domain's email authentication (SPF, DMARC, DKIM, MX, blacklist,
|
|
4
4
|
domain/SSL expiry) from inside Claude. This plugin bundles the DNS Doctor **skill**
|
|
@@ -18,7 +18,7 @@ claude-plugin/
|
|
|
18
18
|
├── .mcp.json # MCP server: https://dnsdoctor.dev/mcp (HTTP)
|
|
19
19
|
├── skills/dns-doctor/SKILL.md # the scan → diagnose → fix workflow
|
|
20
20
|
├── src/ # @dnsdoctor/mcp — the local stdio MCP server
|
|
21
|
-
├── tools.json # the
|
|
21
|
+
├── tools.json # the 13 tool definitions (generated, never hand-edited)
|
|
22
22
|
├── instructions.txt # the server's own `initialize` guidance (generated)
|
|
23
23
|
├── tests/ # vitest suite for the stdio server
|
|
24
24
|
├── package.json tsconfig.json # npm package + build
|
|
@@ -40,6 +40,8 @@ claude-plugin/
|
|
|
40
40
|
| `parse_dmarc_report` | Parse an aggregate (RUA) report file into rows. |
|
|
41
41
|
| `check_record` | Read any DNS record type for a name. |
|
|
42
42
|
| `check_reverse_dns` | PTR / forward-confirmed reverse DNS for an IP. |
|
|
43
|
+
| `audit_spf_includes` | The SPF include/redirect tree — who can transitively send as the domain, with typed findings (broken include, confirmed-unregistered include, expiring registration, nested `+all`). Analysis only; no SPF fix record. |
|
|
44
|
+
| `build_parked_domain_records` | The Null MX + `v=spf1 -all` + `p=reject; np=reject` hardening pack for a domain that sends no mail. The server re-checks DNS itself and refuses when it finds evidence of mail. |
|
|
43
45
|
| `start_monitoring_signup` | A sign-up link to hand to the human who owns the domain. Sends no email and creates nothing — they open it, sign in on our page themselves (a social provider or an emailed link, whichever that deployment offers), and the domain is carried over to their dashboard already filled in; monitoring starts once they verify it with a TXT record. |
|
|
44
46
|
|
|
45
47
|
Over the hosted HTTP transport the `dnsdoctor://domains` resource (your
|
|
@@ -101,7 +103,7 @@ latest per-check statuses).
|
|
|
101
103
|
|
|
102
104
|
### Transport
|
|
103
105
|
|
|
104
|
-
Two supported public transports, same
|
|
106
|
+
Two supported public transports, same 13 tools:
|
|
105
107
|
|
|
106
108
|
- **Hosted streamable HTTP** — `https://dnsdoctor.dev/mcp`, wired in this
|
|
107
109
|
plugin's `.mcp.json`. No install, no keys.
|
package/dist/index.js
CHANGED
|
@@ -34,6 +34,11 @@ const ROUTES = {
|
|
|
34
34
|
},
|
|
35
35
|
check_record: { kind: "json", path: "/api/tools/check-record" },
|
|
36
36
|
check_reverse_dns: { kind: "json", path: "/api/tools/reverse-dns-check" },
|
|
37
|
+
audit_spf_includes: { kind: "json", path: "/api/tools/spf-audit" },
|
|
38
|
+
build_parked_domain_records: {
|
|
39
|
+
kind: "json",
|
|
40
|
+
path: "/api/tools/parked-domain-records",
|
|
41
|
+
},
|
|
37
42
|
};
|
|
38
43
|
/** Default upload name when the caller supplies none — the API only reads bytes. */
|
|
39
44
|
const DEFAULT_REPORT_FILENAME = "report.xml";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GAEvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAmBhE,MAAM,MAAM,GAA0B;IACpC,WAAW,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE;IACnD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;IAC9B,mBAAmB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,EAAE;IACpE,uBAAuB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,oBAAoB,EAAE;IACrE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,EAAE;IACjE,qBAAqB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAC1E,qBAAqB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,2BAA2B,EAAE;IAC1E,mBAAmB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,uBAAuB,EAAE;IACpE,kBAAkB,EAAE;QAClB,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,+BAA+B;QACrC,KAAK,EAAE,MAAM;KACd;IACD,YAAY,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,EAAE;IAC/D,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,EAAE;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/instructions.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
DNS Doctor scans a domain's email-authentication posture (SPF, DMARC, DKIM, MX, DNS, blacklist, expiry) and returns deterministic verdicts plus copy-paste fix records generated by a validating engine — never a guessed record. Workflow: call scan_domain (or get_report), read the verdicts failing-first (a 'temperror' status is transient, NOT a failure), then call build_dmarc_upgrade for a DMARC enforcement record. ONE EXCEPTION TO READING FAILING-FIRST: when a report carries not_registered: true the domain has no DNS records at all, so no check ran and every status is an 'info' placeholder — zero failing checks there does NOT mean the domain is healthy. Report that the domain does not resolve (usually a typo), propose no records for it, and do not offer monitoring until it resolves. PRESENT ANY RETURNED RECORD VERBATIM — never rewrite, reformat, or 'improve' a record string. build_dmarc_upgrade may return record: null (the domain does not exist; the DMARC lookup itself hit NXDOMAIN while the existence probe did not resolve; the DMARC lookup temp-failed; or the domain already applies a policy at least as strong as the one this scan justifies) — relay its 'rationale' as the answer and NEVER compose a record yourself to fill the gap. 'policy' describes the returned record and is null whenever record is; the domain's observed policy is in 'current_policy'. A human must approve every DNS change; nothing is applied automatically. SPF is diagnose-only: relay the report's SPF findings, but never propose SPF record edits of your own (e.g. tightening ~all to -all) — an SPF change can silently de-authorize a real sender, which is why the engine emits no SPF fix record. Scan responses end with a next_steps block: relay it — safe DMARC enforcement needs ~30 days of aggregate-report (RUA) evidence that no chat session can watch, so when a domain lacks reporting, call start_monitoring_signup and give the human the signup_url it returns. That tool sends no email and creates nothing: the human opens the link, signs in themselves, and adds the domain themselves. Never ask a human for their email address to pass to us, and never invent one — hand over the link and let them sign in on our page. Also share the report_url and monitor_url links from next_steps.
|
|
1
|
+
DNS Doctor scans a domain's email-authentication posture (SPF, DMARC, DKIM, MX, DNS, blacklist, expiry) and returns deterministic verdicts plus copy-paste fix records generated by a validating engine — never a guessed record. Workflow: call scan_domain (or get_report), read the verdicts failing-first (a 'temperror' status is transient, NOT a failure), then call build_dmarc_upgrade for a DMARC enforcement record. ONE EXCEPTION TO READING FAILING-FIRST: when a report carries not_registered: true the domain has no DNS records at all, so no check ran and every status is an 'info' placeholder — zero failing checks there does NOT mean the domain is healthy. Report that the domain does not resolve (usually a typo), propose no records for it, and do not offer monitoring until it resolves. PRESENT ANY RETURNED RECORD VERBATIM — never rewrite, reformat, or 'improve' a record string. build_dmarc_upgrade may return record: null (the domain does not exist; the DMARC lookup itself hit NXDOMAIN while the existence probe did not resolve; the DMARC lookup temp-failed; or the domain already applies a policy at least as strong as the one this scan justifies) — relay its 'rationale' as the answer and NEVER compose a record yourself to fill the gap. 'policy' describes the returned record and is null whenever record is; the domain's observed policy is in 'current_policy'. A human must approve every DNS change; nothing is applied automatically. SPF is diagnose-only: relay the report's SPF findings, but never propose SPF record edits of your own (e.g. tightening ~all to -all) — an SPF change can silently de-authorize a real sender, which is why the engine emits no SPF fix record. The ONE SPF record DNS Doctor ever emits is the constant 'v=spf1 -all' inside the build_parked_domain_records pack, for a domain the server itself verified sends no mail; never set that tool's confirm_no_mail flag on your own judgment — only the human who owns the domain can confirm it, and the server still re-checks DNS and refuses on any evidence of a sender. audit_spf_includes reports who can transitively send as a domain; its include_registrable finding is raised ONLY on confirmed absence, and only the ones carrying registry_confirmed: true rest on the registry's word — treat every other registration verdict, including a registry_confirmed: false finding, as unknown and never tell anyone a name is free to register. Scan responses end with a next_steps block: relay it — safe DMARC enforcement needs ~30 days of aggregate-report (RUA) evidence that no chat session can watch, so when a domain lacks reporting, call start_monitoring_signup and give the human the signup_url it returns. That tool sends no email and creates nothing: the human opens the link, signs in themselves, and adds the domain themselves. Never ask a human for their email address to pass to us, and never invent one — hand over the link and let them sign in on our page. Also share the report_url and monitor_url links from next_steps.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dnsdoctor/mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Thin stdio MCP server for DNS Doctor
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "Thin stdio MCP server for DNS Doctor \u2014 diagnoses SPF, DMARC, DKIM, MX, DNS, blacklist and expiry over the public DNS Doctor REST API.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "DNS Doctor",
|
package/tools.json
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"annotations": {
|
|
4
|
+
"destructiveHint": false,
|
|
5
|
+
"idempotentHint": true,
|
|
6
|
+
"openWorldHint": true,
|
|
7
|
+
"readOnlyHint": true
|
|
8
|
+
},
|
|
9
|
+
"description": "Audit a domain's SPF supply chain: walks every include and redirect it delegates to, and reports who can transitively send as it. Returns the resolved tree, per-node lookup attribution, the total authorized IPv4 address count, and typed findings \u2014 include_broken (a target that no longer publishes SPF, a PermError today), include_registrable (a delegated-to domain that does not exist, so a stranger who registers it becomes an authorized sender), include_expiring (registration lapsing within 30 days), pass_all_nested (a +all deep in the chain) and spf_record_unusable (the audited domain's OWN record is missing or does not parse, so there is no chain to walk). A domain we could not verify is reported as unverified and NEVER as available \u2014 never tell anyone a name is free on this tool's say-so unless the finding is include_registrable AND carries registry_confirmed: true. A registry_confirmed: false finding rests on DNS alone, which cannot tell an unsold name from one in redemption or on clientHold: report the mechanism as broken and the takeover risk as possible, but never as an available domain. Findings are risk analysis, not instructions: no SPF fix record exists here or anywhere else in DNS Doctor, because dropping a mechanism can silently de-authorize a real sender \u2014 relay the findings and let the domain's owner decide. Use count_spf_lookups instead when the question is only the 10-lookup limit.",
|
|
10
|
+
"inputSchema": {
|
|
11
|
+
"properties": {
|
|
12
|
+
"domain": {
|
|
13
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
14
|
+
"title": "Domain",
|
|
15
|
+
"type": "string"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"required": [
|
|
19
|
+
"domain"
|
|
20
|
+
],
|
|
21
|
+
"title": "audit_spf_includesArguments",
|
|
22
|
+
"type": "object"
|
|
23
|
+
},
|
|
24
|
+
"name": "audit_spf_includes"
|
|
25
|
+
},
|
|
2
26
|
{
|
|
3
27
|
"annotations": {
|
|
4
28
|
"destructiveHint": false,
|
|
@@ -6,10 +30,11 @@
|
|
|
6
30
|
"openWorldHint": true,
|
|
7
31
|
"readOnlyHint": false
|
|
8
32
|
},
|
|
9
|
-
"description": "Return a validated DMARC enforcement-upgrade record for a domain. The alignment gate (whether p=reject is safe) is derived server-side from a scan \u2014 a caller can never assert alignment. `record` is null when there is no honest upgrade to offer (the domain does not exist; the DMARC lookup itself hit NXDOMAIN while the existence probe did not resolve; the DMARC lookup temp-failed; or the domain already applies a policy at least as strong as this scan justifies): relay `rationale` and never compose a record to fill the gap. Present a returned record verbatim; a human must approve before publishing.",
|
|
33
|
+
"description": "Return a validated DMARC enforcement-upgrade record for a domain. The alignment gate (whether p=reject is safe) is derived server-side from a scan \u2014 a caller can never assert alignment. `record` is null when there is no honest upgrade to offer (the domain does not exist; the DMARC lookup itself hit NXDOMAIN while the existence probe did not resolve; the DMARC lookup temp-failed; or the domain already applies a policy at least as strong as this scan justifies): relay `rationale` and never compose a record to fill the gap. A returned record also carries np=reject (the DMARCbis tag covering non-existent subdomains, which can have no legitimate aligned mail) unless the domain already publishes an np tag, which is preserved as-is. Present a returned record verbatim; a human must approve before publishing.",
|
|
10
34
|
"inputSchema": {
|
|
11
35
|
"properties": {
|
|
12
36
|
"domain": {
|
|
37
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
13
38
|
"title": "Domain",
|
|
14
39
|
"type": "string"
|
|
15
40
|
}
|
|
@@ -22,6 +47,49 @@
|
|
|
22
47
|
},
|
|
23
48
|
"name": "build_dmarc_upgrade"
|
|
24
49
|
},
|
|
50
|
+
{
|
|
51
|
+
"annotations": {
|
|
52
|
+
"destructiveHint": false,
|
|
53
|
+
"idempotentHint": true,
|
|
54
|
+
"openWorldHint": true,
|
|
55
|
+
"readOnlyHint": true
|
|
56
|
+
},
|
|
57
|
+
"description": "Build the three-record hardening pack that makes a NON-SENDING domain unusable for spoofing: a Null MX, a hard-fail SPF record, and a p=reject; np=reject DMARC record. For parked, redirect and brand-defensive domains only \u2014 NEVER for a domain that sends any mail, including transactional or one legacy system. Do NOT set confirm_no_mail on your own judgment or because a scan looked quiet: only the human who owns the domain can confirm it sends nothing, so ask them first. That flag unlocks the question, not the answer \u2014 the server re-checks DNS itself (existence, MX, SPF, DKIM selectors) and returns records: null with a rationale when it finds evidence of mail; relay that rationale rather than retrying. A lookup failure is reported as a failure, never as a pack. Publishing is the human's decision: present the records verbatim, in the order given, and let them approve each one.",
|
|
58
|
+
"inputSchema": {
|
|
59
|
+
"properties": {
|
|
60
|
+
"confirm_no_mail": {
|
|
61
|
+
"description": "Must be true, and only the HUMAN who owns the domain may decide it: it records their confirmation that this domain sends no email at all. Never set it on your own judgment or because a scan looked quiet \u2014 ask them. It unlocks the question only; the server independently re-checks DNS for evidence of mail and refuses when it finds any.",
|
|
62
|
+
"title": "Confirm No Mail",
|
|
63
|
+
"type": "boolean"
|
|
64
|
+
},
|
|
65
|
+
"domain": {
|
|
66
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
67
|
+
"title": "Domain",
|
|
68
|
+
"type": "string"
|
|
69
|
+
},
|
|
70
|
+
"rua_email": {
|
|
71
|
+
"anyOf": [
|
|
72
|
+
{
|
|
73
|
+
"type": "string"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"type": "null"
|
|
77
|
+
}
|
|
78
|
+
],
|
|
79
|
+
"default": null,
|
|
80
|
+
"description": "Mailbox to receive DMARC aggregate (RUA) reports, as a plain address like dmarc@example.com. Strongly recommended: without it nobody can see who sends as the domain.",
|
|
81
|
+
"title": "Rua Email"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"required": [
|
|
85
|
+
"domain",
|
|
86
|
+
"confirm_no_mail"
|
|
87
|
+
],
|
|
88
|
+
"title": "build_parked_domain_recordsArguments",
|
|
89
|
+
"type": "object"
|
|
90
|
+
},
|
|
91
|
+
"name": "build_parked_domain_records"
|
|
92
|
+
},
|
|
25
93
|
{
|
|
26
94
|
"annotations": {
|
|
27
95
|
"destructiveHint": false,
|
|
@@ -33,10 +101,12 @@
|
|
|
33
101
|
"inputSchema": {
|
|
34
102
|
"properties": {
|
|
35
103
|
"domain": {
|
|
104
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
36
105
|
"title": "Domain",
|
|
37
106
|
"type": "string"
|
|
38
107
|
},
|
|
39
108
|
"selector": {
|
|
109
|
+
"description": "The DKIM selector to probe \u2014 the name before ._domainkey, e.g. 'google', 'selector1', or a dotted form like 's1.prod'. The sending platform's settings page names it; it is not guessable from the domain.",
|
|
40
110
|
"title": "Selector",
|
|
41
111
|
"type": "string"
|
|
42
112
|
}
|
|
@@ -61,6 +131,7 @@
|
|
|
61
131
|
"inputSchema": {
|
|
62
132
|
"properties": {
|
|
63
133
|
"domain": {
|
|
134
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
64
135
|
"title": "Domain",
|
|
65
136
|
"type": "string"
|
|
66
137
|
},
|
|
@@ -74,9 +145,11 @@
|
|
|
74
145
|
}
|
|
75
146
|
],
|
|
76
147
|
"default": null,
|
|
148
|
+
"description": "Optional label to prepend to the domain (e.g. 'mail' to check mail.<domain>) \u2014 honored for txt, cname, a and aaaa only; spf, dmarc and mx derive their own query name.",
|
|
77
149
|
"title": "Host"
|
|
78
150
|
},
|
|
79
151
|
"kind": {
|
|
152
|
+
"description": "Which record to read; the right query is derived from it \u2014 'dmarc' reads TXT at _dmarc.<domain> filtered to v=DMARC1, 'spf' reads the apex TXT filtered to v=spf1, so don't prefix the domain yourself.",
|
|
80
153
|
"enum": [
|
|
81
154
|
"spf",
|
|
82
155
|
"dmarc",
|
|
@@ -110,6 +183,7 @@
|
|
|
110
183
|
"inputSchema": {
|
|
111
184
|
"properties": {
|
|
112
185
|
"ip": {
|
|
186
|
+
"description": "The sending IP to check, IPv4 or IPv6. Must be a public address \u2014 private, loopback and CGNAT ranges have no meaningful reverse DNS and are refused.",
|
|
113
187
|
"title": "Ip",
|
|
114
188
|
"type": "string"
|
|
115
189
|
}
|
|
@@ -142,6 +216,7 @@
|
|
|
142
216
|
}
|
|
143
217
|
],
|
|
144
218
|
"default": null,
|
|
219
|
+
"description": "Domain whose PUBLISHED SPF record should be resolved and counted recursively (nested includes cost lookups too). Pass exactly one of domain or record, never both.",
|
|
145
220
|
"title": "Domain"
|
|
146
221
|
},
|
|
147
222
|
"record": {
|
|
@@ -154,6 +229,7 @@
|
|
|
154
229
|
}
|
|
155
230
|
],
|
|
156
231
|
"default": null,
|
|
232
|
+
"description": "A pasted SPF record to parse instead of resolving one, e.g. 'v=spf1 include:_spf.google.com ~all'. Counts this record's own terms only. Pass exactly one of domain or record, never both.",
|
|
157
233
|
"title": "Record"
|
|
158
234
|
}
|
|
159
235
|
},
|
|
@@ -169,10 +245,11 @@
|
|
|
169
245
|
"openWorldHint": false,
|
|
170
246
|
"readOnlyHint": true
|
|
171
247
|
},
|
|
172
|
-
"description": "Build a DMARC record from scratch for a domain that has none, using a validating engine \u2014 never compose one yourself. `policy` is none|quarantine|reject; optional `rua_email` (aggregate-report destination), `subdomain_policy`, and `strict_alignment`. The generated record is re-validated before it is returned. Present it verbatim; a human must approve before publishing.",
|
|
248
|
+
"description": "Build a DMARC record from scratch for a domain that has none, using a validating engine \u2014 never compose one yourself. `policy` is none|quarantine|reject; optional `rua_email` (aggregate-report destination), `subdomain_policy`, and `strict_alignment`. Every generated record carries np=reject \u2014 the DMARCbis tag for non-existent subdomains, which can have no legitimate aligned mail \u2014 independently of the p= you choose. The generated record is re-validated before it is returned. Present it verbatim; a human must approve before publishing.",
|
|
173
249
|
"inputSchema": {
|
|
174
250
|
"properties": {
|
|
175
251
|
"policy": {
|
|
252
|
+
"description": "The requested p= policy: 'none' monitors only, 'quarantine' sends failing mail to spam, 'reject' refuses it outright. Start at 'none' unless the domain's aggregate reports already justify enforcement.",
|
|
176
253
|
"enum": [
|
|
177
254
|
"none",
|
|
178
255
|
"quarantine",
|
|
@@ -191,10 +268,12 @@
|
|
|
191
268
|
}
|
|
192
269
|
],
|
|
193
270
|
"default": null,
|
|
271
|
+
"description": "Mailbox to receive DMARC aggregate (RUA) reports, as a plain address like dmarc@example.com. Strongly recommended: without it nobody can see who sends as the domain.",
|
|
194
272
|
"title": "Rua Email"
|
|
195
273
|
},
|
|
196
274
|
"strict_alignment": {
|
|
197
275
|
"default": false,
|
|
276
|
+
"description": "Set true to emit strict alignment (aspf=s adkim=s), requiring an exact domain match instead of the organizational-domain match. Leave false unless you know every sender aligns strictly.",
|
|
198
277
|
"title": "Strict Alignment",
|
|
199
278
|
"type": "boolean"
|
|
200
279
|
},
|
|
@@ -213,6 +292,7 @@
|
|
|
213
292
|
}
|
|
214
293
|
],
|
|
215
294
|
"default": null,
|
|
295
|
+
"description": "Optional sp= policy for subdomains when it should differ from the main p= policy. Omit to let subdomains inherit p=.",
|
|
216
296
|
"title": "Subdomain Policy"
|
|
217
297
|
}
|
|
218
298
|
},
|
|
@@ -235,6 +315,7 @@
|
|
|
235
315
|
"inputSchema": {
|
|
236
316
|
"properties": {
|
|
237
317
|
"domain": {
|
|
318
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
238
319
|
"title": "Domain",
|
|
239
320
|
"type": "string"
|
|
240
321
|
}
|
|
@@ -258,6 +339,7 @@
|
|
|
258
339
|
"inputSchema": {
|
|
259
340
|
"properties": {
|
|
260
341
|
"content_base64": {
|
|
342
|
+
"description": "One DMARC aggregate (RUA) report file, base64-encoded: the .xml, .xml.gz or .zip attachment exactly as received, up to 2 MiB decoded. Encode the file bytes \u2014 do not paste raw XML here.",
|
|
261
343
|
"title": "Content Base64",
|
|
262
344
|
"type": "string"
|
|
263
345
|
},
|
|
@@ -271,6 +353,7 @@
|
|
|
271
353
|
}
|
|
272
354
|
],
|
|
273
355
|
"default": null,
|
|
356
|
+
"description": "Optional original attachment filename, recorded in logs only \u2014 format detection is content-based, so this changes nothing about parsing.",
|
|
274
357
|
"title": "Filename"
|
|
275
358
|
}
|
|
276
359
|
},
|
|
@@ -293,6 +376,7 @@
|
|
|
293
376
|
"inputSchema": {
|
|
294
377
|
"properties": {
|
|
295
378
|
"domain": {
|
|
379
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
296
380
|
"title": "Domain",
|
|
297
381
|
"type": "string"
|
|
298
382
|
}
|
|
@@ -316,6 +400,7 @@
|
|
|
316
400
|
"inputSchema": {
|
|
317
401
|
"properties": {
|
|
318
402
|
"domain": {
|
|
403
|
+
"description": "The domain to check, e.g. example.com. Bare registrable names and subdomains both work; scheme, path or port do not belong here. Unicode names are accepted and normalized to punycode.",
|
|
319
404
|
"title": "Domain",
|
|
320
405
|
"type": "string"
|
|
321
406
|
}
|
|
@@ -339,6 +424,7 @@
|
|
|
339
424
|
"inputSchema": {
|
|
340
425
|
"properties": {
|
|
341
426
|
"record": {
|
|
427
|
+
"description": "The DMARC record text to validate, e.g. 'v=DMARC1; p=none; rua=mailto:reports@example.com'. The record value only \u2014 not the _dmarc hostname it is published at.",
|
|
342
428
|
"title": "Record",
|
|
343
429
|
"type": "string"
|
|
344
430
|
}
|