Skip to main content
Glama

dynadot_folder

Manage domain folders by creating, deleting, listing, and configuring settings like WHOIS, DNS, forwarding, and renewal options for organized domain administration.

Instructions

Folder management: create, delete, list, configure folder-level settings

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesAction to perform: list: List all folders | create: Create new folder | delete: Delete folder | rename: Rename folder | set_whois: Set WHOIS for all domains in folder | set_ns: Set nameservers for folder | set_parking: Enable parking for folder | set_forwarding: Set forwarding for folder | set_stealth: Set stealth forwarding for folder | set_hosting: Set hosting for folder | set_dns: Set DNS for folder | set_dns2: Set DNS2 for folder | set_email_forward: Set email forwarding for folder | set_renew_option: Set renewal option for folder | clear_settings: Clear all folder settings
folderNameNoName
folderIdNoFolder ID
contactIdNoContact ID
nameserversNoList of nameservers
forwardUrlNoURL
stealthUrlNoURL
optionsNo
mainRecordsNo
subdomainRecordsNo
emailNoEmail address
renewOptionNoRenewal option

Implementation Reference

  • Handler function for dynadot_folder tool that determines the action, applies schema-defined transform to input parameters, executes the corresponding Dynadot API command, and returns the result as formatted JSON.
    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) }],
      };
    }
  • Input/output schema and action definitions for the dynadot_folder tool, including Zod schemas for parameters and transform functions to map to Dynadot API params.
      name: 'dynadot_folder',
      description: 'Folder management: create, delete, list, configure folder-level settings',
      actions: {
        list: {
          command: 'folder_list',
          description: 'List all folders',
        },
        create: {
          command: 'create_folder',
          description: 'Create new folder',
          params: z.object({ folderName: p.name }),
          transform: (_, input) => ({ folder_name: input.folderName as string }),
        },
        delete: {
          command: 'delete_folder',
          description: 'Delete folder',
          params: z.object({ folderId: p.folderId }),
          transform: (_, input) => tx.folderId(input),
        },
        rename: {
          command: 'set_folder_name',
          description: 'Rename folder',
          params: z.object({ folderId: p.folderId, folderName: p.name }),
          transform: (_, input) => ({
            folder_id: input.folderId as string,
            folder_name: input.folderName as string,
          }),
        },
        set_whois: {
          command: 'set_folder_whois',
          description: 'Set WHOIS for all domains in folder',
          params: z.object({ folderId: p.folderId, contactId: p.contactId }),
          transform: (_, input) => ({
            folder_id: input.folderId as string,
            contact_id: input.contactId as string,
          }),
        },
        set_ns: {
          command: 'set_folder_ns',
          description: 'Set nameservers for folder',
          params: z.object({ folderId: p.folderId, nameservers: p.nameservers }),
          transform: (_, input) => tx.folderNs(input),
        },
        set_parking: {
          command: 'set_folder_parking',
          description: 'Enable parking for folder',
          params: z.object({ folderId: p.folderId }),
          transform: (_, input) => tx.folderId(input),
        },
        set_forwarding: {
          command: 'set_folder_forwarding',
          description: 'Set forwarding for folder',
          params: z.object({ folderId: p.folderId, forwardUrl: p.url }),
          transform: (_, input) => ({
            folder_id: input.folderId as string,
            forward_url: input.forwardUrl as string,
          }),
        },
        set_stealth: {
          command: 'set_folder_stealth',
          description: 'Set stealth forwarding for folder',
          params: z.object({ folderId: p.folderId, stealthUrl: p.url }),
          transform: (_, input) => ({
            folder_id: input.folderId as string,
            stealth_url: input.stealthUrl as string,
          }),
        },
        set_hosting: {
          command: 'set_folder_hosting',
          description: 'Set hosting for folder',
          params: z.object({ folderId: p.folderId, options: z.record(z.string(), z.string()) }),
          transform: (_, input) => {
            const params: ApiParams = { folder_id: input.folderId as string };
            for (const [k, v] of Object.entries(input.options as Record<string, string>)) {
              params[k] = v;
            }
            return params;
          },
        },
        set_dns: {
          command: 'set_folder_dns',
          description: 'Set DNS for folder',
          params: z.object({
            folderId: p.folderId,
            mainRecords: z.array(dnsRecord).optional(),
            subdomainRecords: z.array(subdomainRecord).optional(),
          }),
          transform: (_, input) => tx.folderDns(input),
        },
        set_dns2: {
          command: 'set_folder_dns2',
          description: 'Set DNS2 for folder',
          params: z.object({
            folderId: p.folderId,
            mainRecords: z.array(dnsRecord).optional(),
            subdomainRecords: z.array(subdomainRecord).optional(),
          }),
          transform: (_, input) => tx.folderDns(input),
        },
        set_email_forward: {
          command: 'set_folder_email_forward',
          description: 'Set email forwarding for folder',
          params: z.object({ folderId: p.folderId, email: p.email }),
          transform: (_, input) => ({
            folder_id: input.folderId as string,
            email: input.email as string,
          }),
        },
        set_renew_option: {
          command: 'set_folder_renew_option',
          description: 'Set renewal option for folder',
          params: z.object({ folderId: p.folderId, renewOption: p.renewOption }),
          transform: (_, input) => ({
            folder_id: input.folderId as string,
            renew_option: input.renewOption as string,
          }),
        },
        clear_settings: {
          command: 'set_clear_folder_setting',
          description: 'Clear all folder settings',
          params: z.object({ folderId: p.folderId }),
          transform: (_, input) => tx.folderId(input),
        },
      },
    },
  • src/register.ts:6-65 (registration)
    Registers the dynadot_folder tool with the MCP server by looping over compositeTools, dynamically generating the input schema from actions, and attaching the shared handler.
    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) }],
            };
          }
        );
      }
    }
  • Transform helper object 'tx' with functions like folderId, folderNs, folderDns used by dynadot_folder action transforms to convert tool inputs to Dynadot API parameters.
    const tx = {
      domain: (input: Record<string, unknown>): ApiParams => ({
        domain: input.domain as string,
      }),
    
      domains:
        (prefix: string) =>
        (input: Record<string, unknown>): ApiParams => {
          const params: ApiParams = {};
          const domains = input.domains as string[] | undefined;
          domains?.forEach((d, i) => {
            params[`${prefix}${i}`] = d;
          });
          return params;
        },
    
      nameservers: (input: Record<string, unknown>): ApiParams => {
        const params: ApiParams = { domain: input.domain as string };
        const ns = input.nameservers as string[] | undefined;
        ns?.forEach((v, i) => {
          params[`ns${i}`] = v;
        });
        return params;
      },
    
      dnsRecords: (input: Record<string, unknown>): ApiParams => {
        const params: ApiParams = { domain: input.domain as string };
        const main = input.mainRecords as
          | Array<{ type: string; value: string; ttl?: number; priority?: number }>
          | undefined;
        const sub = input.subdomainRecords as
          | Array<{ subdomain: string; type: string; value: string; ttl?: number; priority?: number }>
          | undefined;
    
        main?.forEach((r, i) => {
          params[`main_record_type${i}`] = r.type;
          params[`main_record${i}`] = r.value;
          if (r.ttl) params[`main_record_ttl${i}`] = r.ttl;
          if (r.priority !== undefined) params[`main_record_distance${i}`] = r.priority;
        });
    
        sub?.forEach((r, i) => {
          params[`subdomain${i}`] = r.subdomain;
          params[`sub_record_type${i}`] = r.type;
          params[`sub_record${i}`] = r.value;
          if (r.ttl) params[`sub_record_ttl${i}`] = r.ttl;
          if (r.priority !== undefined) params[`sub_record_distance${i}`] = r.priority;
        });
    
        return params;
      },
    
      contact: (input: Record<string, unknown>): ApiParams => ({
        name: input.name as string,
        organization: input.organization as string | undefined,
        email: input.email as string,
        phonecc: input.phoneCc as string,
        phonenum: input.phoneNum as string,
        address1: input.address1 as string,
        address2: input.address2 as string | undefined,
        city: input.city as string,
        state: input.state as string,
        zip: input.zipCode as string,
        country: input.country as string,
      }),
    
      folderId: (input: Record<string, unknown>): ApiParams => ({
        folder_id: input.folderId as string,
      }),
    
      folderNs: (input: Record<string, unknown>): ApiParams => {
        const params: ApiParams = { folder_id: input.folderId as string };
        const ns = input.nameservers as string[] | undefined;
        ns?.forEach((v, i) => {
          params[`ns${i}`] = v;
        });
        return params;
      },
    
      folderDns: (input: Record<string, unknown>): ApiParams => {
        const params: ApiParams = { folder_id: input.folderId as string };
        const main = input.mainRecords as
          | Array<{ type: string; value: string; ttl?: number; priority?: number }>
          | undefined;
        const sub = input.subdomainRecords as
          | Array<{ subdomain: string; type: string; value: string; ttl?: number; priority?: number }>
          | undefined;
    
        main?.forEach((r, i) => {
          params[`main_record_type${i}`] = r.type;
          params[`main_record${i}`] = r.value;
          if (r.ttl) params[`main_record_ttl${i}`] = r.ttl;
          if (r.priority !== undefined) params[`main_record_distance${i}`] = r.priority;
        });
    
        sub?.forEach((r, i) => {
          params[`subdomain${i}`] = r.subdomain;
          params[`sub_record_type${i}`] = r.type;
          params[`sub_record${i}`] = r.value;
          if (r.ttl) params[`sub_record_ttl${i}`] = r.ttl;
          if (r.priority !== undefined) params[`sub_record_distance${i}`] = r.priority;
        });
    
        return params;
      },
    
      defaultNs: (input: Record<string, unknown>): ApiParams => {
        const params: ApiParams = {};
        const ns = input.nameservers as string[] | undefined;
        ns?.forEach((v, i) => {
          params[`ns${i}`] = v;
        });
        return params;
      },
    
      defaultDns: (input: Record<string, unknown>): ApiParams => {
        const params: ApiParams = {};
        const main = input.mainRecords as
          | Array<{ type: string; value: string; ttl?: number; priority?: number }>
          | undefined;
        const sub = input.subdomainRecords as
          | Array<{ subdomain: string; type: string; value: string; ttl?: number; priority?: number }>
          | undefined;
    
        main?.forEach((r, i) => {
          params[`main_record_type${i}`] = r.type;
          params[`main_record${i}`] = r.value;
          if (r.ttl) params[`main_record_ttl${i}`] = r.ttl;
          if (r.priority !== undefined) params[`main_record_distance${i}`] = r.priority;
        });
    
        sub?.forEach((r, i) => {
          params[`subdomain${i}`] = r.subdomain;
          params[`sub_record_type${i}`] = r.type;
          params[`sub_record${i}`] = r.value;
          if (r.ttl) params[`sub_record_ttl${i}`] = r.ttl;
          if (r.priority !== undefined) params[`sub_record_distance${i}`] = r.priority;
        });
    
        return params;
      },
    };
  • DynadotClient.execute method invoked by the handler to send API requests to Dynadot, handling authentication, param serialization, retries, and error checking.
    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;
    }

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