Initial commit

This commit is contained in:
2026-06-02 23:13:20 +02:00
commit 7e83dd39da
9 changed files with 1920 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules/
dist/
.env

2
index.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=index.d.ts.map

1
index.d.ts.map Normal file
View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":""}

132
index.js Normal file
View File

@@ -0,0 +1,132 @@
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) {
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) {
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) {
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) {
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);
});
//# sourceMappingURL=index.js.map

1
index.js.map Normal file

File diff suppressed because one or more lines are too long

159
index.ts Normal file
View File

@@ -0,0 +1,159 @@
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);
});

1554
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "godaddy_mcp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0",
"axios": "^1.16.1",
"dotenv": "^17.4.2",
"zod": "^4.4.3"
},
"devDependencies": {
"@types/node": "^25.9.1",
"ts-node": "^10.9.2",
"typescript": "^6.0.3"
}
}

44
tsconfig.json Normal file
View File

@@ -0,0 +1,44 @@
{
// Visit https://aka.ms/tsconfig to read more about this file
"compilerOptions": {
// File Layout
// "rootDir": "./src",
// "outDir": "./dist",
// Environment Settings
// See also https://aka.ms/tsconfig/module
"module": "nodenext",
"target": "esnext",
"types": [],
// For nodejs:
// "lib": ["esnext"],
// "types": ["node"],
// and npm install -D @types/node
// Other Outputs
"sourceMap": true,
"declaration": true,
"declarationMap": true,
// Stricter Typechecking Options
"noUncheckedIndexedAccess": true,
"exactOptionalPropertyTypes": true,
// Style Options
// "noImplicitReturns": true,
// "noImplicitOverride": true,
// "noUnusedLocals": true,
// "noUnusedParameters": true,
// "noFallthroughCasesInSwitch": true,
// "noPropertyAccessFromIndexSignature": true,
// Recommended Options
"strict": true,
"jsx": "react-jsx",
"verbatimModuleSyntax": true,
"isolatedModules": true,
"noUncheckedSideEffectImports": true,
"moduleDetection": "force",
"skipLibCheck": true,
}
}