DoDomain MCP

Connect customers' custom domains to your product: guided DNS setup, verification and certificates, managed from DoDomain. Remote server with OAuth sign-in.

Hosted MCP Server

npx add-mcp 'https://app.dodomain.io/api/mcp'

Installs into Claude Code, Codex, Cursor and more

Documentation

DoDomain's remote MCP server — one URL, OAuth 2.1 sign-in, and eight scoped tools for checking domains and running connect sessions.

DoDomain ships a remote MCP (Model Context Protocol) server, so AI assistants and agents — Claude, coding agents, anything that speaks MCP — can check a domain's DNS provider, mint a connect session, hand your user the hosted connect link, and verify DNS, using the same REST API and permissions your integration already has.

One URL, nothing else to configure

The server lives at:

https://app.dodomain.io/api/mcp

Let your coding agent set itself up

Paste this sentence into Claude Code, Codex, Cursor, OpenCode or GitHub Copilot. The agent fetches DoDomain's setup instructions and adds this server, installs the SDK for your stack and verifies the result:

Fetch and execute the appropriate instructions to set me up for DoDomain from https://dodomain.io/agent-setup/prompt.md

The same commands, one page per agent, are at dodomain.io/agent-setup. The manual setup for each client follows.

How sign-in works

It speaks Streamable HTTP (stateless) and authenticates with OAuth 2.1 — PKCE plus dynamic client registration — publishing the standard discovery documents (RFC 9728 protected-resource and RFC 8414 authorization-server metadata). MCP clients find the authorization server, register themselves, and start the sign-in flow automatically. You add the URL, sign in with your DoDomain account, and approve the requested scopes on the consent page. No API keys, no manual client setup.

Claude Code

claude mcp add --transport http dodomain https://app.dodomain.io/api/mcp

Start a new session, run /mcp, pick dodomain and choose Authenticate.

Codex

codex mcp add dodomain --url https://app.dodomain.io/api/mcp
codex mcp login dodomain

Cursor

Add the server to ~/.cursor/mcp.json (every project) or .cursor/mcp.json (one project), merging into mcpServers if the file exists:

{
  "mcpServers": {
    "dodomain": {
      "url": "https://app.dodomain.io/api/mcp"
    }
  }
}

OpenCode

Add the server to opencode.json in the project root (or ~/.config/opencode/opencode.json), then sign in:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "dodomain": {
      "type": "remote",
      "url": "https://app.dodomain.io/api/mcp",
      "enabled": true
    }
  }
}
opencode mcp auth dodomain

GitHub Copilot (VS Code)

Add the server to .vscode/mcp.json, then start it from MCP: List Servers and sign in when VS Code asks:

{
  "servers": {
    "dodomain": {
      "type": "http",
      "url": "https://app.dodomain.io/api/mcp"
    }
  }
}

Claude.ai (custom connector)

In Claude's web or desktop app, open Settings → Connectors → Add custom connector and paste the URL above as the remote MCP server URL. Claude walks you through the DoDomain sign-in and consent screen, then the tools appear in your conversations.

Any MCP client

Any client that supports remote MCP servers over Streamable HTTP with OAuth works the same way — MCP Inspector, ChatGPT connector settings, or your own agent built on an MCP SDK. The URL is the only configuration.

The eight tools

Every tool calls the same /api/v1 REST surface documented in the API reference, on the teams you chose when you approved the connection (see Teams). None are destructive — nothing an agent can call deletes apps, connections, or DNS records.

ToolWhat it doesScopeAccess
check_domainPre-flight a domain before connecting it: which DNS provider manages it, the registrable zone, the connect tier its provider supports (one-click, Domain Connect, or guided manual; the one-click tiers need a Pro or Scale session), nameservers, and a provider-specific setup guide.domains:readRead-only
list_teamsList the teams this connection can use — id and name. The source of the teamId the other tools take when the connection covers more than one team.teams:readRead-only
list_appsList the apps in your team — id, name, public (widget) key, sandbox flag. Never returns secret keys. The source of the appId other tools take.apps:readRead-only
list_connectionsList verified domain connections and their live DNS health (active vs broken), filterable by app or domain.connections:readRead-only
get_connect_sessionFetch one connect session's state by its token: domain, requested DNS records, status, detected provider, expiry. Poll it to see whether the end user finished.sessions:readRead-only
create_connect_sessionStart a connect session for a domain. Returns a connectUrl the agent hands your end user to finish DNS setup in the browser, plus the composed fqdn each record will be verified at. Refused with quota_exceeded at the monthly cap; on Free the cap is shared across the owners' Free teams and unfinished sessions count against it (see Rate limits and pricing).sessions:writeWrites
verify_connect_sessionTrigger a live DNS check of a session's expected records against authoritative nameservers. When every record matches, the connection is finalized and webhooks fire.sessions:writeWrites
reverify_connectionQueue an on-demand DNS health recheck of one existing connection. The result arrives asynchronously as a connection.verified / connection.failed webhook and on the dashboard.connections:writeWrites

Scopes and consent

Access is scoped. When a client connects, the consent page lists exactly what it asked for, and the token it receives carries only the scopes you approve. The tool list an agent sees is filtered to its granted scopes — a client granted only read scopes never even sees create_connect_session.

These are the seven scopes, worded as the consent screen words them:

ScopeGrants
domains:readCheck which DNS provider manages a domain and how it can connect
apps:readList the apps in your team
connections:readList verified domain connections
connections:writeRequest re-verification of an existing connection
sessions:readRead the status of domain-connect sessions
sessions:writeCreate domain-connect sessions and trigger DNS verification
teams:readSee which of your teams this connection can use

Teams

If you belong to more than one DoDomain team, the consent screen asks which ones the connection can use: the teams you tick (your current team is ticked to start with), or All my teams, which also covers teams you join later. The connection can act on a team only while you are still a member of it; leave a team and the connection loses it on the next request. If you rejoin a team the connection was granted, it can use that team again; to stop that, disconnect the client (dashboard, Connected apps) or connect it again without that team. To change the teams later, connect the client again and choose again: the new choice replaces the old one for the whole connection, including the access tokens the client already holds.

When a connection covers more than one team, the agent says which team each call is for. list_teams returns the teams it can use, and the tools that read or write team data (check_domain, list_apps, list_connections, create_connect_session, reverify_connection) take an optional teamId. With more than one team, a call without teamId is refused with TEAM_REQUIRED (except check_domain, whose answer does not depend on the team), and a call naming a team the connection cannot use is refused with TEAM_NOT_FOUND; both list the usable teams. With a single team, teamId can be left out.

Over REST, the same choice is the DoDomain-Team header (a team id from GET /api/v1/teams); see the API reference. A secret key (dd_sk_) belongs to exactly one team, so it needs no header, and a header naming any other team is refused with 404 TEAM_NOT_FOUND.

Revoking access

Every connected client is listed in the dashboard under Connected apps. Revoking one takes effect immediately: both its access and refresh tokens stop working on the next request.

Rate limits and pricing

MCP access is included on every plan — there is no separate SKU. Requests ride the same per-minute plan meters as the REST API (Free 60, Pro 300, Scale 1,200 requests/min per team), and the monthly connection quota is metered identically to REST: creating a session costs nothing, and one unit is charged when a domain is first verified. create_connect_session is refused with quota_exceeded exactly when the REST endpoint would refuse it: on every plan once the team's monthly cap is reached, and on Free also once the Free teams owned by any of this team's owners together reach it, or once its unfinished sessions reach what the month has left plus 10 (see Pricing).

Security

MCP callers authenticate exclusively with OAuth 2.1: PKCE on every flow, short-lived access tokens, and refresh only for clients granted it at consent. Your dd_sk_ secret keys are never exposed to agents — the MCP endpoint does not accept them. Grants are per-user, per-client, scope-limited, and revocable instantly from the dashboard.

[

Testing your integration

Drive the hosted connect flow from your own Playwright suite — the supported automation path, what needs real DNS, and how to assert the result without one.

](https://dodomain.io/docs/testing-your-integration)[

Pricing

Free, Pro, and Scale — what each plan includes and how the quotas work.

](https://dodomain.io/docs/pricing)