Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | 3x 31x 4x 4x 4x 3x 1x 2x 3x 1x 31x 3x 3x 3x 2x 1x 31x 2x 2x 2x 1x 1x 31x 2x 2x 2x 1x 1x | import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import * as z from "zod/v4";
import type { SpaceshipClient } from "../spaceship-client.js";
import { normalizeDomain } from "../dns-utils.js";
import { toTextResult, toErrorResult } from "../tool-result.js";
export const registerPersonalNameserverTools = (server: McpServer, client: SpaceshipClient): void => {
server.registerTool(
"list_personal_nameservers",
{
title: "List Personal Nameservers",
description:
"List personal (vanity) nameservers configured for a domain (e.g. ns1.yourdomain.com, ns2.yourdomain.com).",
annotations: { readOnlyHint: true, openWorldHint: true },
inputSchema: z.object({
domain: z.string().min(4).max(255).describe("The domain name to list personal nameservers for."),
}),
},
async ({ domain }) => {
try {
const normalizedDomain = normalizeDomain(domain);
const nameservers = await client.listPersonalNameservers(normalizedDomain);
if (nameservers.length === 0) {
return toTextResult(`No personal nameservers configured for ${normalizedDomain}`);
}
return toTextResult(
[
`Personal nameservers for ${normalizedDomain}:`,
...nameservers.map(
(ns) => ` - ${ns.host}${ns.ips?.length ? ` (${ns.ips.join(", ")})` : ""}`,
),
].join("\n"),
{ nameservers } as Record<string, unknown>,
);
} catch (error) {
return toErrorResult(error);
}
},
);
server.registerTool(
"get_personal_nameserver",
{
title: "Get Personal Nameserver",
description:
"Get details of a single personal (vanity) nameserver by hostname, including its IP addresses.",
annotations: { readOnlyHint: true, openWorldHint: true },
inputSchema: z.object({
domain: z.string().min(4).max(255).describe("The parent domain name."),
host: z.string().min(1).describe('The nameserver hostname (e.g. "ns1.yourdomain.com").'),
}),
},
async ({ domain, host }) => {
try {
const normalizedDomain = normalizeDomain(domain);
const ns = await client.getPersonalNameserver(normalizedDomain, host);
return toTextResult(
`Personal nameserver: ${ns.host}${ns.ips?.length ? ` (${ns.ips.join(", ")})` : ""}`,
ns as unknown as Record<string, unknown>,
);
} catch (error) {
return toErrorResult(error);
}
},
);
server.registerTool(
"update_personal_nameserver",
{
title: "Update Personal Nameserver",
description:
"Create or update a personal nameserver host with its IP addresses. These are glue records that map a nameserver hostname (e.g. ns1.yourdomain.com) to IP addresses at the registry level.",
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
inputSchema: z.object({
domain: z.string().min(4).max(255).describe("The parent domain name."),
host: z.string().min(1).describe("The nameserver hostname (e.g. \"ns1.yourdomain.com\")."),
ips: z.array(z.string().min(1)).min(1).describe("Array of IP addresses for the nameserver glue record."),
}),
},
async ({ domain, host, ips }) => {
try {
const normalizedDomain = normalizeDomain(domain);
await client.updatePersonalNameserver(normalizedDomain, host, ips);
return toTextResult(
`Updated personal nameserver ${host} for ${normalizedDomain} with IPs: ${ips.join(", ")}`,
);
} catch (error) {
return toErrorResult(error);
}
},
);
server.registerTool(
"delete_personal_nameserver",
{
title: "Delete Personal Nameserver",
description:
"Delete a personal nameserver host from a domain. This removes the glue record at the registry. " +
"WARNING: If this nameserver is actively used by any domain, those domains will lose DNS resolution and experience downtime. " +
"Always confirm with the user before calling this tool.",
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true },
inputSchema: z.object({
domain: z.string().min(4).max(255).describe("The parent domain name."),
host: z.string().min(1).describe("The nameserver hostname to delete (e.g. \"ns1.yourdomain.com\")."),
}),
},
async ({ domain, host }) => {
try {
const normalizedDomain = normalizeDomain(domain);
await client.deletePersonalNameserver(normalizedDomain, host);
return toTextResult(
`Deleted personal nameserver ${host} from ${normalizedDomain}`,
);
} catch (error) {
return toErrorResult(error);
}
},
);
};
|