Content Error or Suggest an Edit
Notice a grammatical error or technical inaccuracy? Let us know; we will give you credit!
Introduction
⚡ Short on time? The key facts and fixes are in the TL;DR.
We wanted our AI agents to read DMARC data straight from DMARC Report: compliance summaries, failing senders, BIMI status, the lot. We run a self-hosted MCPHub that every device connects to, and MCPHub can turn any OpenAPI spec into MCP tools. So the only question was whether DMARC Report publishes one.
It does, sort of. There’s no link to it anywhere in the docs, it’s Swagger 2.0 rather than OpenAPI 3, and it points at localhost:3000. This is how we found it, what was wrong with it, and the cleaned-up spec and MCPHub config you can download and use.
TL;DR
- What: DMARC Report’s API docs are generated by Apipie, which also serves a Swagger file at
https://docs.dmarcreport.com/api/2.0.json?type=swagger. The docs don’t link to it. - Don’t: paste that URL into MCPHub. It’s Swagger 2.0 (MCPHub wants OpenAPI 3.x), its server is
localhost:3000, and it defines no auth. - Fix: use our cleaned OpenAPI 3.0.3 spec: 50 operations, real server URL, a
TokenAuthscheme and short tool names. - Auth: MCPHub’s
apiKeysecurity, headerAuthorization, valueToken token=YOUR_TOKEN. Bearer won’t work. - Check: 13 of the 50 tools create, update or delete things. Give the token read-only privileges or switch those tools off in MCPHub.
The Problem: No Spec in the Docs
The DMARC Report API docs list every resource (accounts, aggregate reports, alerts, BIMI status, domains, forensic reports, MTA-STS reports and more) under /api/2.0, with the API itself at https://api.dmarcreport.com. What they don’t have is a “Download OpenAPI” link, a Swagger UI, or any mention of a spec file.
Without a spec you’re left writing an MCP server by hand, or pointing an agent at HTML docs and hoping. Neither is great for 50 endpoints.
The docs page embeds its content as JSON, and the field names give the generator away: short_description, full_description, validators like "Must be a String", and Ransack-style search params (q[org_name_eq]). That’s Apipie, the Ruby on Rails API docs gem.
Apipie can serve Swagger output from the same docs route if you ask for it, so we tried the usual address:
curl -s "https://docs.dmarcreport.com/api/2.0.json?type=swagger" -o dmarcreport-swagger2.json
It came back with a 70 KB Swagger 2.0 document: 45 paths, 50 operations, every operation with an operationId. If you run into another Rails API with Apipie-style docs, the same ?type=swagger trick is worth a try.
What’s Wrong With the Raw Spec
MCPHub’s OpenAPI server type only supports OpenAPI 3.x, so Swagger 2.0 was the first blocker. Converting it is easy. The rest needed hand fixes:
- Wrong server.
hostislocalhost:3000andbasePathis the full URLhttps://api.dmarcreport.com. A straight conversion gives you a server MCPHub would call on its own localhost. - No auth.
securityDefinitionsis empty. The only description of auth is prose: sendAuthorization: Token token=<token>. That’s the Rails token format, not Bearer and not Basic. - A token in the docs. The auth example contains a real-looking 61-character token. We stripped it.
- Tool names MCP clients reject. operationIds like
post_v2_accounts.jsoncontain dots, and some run past 80 characters. Claude and most MCP clients only accept tool names of up to 64 letters, digits, underscores and hyphens. - Broken types. Boolean fields are
type: stringwith enums like[true, false, "true", "false"],dmarc_compliance_eqis a string with integer enum values, andpage/per/limitare strings. - Form fields as flat names. Request bodies are
formDatafields such asdomain[mta_sts_policy][mode], which make awkward tool inputs. - No success responses. Only 401/403/404/500 are defined, and descriptions are raw HTML.
Converting and Cleaning It
npx swagger2openapi handles the format change, but it can’t fix the server, auth or types. We wrote a small Python converter instead, so every fix is repeatable when DMARC Report updates their docs. It:
- Outputs OpenAPI 3.0.3 with
serversset tohttps://api.dmarcreport.com. - Adds a
TokenAuthscheme:apiKeyin theAuthorizationheader. - Renames all 50 operations to short names like
get_account_compliance_summary,get_alignment_failures,get_bimi_statusandgenerate_dmarc_record(34 characters at most). - Turns bracketed form fields into nested JSON request bodies (
{"domain": {"address": "...", "mta_sts_policy": {...}}}). - Fixes types: true/false enums become booleans, IDs and paging become integers, and IDs that accept slugs stay strings.
- Converts the HTML descriptions to Markdown, restores the bullet lists Apipie flattened, and fixes typos like “Aggregte”.
- Adds generic JSON 200 responses (and a binary PDF response for the audit report endpoint).
The output passes openapi-spec-validator, and a scan confirmed the sample token is gone.
Download the Spec
This is an unofficial conversion. We’re not affiliated with DMARC Report, and the source spec is theirs.
Adding It to MCPHub
Create an API token in DMARC Report first: profile icon, API Tokens, New Api Token, pick its privileges and save. Then add an OpenAPI server in MCPHub, either in the dashboard (server type OpenAPI, paste the spec URL, security API Key) or in mcp_settings.json:
{
"mcpServers": {
"dmarcreport": {
"type": "openapi",
"openapi": {
"url": "https://raw.githubusercontent.com/managingwp/openapi-specs/main/specs/dmarcreport/openapi.json",
"version": "3.0.3",
"security": {
"type": "apiKey",
"apiKey": {
"name": "Authorization",
"in": "header",
"value": "Token token=YOUR_DMARC_REPORT_API_TOKEN"
}
}
},
"headers": {
"Accept": "application/json"
}
}
}
}
The value has to include the Token token= prefix. MCPHub’s http/bearer option would send Bearer YOUR_TOKEN, which the API won’t accept. If you’d rather not depend on our copy, MCPHub can also take the whole schema embedded in the server config instead of a URL.
Put the server in a group (we use one group per connector), and connect your client to https://your-mcphub/mcp/GROUP. Each operation shows up as a tool named after its operationId.
Status: we’ve loaded it into our own MCPHub and it’s still a work in progress. 41 of the 50 tools show up in Claude. The other nine (aggregate report stats, alignment failures, compliance trends, top sources, and the aggregate, failure and MTA-STS report lists) were dropped because Claude rejects parameter names with brackets, such as q[start_date]. The repo version folds those into a single q object parameter (OpenAPI deepObject), which still sends q[start_date] on the wire; we haven't confirmed yet that MCPHub serialises it that way. Our first test call also came back 401 Not authorized, so we’re still working out how MCPHub passes the token. We’ll update this post with both fixes.
Key Takeaways for MCPHub Administrators
1. Check the docs generator before giving up on a spec. Apipie, rswag, FastAPI, NestJS and Spring all serve machine-readable specs at predictable URLs, even when the docs never link to them.
2. Converting a spec isn’t the same as fixing it. A format converter will happily carry over a localhost server and an empty security block. Read servers, securitySchemes and the operationIds before you load anything into MCPHub.
3. operationIds are your tool names. Keep them short, without dots, and descriptive enough that an agent picks the right one. get_alignment_failures works much better for an agent than get_v2_accounts_account_id_domains_domain_id_agg_reports_alignment_failures.
4. Scope the token, not just the tools. This spec includes delete_domain, delete_account, disable_hosted_dmarc and other write calls. Use a read-only DMARC Report token for reporting agents, and switch off the write tools in MCPHub if you don’t need them.
Updates
- 11/10/2026: The spec now lives in the managingwp/openapi-specs repo, along with a read-only (GET-only) variant and an MCPHub config. The bracketed q[…] filters are now one q object parameter, so the nine reporting tools should no longer be rejected (not yet tested in MCPHub). Both download buttons and the config example point at the repo.
- 11/09/2026: The spec is now hosted on GitHub Gist. The download button, the MCPHub config file and the config example all point at its raw URL.
- 11/09/2026: Initial post.
