import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import axios from "axios"; import { z } from "zod"; import * as dotenv from "dotenv"; dotenv.config(); const GODADDY_API_KEY = process.env.GODADDY_API_KEY; const GODADDY_API_SECRET = process.env.GODADDY_API_SECRET; const ENVIRONMENT = process.env.GODADDY_ENVIRONMENT || "production"; const baseURL = ENVIRONMENT === "ote" ? "https://api.ote-godaddy.com" : "https://api.godaddy.com"; if (!GODADDY_API_KEY || !GODADDY_API_SECRET) { console.error("GODADDY_API_KEY and GODADDY_API_SECRET environment variables are required."); process.exit(1); } const apiClient = axios.create({ baseURL, headers: { "Authorization": `sso-key ${GODADDY_API_KEY}:${GODADDY_API_SECRET}`, "Content-Type": "application/json", }, }); const server = new McpServer({ name: "godaddy-mcp", version: "1.0.0", }); // GET /v1/domains/{domain}/records server.tool( "godaddy_list_records", "Retrieve all DNS records for a domain", { domain: z.string().describe("The domain name (e.g., mintel.me)"), type: z.string().optional().describe("Filter by record type (A, CNAME, TXT, MX, etc.)"), name: z.string().optional().describe("Filter by record name (e.g., @, www)"), }, async ({ domain, type, name }) => { try { let url = `/v1/domains/${domain}/records`; if (type) { url += `/${type}`; if (name) { url += `/${name}`; } } const response = await apiClient.get(url); return { content: [{ type: "text", text: JSON.stringify(response.data, null, 2) }], }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.response?.data?.message || error.message}` }], isError: true, }; } } ); // PATCH /v1/domains/{domain}/records server.tool( "godaddy_add_records", "Add new DNS records to a domain without replacing existing ones", { domain: z.string().describe("The domain name (e.g., mintel.me)"), records: z.array(z.object({ type: z.enum(["A", "AAAA", "CNAME", "MX", "NS", "SRV", "TXT"]), name: z.string(), data: z.string(), ttl: z.number().optional().describe("Time to live in seconds (default 3600)"), priority: z.number().optional().describe("Priority for MX or SRV records"), weight: z.number().optional(), port: z.number().optional() })).describe("Array of DNS records to add"), }, async ({ domain, records }) => { try { const response = await apiClient.patch(`/v1/domains/${domain}/records`, records); return { content: [{ type: "text", text: "Successfully added records." }], }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.response?.data?.message || error.message}` }], isError: true, }; } } ); // DELETE /v1/domains/{domain}/records/{type}/{name} server.tool( "godaddy_delete_record", "Delete specific DNS records by type and name", { domain: z.string().describe("The domain name (e.g., mintel.me)"), type: z.enum(["A", "AAAA", "CNAME", "MX", "NS", "SRV", "TXT"]).describe("Record type"), name: z.string().describe("Record name (e.g., @, www)"), }, async ({ domain, type, name }) => { try { const response = await apiClient.delete(`/v1/domains/${domain}/records/${type}/${name}`); return { content: [{ type: "text", text: "Successfully deleted record." }], }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.response?.data?.message || error.message}` }], isError: true, }; } } ); // PUT /v1/domains/{domain}/records/{type}/{name} server.tool( "godaddy_replace_records", "Replace all DNS records for a specific type and name", { domain: z.string().describe("The domain name (e.g., mintel.me)"), type: z.enum(["A", "AAAA", "CNAME", "MX", "NS", "SRV", "TXT"]).describe("Record type"), name: z.string().describe("Record name (e.g., @, www)"), records: z.array(z.object({ data: z.string(), ttl: z.number().optional().describe("Time to live in seconds (default 3600)"), priority: z.number().optional().describe("Priority for MX or SRV records"), weight: z.number().optional(), port: z.number().optional() })).describe("Array of DNS records to replace with"), }, async ({ domain, type, name, records }) => { try { const response = await apiClient.put(`/v1/domains/${domain}/records/${type}/${name}`, records); return { content: [{ type: "text", text: "Successfully replaced records." }], }; } catch (error: any) { return { content: [{ type: "text", text: `Error: ${error.response?.data?.message || error.message}` }], isError: true, }; } } ); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("GoDaddy MCP Server running on stdio"); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });