DomainCanary

Check a domain's DMARC, SPF and DKIM, build SPF records, explain bounces, read DMARC reports.

Should I use this

Quality & Safety

A
Description quality
100%
Schema completeness
97%
Naming quality
95%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~3,543Tokens (tool definitions)
~8.8 KBTypical response size
Significant attention impact (2.77% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "mcp": {
      "url": "https://domaincanary.com/mcp"
    }
  }
}

Remote endpoints

https://domaincanary.com/mcpstreamable-http

What it can do

Tool inventory

Tools (4)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢check_domain(domain, selector)

Use this when someone asks whether a domain's email authentication is set up correctly, why mail from a domain fails DMARC, SPF or DKIM, or which DNS records to publish for it. Reads the domain's live DMARC, SPF and DKIM records and returns what is wrong with each, plus the records to add or change. Pass a DKIM selector when you know it. Without one, common selectors are tried. Takes a domain name only, not a mailbox address or an IP address.

Input Schema

{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string",
      "minLength": 1,
      "maxLength": 253,
      "description": "The domain to check, such as example.com. A URL is cut down to its host."
    },
    "selector": {
      "description": "The DKIM selector, the s= value in a DKIM-Signature header. Leave it out to try common ones.",
      "type": "string",
      "maxLength": 63
    }
  },
  "required": [
    "domain"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Output Schema

{
  "type": "object",
  "properties": {
    "domain": {
      "type": "string"
    },
    "verdict": {
      "type": "string",
      "enum": [
        "clean",
        "warn",
        "flagged",
        "idle"
      ]
    },
    "dmarc": {
      "type": "object",
      "properties": {
        "found": {
          "type": "boolean"
        },
        "policy": {
          "anyOf": [
            {
              "type": "string",
              "enum": [
                "none",
                "quarantine",
                "reject"
              ]
            },
            {
              "type": "null"
            }
          ]
        },
        "findings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "level": {
                "type": "string",
                "enum": [
                  "ok",
                  "warn",
                  "error"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "level",
              "message"
            ],
            "additionalProperties": false
          }
        },
        "findings_omitted": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "found",
        "policy",
        "findings",
        "findings_omitted"
      ],
      "additionalProperties": false
    },
    "spf": {
      "type": "object",
      "properties": {
        "found": {
          "type": "boolean"
        },
        "lookups": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "findings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "level": {
                "type": "string",
                "enum": [
                  "ok",
                  "warn",
                  "error"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "level",
              "message"
            ],
            "additionalProperties": false
          }
        },
        "findings_omitted": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "found",
        "lookups",
        "findings",
        "findings_omitted"
      ],
      "additionalProperties": false
    },
    "dkim": {
      "type": "object",
      "properties": {
        "selector": {
          "type": [
            "string",
            "null"
          ]
        },
        "found": {
          "type": "boolean"
        },
        "findings": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "level": {
                "type": "string",
                "enum": [
                  "ok",
                  "warn",
                  "error"
                ]
              },
              "message": {
                "type": "string"
              }
            },
            "required": [
              "level",
              "message"
            ],
            "additionalProperties": false
          }
        },
        "findings_omitted": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "selector",
        "found",
        "findings",
        "findings_omitted"
      ],
      "additionalProperties": false
    },
    "records_to_publish": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "const": "TXT"
          },
          "value": {
            "type": "string"
          },
          "why": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "type",
          "value",
          "why"
        ],
        "additionalProperties": false
      }
    },
    "external_data": {
      "type": "object",
      "properties": {
        "notice": {
          "type": "string"
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "dns",
                  "report",
                  "request"
                ]
              },
              "label": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "value": {
                "type": "string"
              },
              "shortened": {
                "type": "boolean"
              }
            },
            "required": [
              "source",
              "label",
              "name",
              "value",
              "shortened"
            ],
            "additionalProperties": false
          }
        },
        "omitted": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "notice",
        "fields",
        "omitted"
      ],
      "additionalProperties": false
    },
    "url": {
      "type": "string"
    }
  },
  "required": [
    "domain",
    "verdict",
    "dmarc",
    "spf",
    "dkim",
    "records_to_publish",
    "external_data",
    "url"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢build_spf(senders, domain, ip4, ip6, all)

Use this when someone lists the services that send their email and wants the SPF record to publish, or wants a sender added to the SPF record they already have. Takes provider names such as Google Workspace or Mailchimp, include terms such as include:spf.example.com, or IP addresses, and returns one merged record with its count of DNS lookups against the limit of ten. Pass the domain when you know it, so the result includes the senders already in its published record.

Input Schema

{
  "type": "object",
  "properties": {
    "senders": {
      "minItems": 1,
      "maxItems": 20,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 300
      },
      "description": "The platforms that send this domain's mail: provider names such as Google Workspace or Mailchimp, or include terms such as include:spf.example.com."
    },
    "domain": {
      "description": "The domain the record is for. When given, the SPF record it publishes today is read and the senders are added to it, so nothing already in it is lost.",
      "type": "string",
      "minLength": 1,
      "maxLength": 253
    },
    "ip4": {
      "description": "IPv4 addresses or ranges that send this domain's mail directly, such as 192.0.2.10 or 192.0.2.0/24.",
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 64
      }
    },
    "ip6": {
      "description": "IPv6 addresses or ranges that send this domain's mail directly, such as 2001:db8::1 or 2001:db8::/32.",
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "string",
        "minLength": 1,
        "maxLength": 64
      }
    },
    "all": {
      "description": "How the record ends. A new record ends in ~all unless you pass -all. A record the domain already publishes keeps its own ending unless you pass one.",
      "type": "string",
      "enum": [
        "~all",
        "-all"
      ]
    }
  },
  "required": [
    "senders"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Output Schema

{
  "type": "object",
  "properties": {
    "domain": {
      "type": [
        "string",
        "null"
      ]
    },
    "outcome": {
      "type": "string",
      "enum": [
        "built",
        "created",
        "merged",
        "already-present",
        "not-spf",
        "invalid",
        "nothing-to-add"
      ]
    },
    "published": {
      "type": "boolean"
    },
    "after": {
      "type": [
        "string",
        "null"
      ]
    },
    "added": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "skipped": {
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "unrecognised": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "no_include": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "name",
          "url"
        ],
        "additionalProperties": false
      }
    },
    "lookups": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "over_limit": {
      "type": "boolean"
    },
    "findings": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "level": {
            "type": "string",
            "enum": [
              "ok",
              "warn",
              "error"
            ]
          },
          "message": {
            "type": "string"
          }
        },
        "required": [
          "level",
          "message"
        ],
        "additionalProperties": false
      }
    },
    "findings_omitted": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "external_data": {
      "type": "object",
      "properties": {
        "notice": {
          "type": "string"
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "dns",
                  "report",
                  "request"
                ]
              },
              "label": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "value": {
                "type": "string"
              },
              "shortened": {
                "type": "boolean"
              }
            },
            "required": [
              "source",
              "label",
              "name",
              "value",
              "shortened"
            ],
            "additionalProperties": false
          }
        },
        "omitted": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "notice",
        "fields",
        "omitted"
      ],
      "additionalProperties": false
    },
    "url": {
      "type": "string"
    }
  },
  "required": [
    "domain",
    "outcome",
    "published",
    "after",
    "added",
    "skipped",
    "unrecognised",
    "no_include",
    "lookups",
    "over_limit",
    "findings",
    "findings_omitted",
    "external_data",
    "url"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢explain_bounce(text)

Use this when someone pastes a bounce message, an SMTP reply such as 550 5.7.26, or an Authentication-Results header and asks what it means or how to fix it. Returns what the receiving server refused, what to change, when it clears, and the page that explains it. Works from the pasted text alone and reads no DNS records.

Input Schema

{
  "type": "object",
  "properties": {
    "text": {
      "type": "string",
      "minLength": 1,
      "maxLength": 4000,
      "description": "The bounce message, the SMTP reply or the Authentication-Results line, as pasted. When the bounce runs past 4,000 characters, pass the lines with the error code and the reason."
    }
  },
  "required": [
    "text"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Output Schema

{
  "type": "object",
  "properties": {
    "matched": {
      "type": "boolean"
    },
    "code": {
      "type": [
        "string",
        "null"
      ]
    },
    "page": {
      "type": "object",
      "properties": {
        "title": {
          "type": "string"
        },
        "url": {
          "type": "string"
        }
      },
      "required": [
        "title",
        "url"
      ],
      "additionalProperties": false
    },
    "meaning": {
      "type": "string"
    },
    "change": {
      "type": [
        "string",
        "null"
      ]
    },
    "clears": {
      "type": [
        "string",
        "null"
      ]
    },
    "faq": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "q": {
            "type": "string"
          },
          "a": {
            "type": "string"
          }
        },
        "required": [
          "q",
          "a"
        ],
        "additionalProperties": false
      }
    },
    "related": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "title",
          "url"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "matched",
    "code",
    "page",
    "meaning",
    "change",
    "clears",
    "faq",
    "related"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}
🟢analyze_report(file, report_xml)

Use this when someone has a DMARC aggregate report and wants to know which senders passed and which failed. The report is the XML, .gz or .zip file that receivers such as Google and Yahoo email to the address in a domain's rua tag. In ChatGPT, pass the uploaded file. Elsewhere, pass the report XML as text. Returns totals per report and each sending IP address with its SPF, DKIM and DMARC results. The result gives a next step for the report's domain and a link to a live check of that domain's DNS records. Nothing from the report is stored.

Input Schema

{
  "type": "object",
  "properties": {
    "file": {
      "description": "The report file the user uploaded in ChatGPT: the .xml, .xml.gz or .zip a mailbox provider emailed them.",
      "type": "object",
      "properties": {
        "download_url": {
          "type": "string",
          "maxLength": 4096
        },
        "file_id": {
          "type": "string",
          "maxLength": 512
        },
        "mime_type": {
          "type": "string",
          "maxLength": 255
        },
        "file_name": {
          "type": "string",
          "maxLength": 1024
        }
      },
      "required": [
        "download_url",
        "file_id"
      ]
    },
    "report_xml": {
      "description": "The report XML as text, from <feedback> to </feedback>. Use this when there is no uploaded file, or when the user pasted the XML.",
      "type": "string",
      "maxLength": 1000000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Output Schema

{
  "type": "object",
  "properties": {
    "reports": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "org": {
            "type": [
              "string",
              "null"
            ]
          },
          "domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "date_begin": {
            "type": "string"
          },
          "date_end": {
            "type": "string"
          },
          "policy": {
            "type": "string",
            "enum": [
              "none",
              "quarantine",
              "reject",
              "unrecognised"
            ]
          },
          "messages": {
            "type": "number"
          },
          "passed": {
            "type": "number"
          },
          "failed": {
            "type": "number"
          },
          "sources": {
            "type": "number"
          },
          "failing_sources": {
            "type": "number"
          },
          "verdict": {
            "type": "string",
            "enum": [
              "clean",
              "warn",
              "flagged"
            ]
          },
          "worst_source": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "ip": {
                    "type": "string"
                  },
                  "messages": {
                    "type": "number"
                  },
                  "disposition": {
                    "anyOf": [
                      {
                        "type": "string",
                        "enum": [
                          "none",
                          "quarantine",
                          "reject"
                        ]
                      },
                      {
                        "type": "null"
                      }
                    ]
                  }
                },
                "required": [
                  "ip",
                  "messages",
                  "disposition"
                ],
                "additionalProperties": false
              },
              {
                "type": "null"
              }
            ]
          },
          "records_with_extra_dkim": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "truncated_fields": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "rows": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "ip": {
                  "type": "string"
                },
                "messages": {
                  "type": "number"
                },
                "passed": {
                  "type": "boolean"
                },
                "disposition": {
                  "anyOf": [
                    {
                      "type": "string",
                      "enum": [
                        "none",
                        "quarantine",
                        "reject"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "spf_result": {
                  "anyOf": [
                    {
                      "type": "string",
                      "enum": [
                        "none",
                        "neutral",
                        "pass",
                        "fail",
                        "softfail",
                        "temperror",
                        "permerror",
                        "unrecognised"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "spf_domain": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "dkim_result": {
                  "anyOf": [
                    {
                      "type": "string",
                      "enum": [
                        "none",
                        "pass",
                        "fail",
                        "policy",
                        "neutral",
                        "temperror",
                        "permerror",
                        "unrecognised"
                      ]
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "dkim_domain": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "dkim_signatures": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "override_reasons": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "type": {
                        "anyOf": [
                          {
                            "type": "string",
                            "enum": [
                              "forwarded",
                              "sampled_out",
                              "trusted_forwarder",
                              "mailing_list",
                              "local_policy",
                              "other",
                              "unrecognised"
                            ]
                          },
                          {
                            "type": "null"
                          }
                        ]
                      },
                      "comment_in_external_data": {
                        "type": "boolean"
                      }
                    },
                    "required": [
                      "type",
                      "comment_in_external_data"
                    ],
                    "additionalProperties": false
                  }
                }
              },
              "required": [
                "ip",
                "messages",
                "passed",
                "disposition",
                "spf_result",
                "spf_domain",
                "dkim_result",
                "dkim_domain",
                "dkim_signatures",
                "override_reasons"
              ],
              "additionalProperties": false
            }
          },
          "rows_omitted": {
            "type": "number"
          }
        },
        "required": [
          "org",
          "domain",
          "date_begin",
          "date_end",
          "policy",
          "messages",
          "passed",
          "failed",
          "sources",
          "failing_sources",
          "verdict",
          "worst_source",
          "records_with_extra_dkim",
          "truncated_fields",
          "rows",
          "rows_omitted"
        ],
        "additionalProperties": false
      }
    },
    "reports_omitted": {
      "type": "number"
    },
    "skipped_payloads": {
      "type": "number"
    },
    "record_limit_reached": {
      "type": "boolean"
    },
    "external_data": {
      "type": "object",
      "properties": {
        "notice": {
          "type": "string"
        },
        "fields": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "source": {
                "type": "string",
                "enum": [
                  "dns",
                  "report",
                  "request"
                ]
              },
              "label": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "value": {
                "type": "string"
              },
              "shortened": {
                "type": "boolean"
              }
            },
            "required": [
              "source",
              "label",
              "name",
              "value",
              "shortened"
            ],
            "additionalProperties": false
          }
        },
        "omitted": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        }
      },
      "required": [
        "notice",
        "fields",
        "omitted"
      ],
      "additionalProperties": false
    },
    "next_steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "domain": {
            "type": [
              "string",
              "null"
            ]
          },
          "kind": {
            "type": "string",
            "enum": [
              "quarantine",
              "reject",
              "raise_pct",
              "keep",
              "fix_senders",
              "check"
            ]
          },
          "text": {
            "type": "string"
          },
          "link_text": {
            "type": "string"
          },
          "url": {
            "type": "string"
          }
        },
        "required": [
          "domain",
          "kind",
          "text",
          "link_text",
          "url"
        ],
        "additionalProperties": false
      }
    },
    "analyzer_url": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "reports",
    "reports_omitted",
    "skipped_payloads",
    "record_limit_reached",
    "external_data",
    "next_steps",
    "analyzer_url"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "additionalProperties": false
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded4 tools