Turning the DMARC Report API Into MCP Tools With MCPHub

Cartoon machine turning a pile of JSON API docs into MCP tool icons, with the title Turning the DMARC Report API Into MCP Tools With MCPHub

This page has had its content updated on November 10, 2026 EST by Jordan

Content Error or Suggest an Edit

Notice a grammatical error or technical inaccuracy? Let us know; we will give you credit!

Found this useful? Managing WP is written in the gaps between client work.
If it saved you some time, a coffee keeps it going.

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.

Looking for Support?

Need help implementing this articles content? We can help!

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 TokenAuth scheme and short tool names.
  • Auth: MCPHub’s apiKey security, header Authorization, value Token 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.

Finding the Hidden Swagger File

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. host is localhost:3000 and basePath is the full URL https://api.dmarcreport.com. A straight conversion gives you a server MCPHub would call on its own localhost.
  • No auth. securityDefinitions is empty. The only description of auth is prose: send Authorization: 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.json contain 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: string with enums like [true, false, "true", "false"], dmarc_compliance_eq is a string with integer enum values, and page/per/limit are strings.
  • Form fields as flat names. Request bodies are formData fields such as domain[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:

  1. Outputs OpenAPI 3.0.3 with servers set to https://api.dmarcreport.com.
  2. Adds a TokenAuth scheme: apiKey in the Authorization header.
  3. Renames all 50 operations to short names like get_account_compliance_summary, get_alignment_failures, get_bimi_status and generate_dmarc_record (34 characters at most).
  4. Turns bracketed form fields into nested JSON request bodies ({"domain": {"address": "...", "mta_sts_policy": {...}}}).
  5. Fixes types: true/false enums become booleans, IDs and paging become integers, and IDs that accept slugs stay strings.
  6. Converts the HTML descriptions to Markdown, restores the bullet lists Apipie flattened, and fixes typos like “Aggregte”.
  7. 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.

Found this useful? Managing WP is written in the gaps between client work.
If it saved you some time, a coffee keeps it going.

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.

Sources

0 Shares:

You May Also Like
testing an email address 140
Read More

Testing an Email Address

If you’re looking to verify if an email address is functioning properly there are a couple of methods…