Domain MCP server
Registrar Domains is a domain registrar your AI agent can use through the Model Context Protocol. One endpoint, https://registrar-domains.com/mcp, gives 21 tools: search names, read prices, start a registration, then manage DNS records, nameservers, the transfer lock and code, and renewals. Every order answers a payment link for you. The one exception is automatic renewal: an agent can ask to turn it on for a domain (set_auto_renew), and once you confirm it by email, we charge your saved card before expiry. An unlock, a transfer code and a nameserver change also wait for your confirmation by email.
- Connect a client
- Tools and arguments
- Example prompts
- What needs you
- Scopes
- Confirmation by email
- Endpoint details
Connect a client
Sign-in (OAuth 2.1) is the simplest: the app opens a page where you sign in with your email and press Allow. With a key from your dashboard, send it as a bearer token instead. Search and prices work with no account at all.
Claude.ai and ChatGPT
Add a custom connector in the app's settings with this URL, then sign in when the app asks:
https://registrar-domains.com/mcp/oauthClaude Code
claude mcp add --transport http registrar-domains https://registrar-domains.com/mcp/oauthOr with a key:
claude mcp add --transport http registrar-domains https://registrar-domains.com/mcp --header "Authorization: Bearer apex_…"Claude Desktop
In claude_desktop_config.json, through the mcp-remote bridge, which opens the sign-in page:
{
"mcpServers": {
"registrar-domains": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://registrar-domains.com/mcp/oauth"
]
}
}
}Cursor
In .cursor/mcp.json:
{
"mcpServers": {
"registrar-domains": {
"url": "https://registrar-domains.com/mcp/oauth"
}
}
}VS Code
In .vscode/mcp.json:
{
"servers": {
"registrar-domains": {
"type": "http",
"url": "https://registrar-domains.com/mcp/oauth"
}
}
}Tools and arguments
The first three are open to anyone. The others act on your account and need a key or a signed-in connection with the right scope. Every answer is JSON; a failure is an { "error" } object, never a fake success.
check_domain open
Is this exact domain available? Answers available, taken, or unknown.
domainstring — Full domain, for example tiny.fr
suggest_domains open
Try one idea across the launch TLDs and rank by availability.
ideastring — A word, a short phrase, or a full domain such as quietharbor.frtldsstring[], optional — TLDs to try. Defaults to the launch list.
get_price open
First-year and renewal price in EUR for one TLD, next to our registrar costs.
tldstring — TLD without the dot, for example fr
register_domain account
Start a registration. Needs an API key or a signed-in connection. Answers an order with a payment link for the human; the domain is registered once payment clears. .fr needs a registrant living or established in the EU, Iceland, Liechtenstein, Norway or Switzerland; .eu needs one in the EU, Iceland, Liechtenstein or Norway. Other registrants are refused before payment (see /terms#eligibility).
domainstringyearsinteger, optionalregistrantobject — Legal registrant of the domainaddonsobject, optional — Options for the domain, priced per year: privacy, premiumDns, spamExperts, easyDmarc. Only the ones this deployment offers are kept.
get_order account
Follow an order: awaiting_payment, paid, registering, registered, failed, refunded.
orderIdstring — Order id returned by register_domain
list_domains account
The domains of your account, soonest expiry first, with state, expiry, days left and auto-renew.
No arguments.
list_orders account
The orders of your account, newest first, from every key and connection, with the amount paid and the invoice link.
limitinteger, optional — How many orders, newest first. 1 to 200, 50 by default.
get_domain account
One domain: expiry, auto-renew, nameservers, transfer lock, DNSSEC, and what the registry allows.
domainstring — A domain of your account, as list_domains names it, for example ada.fr
renew_domain account
Start a renewal for N years. Answers an order with a payment link for the human; the domain is renewed once payment clears.
domainstring — A domain of your account, as list_domains names it, for example ada.fryearsinteger, optional — Years to add, 1 to 10. 1 by default.addonsobject, optional — The options to keep with the renewal: privacy, premiumDns, spamExperts, easyDmarc. Absent: the domain keeps its current options. {}: drops them all.
get_basket account
The account's basket, priced live: domains, years, options, line totals and the subtotal.
No arguments.
set_basket account
Replace the basket with lines of { domain, years, addons }. Nothing is charged.
linesobject[]
checkout_basket account
One order and one payment link for the whole basket, every domain to the same registrant. A failed line is refunded alone. .fr needs a registrant living or established in the EU, Iceland, Liechtenstein, Norway or Switzerland; .eu needs one in the EU, Iceland, Liechtenstein or Norway. Other registrants are refused before payment (see /terms#eligibility).
linesobject[], optionalregistrantobject — Legal registrant of every domain in the basket
list_dns_records account
The DNS records of a domain on our nameservers, each with a stable id.
domainstring — A domain of your account, as list_domains names it, for example ada.fr
add_dns_record account
Add a DNS record: A, AAAA, CNAME, MX, TXT, CAA, SRV or NS. TTL 600 to 86400 seconds.
domainstring — A domain of your account, as list_domains names it, for example ada.frnamestring, optional — Host name inside the domain: "" or "@" for the domain itself, "www" for www.<domain>type"A" | "AAAA" | "CNAME" | "MX" | "TXT" | "CAA" | "SRV" | "NS"valuestring — Value: an IP for A/AAAA, a host for CNAME/MX/NS, text for TXT (without quotes), for example v=spf1 include:_spf.example.com ~allttlinteger, optional — Seconds, 600 to 86400priointeger, optional — Priority, for MX and SRV only
update_dns_record account
Replace one DNS record by its id, in one step.
domainstring — A domain of your account, as list_domains names it, for example ada.fridstring — The record's id from list_dns_records, for example rec_3f2a9c0d1e4b5a67namestring, optional — Host name inside the domain: "" or "@" for the domain itself, "www" for www.<domain>type"A" | "AAAA" | "CNAME" | "MX" | "TXT" | "CAA" | "SRV" | "NS"valuestring — Value: an IP for A/AAAA, a host for CNAME/MX/NS, text for TXT (without quotes), for example v=spf1 include:_spf.example.com ~allttlinteger, optional — Seconds, 600 to 86400priointeger, optional — Priority, for MX and SRV only
delete_dns_record account
Remove one DNS record by its id.
domainstring — A domain of your account, as list_domains names it, for example ada.fridstring — The record's id from list_dns_records, for example rec_3f2a9c0d1e4b5a67
set_nameservers account
Ask to point the domain to other nameservers (two or more), or back to ours with an empty list. Nothing changes until the owner confirms it from an email.
domainstring — A domain of your account, as list_domains names it, for example ada.frnameserversstring[] — Two to thirteen host names, for example ["ns1.cloudflare.com", "ns2.cloudflare.com"]. An empty list puts the domain back on our nameservers.
set_transfer_lock account
Lock the domain against transfers, at once, where the registry allows it. An unlock waits for the owner to confirm it from an email.
domainstring — A domain of your account, as list_domains names it, for example ada.frlockedboolean — true locks the domain against transfers; false unlocks it, which a transfer away needs
set_auto_renew account
Turn auto-renew off at once, or ask to turn it on. On: we charge the saved card 7 days before expiry, then renew. Turning it on waits for the owner to confirm it from an email, and needs a card saved at a past payment.
domainstring — A domain of your account, as list_domains names it, for example ada.frenabledboolean — true: we charge the saved card 7 days before expiry, then renew for one year. false: renewal waits for you (renew_domain).
get_auth_code account
Ask for the transfer code, to move the domain to another registrar. The owner confirms it from an email and sees the code on that page. The agent never gets the code.
domainstring — A domain of your account, as list_domains names it, for example ada.fr
get_domain_activity account
Who changed what on a domain, newest first: DNS, nameservers, lock, auto-renew, transfer code, renewals.
domainstring — A domain of your account, as list_domains names it, for example ada.frlimitinteger, optional — How many events, newest first. 1 to 200, 50 by default.
The same tools have REST routes, described in /openapi.json. Prices per extension: domain extensions.
Example prompts
- “Find me a .com or .fr name for a bakery called Quiet Harbor, and tell me what each costs to keep for three years.”
- “Register quietharbor.fr for one year with my details, then send me the payment link.”
- “Point quietharbor.fr to my Vercel site: add the A record for the root and a CNAME for www.”
- “Set up Google Workspace mail on quietharbor.fr.”
- “Which of my domains expire in the next 60 days? Start the renewals and give me the links.”
- “Move quietharbor.io to Cloudflare's nameservers ns1.example.com and ns2.example.com.”
What needs you
- Payment.
register_domainandrenew_domainanswer an order with acheckoutUrl. Nothing is registered, renewed or charged until you pay on that page. Follow the order withget_order. - Eligibility. .fr needs a registrant in the EU, Iceland, Liechtenstein, Norway or Switzerland; .eu one in the EU, Iceland, Liechtenstein or Norway. Other registrants are refused before payment. See who can register.
- Moves away. When an agent asks for a nameserver change, an unlock or a transfer code, nothing changes until you confirm it from an email (confirmation by email). In the dashboard you act at once, and a nameserver change or a transfer code shown there sends an email to the account owner. Every change and every request goes into the domain's activity log, with who did it: you on the web, a key by its label and id, or a connected app by its name and client id.
- Renewal. Renew from your dashboard, or from the link in the reminder emails we send 30 and 7 days before expiry. Automatic renewal is off by default. Turn it on per domain in the dashboard, or confirm an agent's request from the email we send you, and we charge your saved card 7 days before expiry, then renew. You can turn it off at any time. An agent with your key or connection can ask to turn it on with
set_auto_renew; revoke the key or app to stop the requests. - Revoking. Revoke a key or disconnect an app in the dashboard under Connect agent; it stops at once.
- Limits. 30 calls a minute per IP address. An availability the registry did not confirm is reported as
unknown, never as available. When our registrar checks are busy, the reason says "The registrar check is busy. Try again in a few minutes."
Scopes
A connected app asks for scopes, and the consent page shows each one with the line below. Read is always granted. An app without the scope a tool needs gets { "error", "requires": "scope", "scope" }: disconnect it under Connect agent, then connect it again and allow that scope. An app connected before the split (scope domains) can only read until you connect it again. An API key has no scopes: it can do everything an app with all three scopes can do.
domains:read
Search and price domains, read your domains, orders, DNS records and activity, and start registrations and renewals that you pay through a link.
domains:write
Change DNS records (which can redirect your web and email traffic), nameservers and transfer locking (locking only), and turn auto-renew on or off. Turning auto-renew on lets us charge your saved card off-session at renewal. Nameserver changes and auto-renew on wait for your email confirmation.
domains:transfer
Unlock domains and ask for transfer codes. Each request waits for your email confirmation, and only you see the code.
get_auth_codeset_transfer_lock— to unlock
No scope
Open to anyone, with no key and no connection.
Confirmation by email
Four actions let someone take a domain away from you. When an agent asks for one, we email the account owner a link, and nothing changes until the owner confirms it.
set_nameservers: every change, including the empty list that puts the domain back on our nameservers.set_transfer_lockwithlocked: false. Locking acts at once.get_auth_code. The agent never gets the code: the owner sees it on the confirmation page, once.set_auto_renewwithenabled: true. Turning it off acts at once. A domain already on answers{ "autoRenew": true }at once.
The link works once, for 30 minutes. It opens /account/confirm, which asks the owner to sign in to the same account. The page shows the request and who asked for it, with two buttons: Confirm and Refuse. Confirm carries out the change, with the rules checked again. Refuse cancels it. The domain's activity log shows the request (confirm.requested), a refusal (confirm.refused), and the change itself once it is carried out, under the name of who asked.
The tool answers at once:
{
"status": "confirmation_sent",
"domain": "quietharbor.fr",
"action": "nameservers",
"expiresAt": "2026-10-21T10:30:00.000Z",
"message": "We emailed the account owner a link. Nothing changes until they confirm it. The link works once, for 30 minutes."
}actionisunlock,authcode,nameserversorautorenew_on.- The same request again, while its link is open, adds
alreadySent: trueand sends no new email. A newer nameserver request for the same domain replaces the open one. - The REST routes answer
202with the same body. An action that acts at once answers200. - An account can make 5 requests an hour. After that the answer is an error (
429on REST), and nothing changes. - If the email cannot be sent, the answer is an error (
503on REST), and nothing changes. - API keys go through the same confirmation. Revoking a key cancels its open requests.
- In the dashboard you are signed in already, so these actions act at once.
Endpoint details
https://registrar-domains.com/mcp: Streamable HTTP, stateless, JSON-RPC over POST. No session header. Open tools need nothing; account tools takeAuthorization: Bearer <key>.https://registrar-domains.com/mcp/oauth: the same tools behind OAuth 2.1 with dynamic client registration, and the scopes above. Discovery at/.well-known/oauth-protected-resource/mcp/oauth.- Server name for configs:
registrar-domains.
A raw call, to see the shape:
curl -s https://registrar-domains.com/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_price","arguments":{"tld":"fr"}}}'More: all docs, /llms-full.txt for assistants.