160 lines
5.1 KiB
TypeScript
160 lines
5.1 KiB
TypeScript
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);
|
|
});
|