Skip to main content
Glama

dynadot_domain

Manage domain names through Dynadot: search availability, register new domains, renew existing ones, and perform bulk operations.

Instructions

Core domain operations: list, search, register, renew, delete, info, lock, pricing. Search domains: https://www.dynadot.com/domain/search.html?s9F6L9F7U8Q9U8Z8v

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform: list: List all domains in your account | info: Get detailed info about a domain | search: Check domain availability (with optional pricing). Search manually: https://www.dynadot.com/domain/search.html?s9F6L9F7U8Q9U8Z8v | register: Register a new domain. View pricing: https://www.dynadot.com/domain/pricing?s9F6L9F7U8Q9U8Z8v | bulk_register: Register multiple domains at once. View pricing: https://www.dynadot.com/domain/pricing?s9F6L9F7U8Q9U8Z8v | renew: Renew a domain or check renewal price | delete: Delete a domain | restore: Restore a deleted/expired domain | lock: Lock or unlock a domain | tld_price: Get TLD pricing | push: Push domain to another Dynadot account
domainNoDomain name (e.g., example.com)
domainsNoList of domain names
showPriceNoInclude pricing
currencyNoCurrency code (default: USD)USD
durationNoDuration in years (1-10)
priceCheckNoOnly check price
lockNoLock action
tldNoTLD (e.g., com, net)
usernameNoTarget username

Implementation Reference

  • Defines the CompositeTool 'dynadot_domain' with description, actions mapping to Dynadot API commands (e.g., list_domain, domain_info), Zod input schemas for parameters, and transform functions to format inputs for the API.
    { name: 'dynadot_domain', description: `Core domain operations: list, search, register, renew, delete, info, lock, pricing. Search domains: ${DYNADOT_URLS.domainSearch}`, actions: { list: { command: 'list_domain', description: 'List all domains in your account', }, info: { command: 'domain_info', description: 'Get detailed info about a domain', params: z.object({ domain: p.domain }), }, search: { command: 'search', description: `Check domain availability (with optional pricing). Search manually: ${DYNADOT_URLS.domainSearch}`, params: z.object({ domain: z.string().optional().describe('Single domain name (e.g., example.com)'), domains: z.array(z.string()).optional().describe('List of domain names'), showPrice: z.boolean().optional().describe('Include pricing'), currency: p.currency.optional(), }), transform: (_, input) => { const params: ApiParams = {}; // Accept both domain (singular) and domains (plural) let domainList: string[] = []; if (input.domain) { domainList = [input.domain as string]; } else if (input.domains) { domainList = input.domains as string[]; } if (!domainList.length) throw new Error('Either domain or domains parameter is required for search action'); domainList.forEach((d, i) => { params[`domain${i}`] = d; }); if (input.showPrice) params.show_price = '1'; if (input.currency) params.currency = input.currency as string; return params; }, }, register: { command: 'register', description: `Register a new domain. View pricing: ${DYNADOT_URLS.pricing}`, params: z.object({ domain: p.domain, duration: p.duration, currency: p.currency.optional(), }), }, bulk_register: { command: 'bulk_register', description: `Register multiple domains at once. View pricing: ${DYNADOT_URLS.pricing}`, params: z.object({ domains: p.domains, duration: p.duration, currency: p.currency.optional(), }), transform: (_, input) => { const params: ApiParams = { duration: input.duration as number, currency: (input.currency as string) || 'USD', }; const domains = input.domains as string[] | undefined; if (!domains?.length) throw new Error('domains array is required for bulk_register action'); domains.forEach((d, i) => { params[`domain${i}`] = d; }); return params; }, }, renew: { command: 'renew', description: 'Renew a domain or check renewal price', params: z.object({ domain: p.domain, duration: p.duration, currency: p.currency.optional(), priceCheck: z.boolean().optional().describe('Only check price'), }), transform: (_, input) => ({ domain: input.domain as string, duration: input.duration as number, currency: (input.currency as string) || 'USD', price_check: input.priceCheck ? '1' : undefined, }), }, delete: { command: 'delete', description: 'Delete a domain', params: z.object({ domain: p.domain }), }, restore: { command: 'restore', description: 'Restore a deleted/expired domain', params: z.object({ domain: p.domain }), }, lock: { command: 'lock_domain', description: 'Lock or unlock a domain', params: z.object({ domain: p.domain, lock: p.lockAction }), }, tld_price: { command: 'tld_price', description: 'Get TLD pricing', params: z.object({ tld: z.string().describe('TLD (e.g., com, net)'), currency: p.currency.optional(), }), }, push: { command: 'push', description: 'Push domain to another Dynadot account', params: z.object({ domain: p.domain, username: z.string().describe('Target username') }), }, }, },
  • src/register.ts:6-65 (registration)
    Registers the 'dynadot_domain' tool (and all composite tools) with the MCP server using dynamic input schema derived from actions and a shared handler that dispatches based on input.action.
    export function registerAllTools(server: McpServer): void { for (const tool of compositeTools) { // Build action enum from keys const actionKeys = Object.keys(tool.actions) as [string, ...string[]]; // Build combined input schema with action + all possible params const actionDescriptions = actionKeys .map((k) => { const actionDef = tool.actions[k]; return actionDef ? `${k}: ${actionDef.description}` : k; }) .join(' | '); const inputSchema: Record<string, z.ZodTypeAny> = { action: z.enum(actionKeys).describe(`Action to perform: ${actionDescriptions}`), }; // Collect all unique params across actions for (const action of Object.values(tool.actions)) { if (action?.params) { const shape = action.params.shape; for (const [key, schema] of Object.entries(shape)) { if (!inputSchema[key]) { // Make optional since not all actions need all params inputSchema[key] = (schema as z.ZodTypeAny).optional(); } } } } server.registerTool( tool.name, { description: tool.description, inputSchema, }, async (input) => { const action = input.action as string; const actionDef = tool.actions[action]; if (!actionDef) { throw new Error(`Unknown action: ${action}. Valid actions: ${actionKeys.join(', ')}`); } const client = getClient(); const params = actionDef.transform ? actionDef.transform(action, input as Record<string, unknown>) : (input as ApiParams); // Remove 'action' from params sent to API delete params.action; const result = await client.execute(actionDef.command, params); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } ); } }
  • The MCP tool handler function for 'dynadot_domain' (shared across composites): parses action, applies transform if defined, calls Dynadot API via client.execute, and returns JSON-formatted result.
    async (input) => { const action = input.action as string; const actionDef = tool.actions[action]; if (!actionDef) { throw new Error(`Unknown action: ${action}. Valid actions: ${actionKeys.join(', ')}`); } const client = getClient(); const params = actionDef.transform ? actionDef.transform(action, input as Record<string, unknown>) : (input as ApiParams); // Remove 'action' from params sent to API delete params.action; const result = await client.execute(actionDef.command, params); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; } );
  • Core API execution helper called by the tool handler: formats parameters, authenticates with API key, makes HTTP request to Dynadot API, handles errors, and returns structured response.
    async execute(command: string, params: ApiParams = {}): Promise<ApiResponse> { const searchParams = new URLSearchParams(); searchParams.set('key', this.apiKey); searchParams.set('command', command); for (const [key, value] of Object.entries(params)) { if (value !== undefined) { searchParams.set(key, String(value)); } } const response = await this.client.get('api3.json', { searchParams }).json<ApiResponse>(); if (response.Status === 'error') { throw new Error(`Dynadot API error: ${response.Error || 'Unknown error'}`); } return response; }
  • Dynadot base domain URL constant used in tool descriptions and links.
    export const DYNADOT_DOMAIN = 'https://www.dynadot.com';

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/joachimBrindeau/domain-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server