@suzko/mcp-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/GUIDE.md +952 -0
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/dist/bin/mcp-server.d.ts +11 -0
- package/dist/bin/mcp-server.js +108 -0
- package/dist/src/auth.d.ts +14 -0
- package/dist/src/auth.js +140 -0
- package/dist/src/client.d.ts +18 -0
- package/dist/src/client.js +78 -0
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.js +44 -0
- package/dist/src/prompts/index.d.ts +5 -0
- package/dist/src/prompts/index.js +87 -0
- package/dist/src/resources/index.d.ts +7 -0
- package/dist/src/resources/index.js +86 -0
- package/dist/src/security.d.ts +18 -0
- package/dist/src/security.js +108 -0
- package/dist/src/tools/account.d.ts +3 -0
- package/dist/src/tools/account.js +254 -0
- package/dist/src/tools/deploy.d.ts +3 -0
- package/dist/src/tools/deploy.js +468 -0
- package/dist/src/tools/dns.d.ts +3 -0
- package/dist/src/tools/dns.js +313 -0
- package/dist/src/tools/domains.d.ts +3 -0
- package/dist/src/tools/domains.js +499 -0
- package/dist/src/tools/server-admin.d.ts +3 -0
- package/dist/src/tools/server-admin.js +738 -0
- package/dist/src/tools/services.d.ts +3 -0
- package/dist/src/tools/services.js +181 -0
- package/dist/src/tools/support.d.ts +3 -0
- package/dist/src/tools/support.js +259 -0
- package/package.json +57 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// In-memory confirmation store (5-minute TTL)
|
|
3
|
+
const pendingConfirmations = new Map();
|
|
4
|
+
function createConfirmation(action, params) {
|
|
5
|
+
const id = crypto.randomUUID();
|
|
6
|
+
pendingConfirmations.set(id, {
|
|
7
|
+
action,
|
|
8
|
+
params,
|
|
9
|
+
expiresAt: Date.now() + 5 * 60 * 1000,
|
|
10
|
+
});
|
|
11
|
+
return id;
|
|
12
|
+
}
|
|
13
|
+
function consumeConfirmation(id, expectedAction) {
|
|
14
|
+
const entry = pendingConfirmations.get(id);
|
|
15
|
+
if (!entry)
|
|
16
|
+
return null;
|
|
17
|
+
pendingConfirmations.delete(id);
|
|
18
|
+
if (Date.now() > entry.expiresAt)
|
|
19
|
+
return null;
|
|
20
|
+
if (entry.action !== expectedAction)
|
|
21
|
+
return null;
|
|
22
|
+
return entry.params;
|
|
23
|
+
}
|
|
24
|
+
// Periodically clean expired confirmations
|
|
25
|
+
setInterval(() => {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
for (const [id, entry] of pendingConfirmations) {
|
|
28
|
+
if (now > entry.expiresAt)
|
|
29
|
+
pendingConfirmations.delete(id);
|
|
30
|
+
}
|
|
31
|
+
}, 60_000);
|
|
32
|
+
export function registerDomainTools(server, client) {
|
|
33
|
+
// 1. Search domains (batch availability check)
|
|
34
|
+
server.tool("search_domains", "Check availability and pricing for one or more domain names. Accepts up to 20 domains at once.", {
|
|
35
|
+
domains: z
|
|
36
|
+
.array(z.string())
|
|
37
|
+
.min(1)
|
|
38
|
+
.max(20)
|
|
39
|
+
.describe("Array of domain names to check (e.g. ['example.com', 'example.net'])"),
|
|
40
|
+
}, async ({ domains }) => {
|
|
41
|
+
const res = await client.post("/api/domains/check-batch", { domains });
|
|
42
|
+
if (!res.success) {
|
|
43
|
+
return {
|
|
44
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
45
|
+
isError: true,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
const results = res.data ?? [];
|
|
49
|
+
if (results.length === 0) {
|
|
50
|
+
return {
|
|
51
|
+
content: [{ type: "text", text: "No results returned for the provided domains." }],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const lines = results.map((r) => {
|
|
55
|
+
const status = r.available ? "✅ Available" : "❌ Taken";
|
|
56
|
+
const premium = r.premium ? " ⭐ Premium" : "";
|
|
57
|
+
const price = r.price?.register
|
|
58
|
+
? ` — $${r.price.register}${r.price.currency ? ` ${r.price.currency}` : ""}/yr`
|
|
59
|
+
: "";
|
|
60
|
+
return `• **${r.domain}** — ${status}${premium}${price}`;
|
|
61
|
+
});
|
|
62
|
+
const available = results.filter((r) => r.available);
|
|
63
|
+
return {
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
type: "text",
|
|
67
|
+
text: `**Domain Search Results (${available.length}/${results.length} available):**\n\n${lines.join("\n")}`,
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
// 2. Get TLD pricing
|
|
73
|
+
server.tool("get_tld_pricing", "Get pricing information for all available top-level domains (TLDs). Shows registration, renewal, and transfer prices.", {}, async () => {
|
|
74
|
+
const res = await client.get("/api/domains/tlds");
|
|
75
|
+
if (!res.success) {
|
|
76
|
+
return {
|
|
77
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
78
|
+
isError: true,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const tlds = res.data ?? [];
|
|
82
|
+
if (tlds.length === 0) {
|
|
83
|
+
return {
|
|
84
|
+
content: [{ type: "text", text: "No TLD pricing data available." }],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const header = `| TLD | Register | Renew | Transfer |`;
|
|
88
|
+
const divider = `|-----|----------|-------|----------|`;
|
|
89
|
+
const rows = tlds.map((t) => `| .${t.tld} | ${t.register != null ? `$${t.register}` : "—"} | ${t.renew != null ? `$${t.renew}` : "—"} | ${t.transfer != null ? `$${t.transfer}` : "—"} |`);
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: "text",
|
|
94
|
+
text: `**TLD Pricing (${tlds.length} TLDs):**\n\n${header}\n${divider}\n${rows.join("\n")}`,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
// 3. AI domain name suggestions
|
|
100
|
+
server.tool("suggest_domain_names", "Get AI-powered domain name suggestions based on keywords. Optionally specify a preferred TLD.", {
|
|
101
|
+
keywords: z.string().describe("Keywords or description for the desired domain name"),
|
|
102
|
+
tld: z
|
|
103
|
+
.string()
|
|
104
|
+
.optional()
|
|
105
|
+
.describe("Preferred TLD (e.g. 'com', 'io', 'dev'). If omitted, suggestions span multiple TLDs."),
|
|
106
|
+
}, async ({ keywords, tld }) => {
|
|
107
|
+
const body = { keywords };
|
|
108
|
+
if (tld)
|
|
109
|
+
body.tld = tld;
|
|
110
|
+
const res = await client.post("/api/domains/suggest", body);
|
|
111
|
+
if (!res.success) {
|
|
112
|
+
return {
|
|
113
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
114
|
+
isError: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const suggestions = res.data ?? [];
|
|
118
|
+
if (suggestions.length === 0) {
|
|
119
|
+
return {
|
|
120
|
+
content: [
|
|
121
|
+
{
|
|
122
|
+
type: "text",
|
|
123
|
+
text: "No suggestions generated. Try different keywords.",
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const lines = suggestions.map((s) => {
|
|
129
|
+
const availability = s.available === true
|
|
130
|
+
? " ✅"
|
|
131
|
+
: s.available === false
|
|
132
|
+
? " ❌"
|
|
133
|
+
: "";
|
|
134
|
+
const reason = s.reason ? ` — ${s.reason}` : "";
|
|
135
|
+
return `• **${s.domain}**${availability}${reason}`;
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
content: [
|
|
139
|
+
{
|
|
140
|
+
type: "text",
|
|
141
|
+
text: `**AI Domain Suggestions for "${keywords}":**\n\n${lines.join("\n")}`,
|
|
142
|
+
},
|
|
143
|
+
],
|
|
144
|
+
};
|
|
145
|
+
});
|
|
146
|
+
// 4. Register domain (with confirmation)
|
|
147
|
+
server.tool("register_domain", "Register a new domain name. Returns a cost preview and confirmation token — use confirm_domain_registration to finalize. This will incur costs.", {
|
|
148
|
+
domain: z.string().describe("Full domain name to register (e.g. 'example.com')"),
|
|
149
|
+
period: z
|
|
150
|
+
.number()
|
|
151
|
+
.int()
|
|
152
|
+
.min(1)
|
|
153
|
+
.max(10)
|
|
154
|
+
.describe("Registration period in years (1-10)"),
|
|
155
|
+
nameservers: z
|
|
156
|
+
.array(z.string())
|
|
157
|
+
.optional()
|
|
158
|
+
.describe("Custom nameservers to use (e.g. ['ns1.example.com', 'ns2.example.com'])"),
|
|
159
|
+
}, async ({ domain, period, nameservers }) => {
|
|
160
|
+
// First check availability to show price
|
|
161
|
+
const checkRes = await client.post("/api/domains/check-batch", { domains: [domain] });
|
|
162
|
+
if (!checkRes.success) {
|
|
163
|
+
return {
|
|
164
|
+
content: [{ type: "text", text: `Error checking domain: ${checkRes.error}` }],
|
|
165
|
+
isError: true,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
const domainInfo = checkRes.data?.[0];
|
|
169
|
+
if (!domainInfo) {
|
|
170
|
+
return {
|
|
171
|
+
content: [{ type: "text", text: `Could not check availability for ${domain}.` }],
|
|
172
|
+
isError: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
if (!domainInfo.available) {
|
|
176
|
+
return {
|
|
177
|
+
content: [
|
|
178
|
+
{
|
|
179
|
+
type: "text",
|
|
180
|
+
text: `**${domain}** is not available for registration. Try searching for alternatives with \`search_domains\` or \`suggest_domain_names\`.`,
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const params = { domain, period };
|
|
186
|
+
if (nameservers)
|
|
187
|
+
params.nameservers = nameservers;
|
|
188
|
+
const confirmationId = createConfirmation("register", params);
|
|
189
|
+
const pricePerYear = domainInfo.price?.register;
|
|
190
|
+
const currency = domainInfo.price?.currency ?? "USD";
|
|
191
|
+
const totalEstimate = pricePerYear ? pricePerYear * period : null;
|
|
192
|
+
const preview = [
|
|
193
|
+
`**Register Domain — Confirmation Required**`,
|
|
194
|
+
``,
|
|
195
|
+
`| Setting | Value |`,
|
|
196
|
+
`|---------|-------|`,
|
|
197
|
+
`| Domain | ${domain} |`,
|
|
198
|
+
`| Period | ${period} year${period > 1 ? "s" : ""} |`,
|
|
199
|
+
pricePerYear != null ? `| Price/Year | $${pricePerYear} ${currency} |` : null,
|
|
200
|
+
totalEstimate != null ? `| Estimated Total | $${totalEstimate} ${currency} |` : null,
|
|
201
|
+
domainInfo.premium ? `| Premium | ⭐ Yes |` : null,
|
|
202
|
+
nameservers ? `| Nameservers | ${nameservers.join(", ")} |` : null,
|
|
203
|
+
``,
|
|
204
|
+
`⚠️ This will register the domain and charge your account.`,
|
|
205
|
+
``,
|
|
206
|
+
`To confirm, call \`confirm_domain_registration\` with confirmation ID:`,
|
|
207
|
+
`\`${confirmationId}\``,
|
|
208
|
+
``,
|
|
209
|
+
`This confirmation expires in 5 minutes.`,
|
|
210
|
+
]
|
|
211
|
+
.filter(Boolean)
|
|
212
|
+
.join("\n");
|
|
213
|
+
return {
|
|
214
|
+
content: [{ type: "text", text: preview }],
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
// 5. Transfer domain (with confirmation)
|
|
218
|
+
server.tool("transfer_domain", "Transfer an existing domain to your account. Returns a preview and confirmation token — use confirm_domain_transfer to finalize. This will incur costs.", {
|
|
219
|
+
domain: z.string().describe("Full domain name to transfer (e.g. 'example.com')"),
|
|
220
|
+
eppCode: z.string().describe("EPP/authorization code from the current registrar"),
|
|
221
|
+
}, async ({ domain, eppCode }) => {
|
|
222
|
+
// Check transfer pricing
|
|
223
|
+
const checkRes = await client.post("/api/domains/check-batch", { domains: [domain] });
|
|
224
|
+
const domainInfo = checkRes.success ? checkRes.data?.[0] : null;
|
|
225
|
+
const transferPrice = domainInfo?.price?.transfer;
|
|
226
|
+
const currency = domainInfo?.price?.currency ?? "USD";
|
|
227
|
+
const params = { domain, eppCode };
|
|
228
|
+
const confirmationId = createConfirmation("transfer", params);
|
|
229
|
+
const preview = [
|
|
230
|
+
`**Transfer Domain — Confirmation Required**`,
|
|
231
|
+
``,
|
|
232
|
+
`| Setting | Value |`,
|
|
233
|
+
`|---------|-------|`,
|
|
234
|
+
`| Domain | ${domain} |`,
|
|
235
|
+
`| EPP Code | ${"•".repeat(Math.min(eppCode.length, 12))} (hidden) |`,
|
|
236
|
+
transferPrice != null ? `| Transfer Price | $${transferPrice} ${currency} |` : null,
|
|
237
|
+
``,
|
|
238
|
+
`⚠️ This will initiate a domain transfer and charge your account.`,
|
|
239
|
+
`The transfer process typically takes 5-7 days to complete.`,
|
|
240
|
+
``,
|
|
241
|
+
`To confirm, call \`confirm_domain_transfer\` with confirmation ID:`,
|
|
242
|
+
`\`${confirmationId}\``,
|
|
243
|
+
``,
|
|
244
|
+
`This confirmation expires in 5 minutes.`,
|
|
245
|
+
]
|
|
246
|
+
.filter(Boolean)
|
|
247
|
+
.join("\n");
|
|
248
|
+
return {
|
|
249
|
+
content: [{ type: "text", text: preview }],
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
// 6. List user's domains
|
|
253
|
+
server.tool("list_domains", "List all domains owned by the authenticated user, including status and expiry dates.", {}, async () => {
|
|
254
|
+
const res = await client.get("/api/client/domains");
|
|
255
|
+
if (!res.success) {
|
|
256
|
+
return {
|
|
257
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
258
|
+
isError: true,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
const domains = res.data ?? [];
|
|
262
|
+
if (domains.length === 0) {
|
|
263
|
+
return {
|
|
264
|
+
content: [
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
text: "You don't have any domains yet. Use `search_domains` to find one and `register_domain` to register it.",
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
const lines = domains.map((d) => {
|
|
273
|
+
const expiry = d.expiryDate
|
|
274
|
+
? ` | Expires: ${new Date(d.expiryDate).toLocaleDateString()}`
|
|
275
|
+
: "";
|
|
276
|
+
const autoRenew = d.autoRenew ? " | Auto-renew: ✅" : "";
|
|
277
|
+
return `• **${d.domain}** (ID: ${d.id}) — Status: ${d.status}${expiry}${autoRenew}`;
|
|
278
|
+
});
|
|
279
|
+
return {
|
|
280
|
+
content: [
|
|
281
|
+
{
|
|
282
|
+
type: "text",
|
|
283
|
+
text: `**Your Domains (${domains.length}):**\n\n${lines.join("\n")}`,
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
};
|
|
287
|
+
});
|
|
288
|
+
// 7. Get domain details
|
|
289
|
+
server.tool("get_domain_details", "Get detailed information about a specific domain including nameservers, registration/expiry dates, and lock status.", {
|
|
290
|
+
domainId: z.number().int().describe("The domain ID (from list_domains)"),
|
|
291
|
+
}, async ({ domainId }) => {
|
|
292
|
+
const res = await client.get(`/api/client/domains/${domainId}`);
|
|
293
|
+
if (!res.success) {
|
|
294
|
+
return {
|
|
295
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
296
|
+
isError: true,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const d = res.data;
|
|
300
|
+
if (!d) {
|
|
301
|
+
return {
|
|
302
|
+
content: [{ type: "text", text: `Domain with ID ${domainId} not found.` }],
|
|
303
|
+
isError: true,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
const info = [
|
|
307
|
+
`**Domain Details: ${d.domain}**`,
|
|
308
|
+
``,
|
|
309
|
+
`| Field | Value |`,
|
|
310
|
+
`|-------|-------|`,
|
|
311
|
+
`| ID | ${d.id} |`,
|
|
312
|
+
`| Domain | ${d.domain} |`,
|
|
313
|
+
`| Status | ${d.status} |`,
|
|
314
|
+
d.registrationDate
|
|
315
|
+
? `| Registered | ${new Date(d.registrationDate).toLocaleDateString()} |`
|
|
316
|
+
: null,
|
|
317
|
+
d.expiryDate
|
|
318
|
+
? `| Expires | ${new Date(d.expiryDate).toLocaleDateString()} |`
|
|
319
|
+
: null,
|
|
320
|
+
`| Auto-Renew | ${d.autoRenew ? "Yes" : "No"} |`,
|
|
321
|
+
`| Locked | ${d.locked ? "🔒 Yes" : "🔓 No"} |`,
|
|
322
|
+
d.dnsManagement != null
|
|
323
|
+
? `| DNS Management | ${d.dnsManagement ? "Enabled" : "Disabled"} |`
|
|
324
|
+
: null,
|
|
325
|
+
d.emailForwarding != null
|
|
326
|
+
? `| Email Forwarding | ${d.emailForwarding ? "Enabled" : "Disabled"} |`
|
|
327
|
+
: null,
|
|
328
|
+
d.idProtection != null
|
|
329
|
+
? `| ID Protection | ${d.idProtection ? "Enabled" : "Disabled"} |`
|
|
330
|
+
: null,
|
|
331
|
+
]
|
|
332
|
+
.filter(Boolean)
|
|
333
|
+
.join("\n");
|
|
334
|
+
const ns = d.nameservers && d.nameservers.length > 0
|
|
335
|
+
? `\n\n**Nameservers:**\n${d.nameservers.map((n) => `• ${n}`).join("\n")}`
|
|
336
|
+
: "";
|
|
337
|
+
return {
|
|
338
|
+
content: [{ type: "text", text: `${info}${ns}` }],
|
|
339
|
+
};
|
|
340
|
+
});
|
|
341
|
+
// 8. Update domain nameservers
|
|
342
|
+
server.tool("update_domain_nameservers", "Update the nameservers for a domain. Provide 2-5 nameserver hostnames.", {
|
|
343
|
+
domainId: z.number().int().describe("The domain ID (from list_domains)"),
|
|
344
|
+
nameservers: z
|
|
345
|
+
.array(z.string())
|
|
346
|
+
.min(2)
|
|
347
|
+
.max(5)
|
|
348
|
+
.describe("New nameservers (e.g. ['ns1.example.com', 'ns2.example.com'])"),
|
|
349
|
+
}, async ({ domainId, nameservers }) => {
|
|
350
|
+
const res = await client.put(`/api/client/domains/${domainId}/nameservers`, { nameservers });
|
|
351
|
+
if (!res.success) {
|
|
352
|
+
return {
|
|
353
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
354
|
+
isError: true,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
content: [
|
|
359
|
+
{
|
|
360
|
+
type: "text",
|
|
361
|
+
text: `✅ Nameservers updated successfully for domain ID ${domainId}:\n${nameservers.map((ns) => `• ${ns}`).join("\n")}\n\nDNS propagation may take up to 48 hours.`,
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
};
|
|
365
|
+
});
|
|
366
|
+
// 9. Get domain lock status
|
|
367
|
+
server.tool("get_domain_lock_status", "Check whether a domain's registrar lock (transfer lock) is enabled or disabled.", {
|
|
368
|
+
domainId: z.number().int().describe("The domain ID (from list_domains)"),
|
|
369
|
+
}, async ({ domainId }) => {
|
|
370
|
+
const res = await client.get(`/api/client/domains/${domainId}/lock`);
|
|
371
|
+
if (!res.success) {
|
|
372
|
+
return {
|
|
373
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
374
|
+
isError: true,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const locked = res.data?.locked ?? false;
|
|
378
|
+
return {
|
|
379
|
+
content: [
|
|
380
|
+
{
|
|
381
|
+
type: "text",
|
|
382
|
+
text: locked
|
|
383
|
+
? `🔒 Domain ID ${domainId} is **locked**. The domain cannot be transferred to another registrar while locked.`
|
|
384
|
+
: `🔓 Domain ID ${domainId} is **unlocked**. The domain can be transferred to another registrar. Use \`toggle_domain_lock\` to lock it.`,
|
|
385
|
+
},
|
|
386
|
+
],
|
|
387
|
+
};
|
|
388
|
+
});
|
|
389
|
+
// 10. Toggle domain lock
|
|
390
|
+
server.tool("toggle_domain_lock", "Enable or disable the registrar lock (transfer protection) on a domain.", {
|
|
391
|
+
domainId: z.number().int().describe("The domain ID (from list_domains)"),
|
|
392
|
+
locked: z.boolean().describe("true to lock the domain, false to unlock"),
|
|
393
|
+
}, async ({ domainId, locked }) => {
|
|
394
|
+
const res = await client.put(`/api/client/domains/${domainId}/lock`, { locked });
|
|
395
|
+
if (!res.success) {
|
|
396
|
+
return {
|
|
397
|
+
content: [{ type: "text", text: `Error: ${res.error}` }],
|
|
398
|
+
isError: true,
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
content: [
|
|
403
|
+
{
|
|
404
|
+
type: "text",
|
|
405
|
+
text: locked
|
|
406
|
+
? `🔒 Domain ID ${domainId} has been **locked**. It is now protected from unauthorized transfers.`
|
|
407
|
+
: `🔓 Domain ID ${domainId} has been **unlocked**. It can now be transferred to another registrar.`,
|
|
408
|
+
},
|
|
409
|
+
],
|
|
410
|
+
};
|
|
411
|
+
});
|
|
412
|
+
// 11. Confirm domain registration
|
|
413
|
+
server.tool("confirm_domain_registration", "Confirm and execute a pending domain registration. Use the confirmation ID returned by register_domain.", {
|
|
414
|
+
confirmationId: z.string().describe("The confirmation ID from register_domain"),
|
|
415
|
+
}, async ({ confirmationId }) => {
|
|
416
|
+
const params = consumeConfirmation(confirmationId, "register");
|
|
417
|
+
if (!params) {
|
|
418
|
+
return {
|
|
419
|
+
content: [
|
|
420
|
+
{
|
|
421
|
+
type: "text",
|
|
422
|
+
text: "Confirmation not found or expired. Please run `register_domain` again.",
|
|
423
|
+
},
|
|
424
|
+
],
|
|
425
|
+
isError: true,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
428
|
+
const res = await client.post("/api/domains/register", params);
|
|
429
|
+
if (!res.success) {
|
|
430
|
+
return {
|
|
431
|
+
content: [{ type: "text", text: `Registration failed: ${res.error}` }],
|
|
432
|
+
isError: true,
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
const d = res.data;
|
|
436
|
+
const details = [
|
|
437
|
+
`✅ **Domain registered successfully!**`,
|
|
438
|
+
``,
|
|
439
|
+
`| Field | Value |`,
|
|
440
|
+
`|-------|-------|`,
|
|
441
|
+
d?.domain ? `| Domain | ${d.domain} |` : null,
|
|
442
|
+
d?.domainId ? `| Domain ID | ${d.domainId} |` : null,
|
|
443
|
+
d?.orderId ? `| Order ID | ${d.orderId} |` : null,
|
|
444
|
+
d?.invoiceId ? `| Invoice ID | ${d.invoiceId} |` : null,
|
|
445
|
+
d?.status ? `| Status | ${d.status} |` : null,
|
|
446
|
+
``,
|
|
447
|
+
`Use \`get_domain_details\` to see full domain information.`,
|
|
448
|
+
]
|
|
449
|
+
.filter(Boolean)
|
|
450
|
+
.join("\n");
|
|
451
|
+
return {
|
|
452
|
+
content: [{ type: "text", text: details }],
|
|
453
|
+
};
|
|
454
|
+
});
|
|
455
|
+
// 12. Confirm domain transfer
|
|
456
|
+
server.tool("confirm_domain_transfer", "Confirm and execute a pending domain transfer. Use the confirmation ID returned by transfer_domain.", {
|
|
457
|
+
confirmationId: z.string().describe("The confirmation ID from transfer_domain"),
|
|
458
|
+
}, async ({ confirmationId }) => {
|
|
459
|
+
const params = consumeConfirmation(confirmationId, "transfer");
|
|
460
|
+
if (!params) {
|
|
461
|
+
return {
|
|
462
|
+
content: [
|
|
463
|
+
{
|
|
464
|
+
type: "text",
|
|
465
|
+
text: "Confirmation not found or expired. Please run `transfer_domain` again.",
|
|
466
|
+
},
|
|
467
|
+
],
|
|
468
|
+
isError: true,
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
const res = await client.post("/api/domains/transfer", params);
|
|
472
|
+
if (!res.success) {
|
|
473
|
+
return {
|
|
474
|
+
content: [{ type: "text", text: `Transfer failed: ${res.error}` }],
|
|
475
|
+
isError: true,
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
const d = res.data;
|
|
479
|
+
const details = [
|
|
480
|
+
`✅ **Domain transfer initiated!**`,
|
|
481
|
+
``,
|
|
482
|
+
`| Field | Value |`,
|
|
483
|
+
`|-------|-------|`,
|
|
484
|
+
d?.domain ? `| Domain | ${d.domain} |` : null,
|
|
485
|
+
d?.domainId ? `| Domain ID | ${d.domainId} |` : null,
|
|
486
|
+
d?.orderId ? `| Order ID | ${d.orderId} |` : null,
|
|
487
|
+
d?.invoiceId ? `| Invoice ID | ${d.invoiceId} |` : null,
|
|
488
|
+
d?.status ? `| Status | ${d.status} |` : null,
|
|
489
|
+
``,
|
|
490
|
+
`Domain transfers typically take 5-7 days to complete.`,
|
|
491
|
+
`You will receive email updates as the transfer progresses.`,
|
|
492
|
+
]
|
|
493
|
+
.filter(Boolean)
|
|
494
|
+
.join("\n");
|
|
495
|
+
return {
|
|
496
|
+
content: [{ type: "text", text: details }],
|
|
497
|
+
};
|
|
498
|
+
});
|
|
499
|
+
}
|