@agentdomain/mcp-server 0.5.0 → 0.6.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.
Files changed (3) hide show
  1. package/README.md +9 -4
  2. package/dist/index.js +587 -336
  3. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -21,17 +21,18 @@
21
21
  * }
22
22
  * }
23
23
  */
24
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
25
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
26
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
27
- import { z } from 'zod';
28
- import { AgentDomain } from '@agentdomain/sdk';
29
- import { AGENTDOMAIN_API_BASE_URL, SERVICE_PLAN_KEYS, SUPPORTED_FRAMEWORKS, SUPPORTED_TLDS, } from '@agentdomain/shared/constants';
30
- import { createPublicClient, createWalletClient, http } from 'viem';
31
- import { privateKeyToAccount } from 'viem/accounts';
32
- import { base, baseSepolia } from 'viem/chains';
24
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
25
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
26
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
27
+ import { z } from "zod";
28
+ import { AgentDomain } from "@agentdomain/sdk";
29
+ import { DNS_RECORD_TYPES, dnsRecordSchema, dnsRecordObjectSchema, } from "@agentdomain/shared";
30
+ import { AGENTDOMAIN_API_BASE_URL, SERVICE_PLAN_KEYS, SUPPORTED_FRAMEWORKS, SUPPORTED_TLDS, } from "@agentdomain/shared/constants";
31
+ import { createPublicClient, createWalletClient, http, } from "viem";
32
+ import { privateKeyToAccount } from "viem/accounts";
33
+ import { base, baseSepolia } from "viem/chains";
33
34
  const API_URL = process.env.AGENTDOMAIN_API_URL ?? AGENTDOMAIN_API_BASE_URL;
34
- const NETWORK = (process.env.AGENTDOMAIN_NETWORK ?? 'base');
35
+ const NETWORK = (process.env.AGENTDOMAIN_NETWORK ?? "base");
35
36
  const AGENT_PRIVATE_KEY = process.env.AGENT_PRIVATE_KEY;
36
37
  const AGENTDOMAIN_API_KEY = process.env.AGENTDOMAIN_API_KEY;
37
38
  const RENEWAL_VAULT_ADDRESS = process.env.RENEWAL_VAULT_ADDRESS;
@@ -44,466 +45,575 @@ function getClient() {
44
45
  };
45
46
  if (AGENT_PRIVATE_KEY) {
46
47
  const account = privateKeyToAccount(AGENT_PRIVATE_KEY);
47
- const chain = NETWORK === 'base' ? base : baseSepolia;
48
- const rpc = NETWORK === 'base' ? 'https://mainnet.base.org' : 'https://sepolia.base.org';
48
+ const chain = NETWORK === "base" ? base : baseSepolia;
49
+ const rpc = NETWORK === "base"
50
+ ? "https://mainnet.base.org"
51
+ : "https://sepolia.base.org";
49
52
  // Cast: viem's deeply-generic types do not always match cleanly across
50
53
  // duplicated installs in monorepos. Behaviour is identical at runtime.
51
- config.walletClient = createWalletClient({ account, chain, transport: http(rpc) });
52
- config.publicClient = createPublicClient({ chain, transport: http(rpc) });
54
+ config.walletClient = createWalletClient({
55
+ account,
56
+ chain,
57
+ transport: http(rpc),
58
+ });
59
+ config.publicClient = createPublicClient({
60
+ chain,
61
+ transport: http(rpc),
62
+ });
53
63
  }
54
64
  return new AgentDomain(config);
55
65
  }
56
- const server = new Server({ name: 'agentdomain-mcp', version: '0.2.1' }, { capabilities: { tools: {} } });
66
+ const server = new Server({ name: "agentdomain-mcp", version: "0.2.1" }, { capabilities: { tools: {} } });
57
67
  // ----------------------------------------------------------------------
58
68
  // TOOL DEFINITIONS
59
69
  // ----------------------------------------------------------------------
60
70
  const TOOLS = [
61
71
  {
62
- name: 'check_domain_availability',
63
- description: 'Check whether an agent domain (name + tld) is available for registration. Returns availability status and pricing.',
72
+ name: "check_domain_availability",
73
+ description: "Check whether an agent domain (name + tld) is available for registration. Returns availability status and pricing.",
64
74
  inputSchema: {
65
- type: 'object',
75
+ type: "object",
66
76
  properties: {
67
- name: { type: 'string', description: 'The desired label, e.g. "myagent"' },
77
+ name: {
78
+ type: "string",
79
+ description: 'The desired label, e.g. "myagent"',
80
+ },
68
81
  tld: {
69
- type: 'string',
82
+ type: "string",
70
83
  enum: SUPPORTED_TLDS,
71
- description: 'TLD',
84
+ description: "TLD",
72
85
  },
73
86
  },
74
- required: ['name'],
87
+ required: ["name"],
75
88
  },
76
89
  },
77
90
  {
78
- name: 'quote_registration',
79
- description: 'Get a price quote for registering an agent identity bundle. Domain, DNS, email, SSL, AgentID NFT orchestration, and platform fee are included by default. Basename and ENS are optional.',
91
+ name: "quote_registration",
92
+ description: "Get a price quote for registering an agent identity bundle. Domain, DNS, email, SSL, AgentID NFT orchestration, and platform fee are included by default. Basename and ENS are optional.",
80
93
  inputSchema: {
81
- type: 'object',
94
+ type: "object",
82
95
  properties: {
83
- preferredName: { type: 'string' },
84
- tld: { type: 'string', enum: SUPPORTED_TLDS },
96
+ preferredName: { type: "string" },
97
+ tld: { type: "string", enum: SUPPORTED_TLDS },
85
98
  registerBasename: {
86
- type: 'boolean',
87
- description: 'Set false to skip Basename registration and cost.',
99
+ type: "boolean",
100
+ description: "Set false to skip Basename registration and cost.",
88
101
  default: true,
89
102
  },
90
103
  registerEns: {
91
- type: 'boolean',
92
- description: 'Set true to add ENS; false skips ENS cost.',
104
+ type: "boolean",
105
+ description: "Set true to add ENS; false skips ENS cost.",
93
106
  default: false,
94
107
  },
95
108
  emailEnabled: {
96
- type: 'boolean',
97
- description: 'Deprecated compatibility flag. Email is now always included.',
109
+ type: "boolean",
110
+ description: "Deprecated compatibility flag. Email is now always included.",
98
111
  default: true,
99
112
  },
100
113
  emailUsername: {
101
- type: 'string',
102
- description: 'Primary email username. Defaults to agent, producing agent@domain.',
103
- default: 'agent',
114
+ type: "string",
115
+ description: "Primary email username. Defaults to agent, producing agent@domain.",
116
+ default: "agent",
104
117
  },
105
118
  premiumPlan: {
106
- type: 'string',
119
+ type: "string",
107
120
  enum: SERVICE_PLAN_KEYS,
108
- default: 'included',
109
- description: 'Premium Plan to buy with registration.',
121
+ default: "included",
122
+ description: "Premium Plan to buy with registration.",
110
123
  },
111
- years: { type: 'integer', default: 1, minimum: 1, maximum: 10 },
124
+ years: { type: "integer", default: 1, minimum: 1, maximum: 10 },
112
125
  },
113
- required: ['preferredName'],
126
+ required: ["preferredName"],
114
127
  },
115
128
  },
116
129
  {
117
- name: 'register_agent_identity',
118
- description: 'Register a complete agent identity bundle. Domain, DNS, email, SSL, AgentID NFT orchestration, and platform fee are included by default. Basename and ENS are optional. Pays in USDC on Base. Requires AGENT_PRIVATE_KEY env var.',
130
+ name: "register_agent_identity",
131
+ description: "Register a complete agent identity bundle. Domain, DNS, email, SSL, AgentID NFT orchestration, and platform fee are included by default. Basename and ENS are optional. Pays in USDC on Base. Requires AGENT_PRIVATE_KEY env var.",
119
132
  inputSchema: {
120
- type: 'object',
133
+ type: "object",
121
134
  properties: {
122
- preferredName: { type: 'string' },
123
- tld: { type: 'string', enum: SUPPORTED_TLDS },
135
+ preferredName: { type: "string" },
136
+ tld: { type: "string", enum: SUPPORTED_TLDS },
124
137
  registerBasename: {
125
- type: 'boolean',
126
- description: 'Set false to skip Basename registration and cost.',
138
+ type: "boolean",
139
+ description: "Set false to skip Basename registration and cost.",
127
140
  default: true,
128
141
  },
129
- basenameLabel: { type: 'string', description: 'Optional alternate Basename label' },
142
+ basenameLabel: {
143
+ type: "string",
144
+ description: "Optional alternate Basename label",
145
+ },
130
146
  registerEns: {
131
- type: 'boolean',
132
- description: 'Set true to add ENS; false skips ENS cost.',
147
+ type: "boolean",
148
+ description: "Set true to add ENS; false skips ENS cost.",
133
149
  default: false,
134
150
  },
135
- ensLabel: { type: 'string', description: 'Optional alternate ENS label' },
151
+ ensLabel: {
152
+ type: "string",
153
+ description: "Optional alternate ENS label",
154
+ },
136
155
  ownerAddress: {
137
- type: 'string',
138
- description: 'Optional EVM address to receive NFT ownership',
156
+ type: "string",
157
+ description: "Optional EVM address to receive NFT ownership",
139
158
  },
140
159
  emailEnabled: {
141
- type: 'boolean',
142
- description: 'Deprecated compatibility flag. Email is now always included.',
160
+ type: "boolean",
161
+ description: "Deprecated compatibility flag. Email is now always included.",
143
162
  default: true,
144
163
  },
145
164
  emailUsername: {
146
- type: 'string',
147
- description: 'Primary email username. Defaults to agent, producing agent@domain.',
148
- default: 'agent',
165
+ type: "string",
166
+ description: "Primary email username. Defaults to agent, producing agent@domain.",
167
+ default: "agent",
149
168
  },
150
169
  premiumPlan: {
151
- type: 'string',
170
+ type: "string",
152
171
  enum: SERVICE_PLAN_KEYS,
153
- default: 'included',
154
- description: 'Premium Plan to buy with registration.',
172
+ default: "included",
173
+ description: "Premium Plan to buy with registration.",
174
+ },
175
+ years: { type: "integer", default: 1, minimum: 1, maximum: 10 },
176
+ autoRenew: { type: "boolean", default: false },
177
+ dnsTarget: {
178
+ type: "string",
179
+ description: "URL or IP to point the domain at",
155
180
  },
156
- years: { type: 'integer', default: 1, minimum: 1, maximum: 10 },
157
- autoRenew: { type: 'boolean', default: false },
158
- dnsTarget: { type: 'string', description: 'URL or IP to point the domain at' },
159
181
  metadata: {
160
- type: 'object',
182
+ type: "object",
161
183
  properties: {
162
- name: { type: 'string' },
163
- description: { type: 'string' },
164
- capabilities: { type: 'array', items: { type: 'string' } },
165
- framework: { type: 'string', enum: SUPPORTED_FRAMEWORKS },
166
- x402Endpoint: { type: 'string' },
184
+ name: { type: "string" },
185
+ description: { type: "string" },
186
+ capabilities: { type: "array", items: { type: "string" } },
187
+ framework: { type: "string", enum: SUPPORTED_FRAMEWORKS },
188
+ x402Endpoint: { type: "string" },
167
189
  },
168
190
  },
169
191
  },
170
- required: ['preferredName'],
192
+ required: ["preferredName"],
171
193
  },
172
194
  },
173
195
  {
174
- name: 'lookup_agent',
175
- description: 'Look up agent identities by wallet address.',
196
+ name: "lookup_agent",
197
+ description: "Look up agent identities by wallet address.",
176
198
  inputSchema: {
177
- type: 'object',
199
+ type: "object",
178
200
  properties: {
179
- wallet: { type: 'string', description: '0x wallet address' },
201
+ wallet: { type: "string", description: "0x wallet address" },
180
202
  },
181
- required: ['wallet'],
203
+ required: ["wallet"],
182
204
  },
183
205
  },
184
206
  {
185
- name: 'get_agent',
186
- description: 'Get one agent identity by AgentDomain agent ID. Works with an agent-scoped API key.',
207
+ name: "get_agent",
208
+ description: "Get one agent identity by AgentDomain agent ID. Works with an agent-scoped API key.",
187
209
  inputSchema: {
188
- type: 'object',
210
+ type: "object",
189
211
  properties: {
190
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
212
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
191
213
  },
192
- required: ['agentId'],
214
+ required: ["agentId"],
193
215
  },
194
216
  },
195
217
  {
196
- name: 'search_agents',
197
- description: 'Search the public agent registry by name, capability, or framework.',
218
+ name: "search_agents",
219
+ description: "Search the public agent registry by name, capability, or framework.",
198
220
  inputSchema: {
199
- type: 'object',
221
+ type: "object",
200
222
  properties: {
201
- q: { type: 'string', description: 'Free-text query' },
202
- capability: { type: 'string' },
223
+ q: { type: "string", description: "Free-text query" },
224
+ capability: { type: "string" },
203
225
  framework: {
204
- type: 'string',
226
+ type: "string",
205
227
  enum: SUPPORTED_FRAMEWORKS,
206
228
  },
207
- limit: { type: 'number', default: 20 },
229
+ limit: { type: "number", default: 20 },
208
230
  },
209
231
  },
210
232
  },
211
233
  {
212
- name: 'send_agent_email',
234
+ name: "send_agent_email",
213
235
  description: "Send an email from an agent's address (requires email-enabled identity).",
214
236
  inputSchema: {
215
- type: 'object',
237
+ type: "object",
216
238
  properties: {
217
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
218
- to: { type: 'string' },
219
- subject: { type: 'string' },
220
- text: { type: 'string' },
239
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
240
+ to: { type: "string" },
241
+ subject: { type: "string" },
242
+ text: { type: "string" },
221
243
  fromAddress: {
222
- type: 'string',
223
- description: 'Optional primary or active alias address to send from.',
244
+ type: "string",
245
+ description: "Optional primary or active alias address to send from.",
224
246
  },
225
247
  },
226
- required: ['agentId', 'to', 'subject'],
248
+ required: ["agentId", "to", "subject"],
227
249
  },
228
250
  },
229
251
  {
230
- name: 'update_primary_email',
231
- description: 'Change the primary email username for an agent. The old primary address stops receiving new mail.',
252
+ name: "update_primary_email",
253
+ description: "Change the primary email username for an agent. The old primary address stops receiving new mail.",
232
254
  inputSchema: {
233
- type: 'object',
255
+ type: "object",
234
256
  properties: {
235
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
236
- username: { type: 'string', description: 'New primary local-part, e.g. agent or support' },
257
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
258
+ username: {
259
+ type: "string",
260
+ description: "New primary local-part, e.g. agent or support",
261
+ },
237
262
  },
238
- required: ['agentId', 'username'],
263
+ required: ["agentId", "username"],
239
264
  },
240
265
  },
241
266
  {
242
- name: 'send_agent_email_batch',
243
- description: 'Queue up to 100 emails in one request; each recipient counts toward monthly usage.',
267
+ name: "send_agent_email_batch",
268
+ description: "Queue up to 100 emails in one request; each recipient counts toward monthly usage.",
244
269
  inputSchema: {
245
- type: 'object',
270
+ type: "object",
246
271
  properties: {
247
- agentId: { type: 'string' },
272
+ agentId: { type: "string" },
248
273
  messages: {
249
- type: 'array',
274
+ type: "array",
250
275
  maxItems: 100,
251
276
  items: {
252
- type: 'object',
277
+ type: "object",
253
278
  properties: {
254
- to: { type: 'string' },
255
- subject: { type: 'string' },
256
- text: { type: 'string' },
257
- fromAddress: { type: 'string' },
279
+ to: { type: "string" },
280
+ subject: { type: "string" },
281
+ text: { type: "string" },
282
+ fromAddress: { type: "string" },
258
283
  },
259
- required: ['to', 'subject', 'text'],
284
+ required: ["to", "subject", "text"],
260
285
  },
261
286
  },
262
- idempotencyKey: { type: 'string' },
287
+ idempotencyKey: { type: "string" },
263
288
  },
264
- required: ['agentId', 'messages'],
289
+ required: ["agentId", "messages"],
265
290
  },
266
291
  },
267
292
  {
268
- name: 'get_agent_email_usage',
269
- description: 'Get combined sent and received monthly quota usage and reset date.',
293
+ name: "get_agent_email_usage",
294
+ description: "Get combined sent and received monthly quota usage and reset date.",
270
295
  inputSchema: {
271
- type: 'object',
272
- properties: { agentId: { type: 'string' } },
273
- required: ['agentId'],
296
+ type: "object",
297
+ properties: { agentId: { type: "string" } },
298
+ required: ["agentId"],
274
299
  },
275
300
  },
276
301
  {
277
- name: 'configure_email_webhook',
278
- description: 'Configure the signed email.received webhook for an agent.',
302
+ name: "configure_email_webhook",
303
+ description: "Configure the signed email.received webhook for an agent.",
279
304
  inputSchema: {
280
- type: 'object',
305
+ type: "object",
281
306
  properties: {
282
- agentId: { type: 'string' },
283
- url: { type: 'string' },
284
- payloadMode: { type: 'string', enum: ['metadata', 'inline_text'] },
285
- enabled: { type: 'boolean' },
307
+ agentId: { type: "string" },
308
+ url: { type: "string" },
309
+ payloadMode: { type: "string", enum: ["metadata", "inline_text"] },
310
+ enabled: { type: "boolean" },
286
311
  },
287
- required: ['agentId', 'url'],
312
+ required: ["agentId", "url"],
288
313
  },
289
314
  },
290
315
  {
291
- name: 'create_email_alias',
292
- description: 'Create an extra receive-and-send email alias. Requires paid-plan alias capacity.',
316
+ name: "create_email_alias",
317
+ description: "Create an extra receive-and-send email alias. Requires paid-plan alias capacity.",
293
318
  inputSchema: {
294
- type: 'object',
319
+ type: "object",
295
320
  properties: {
296
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
297
- username: { type: 'string', description: 'Alias local-part, e.g. billing' },
321
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
322
+ username: {
323
+ type: "string",
324
+ description: "Alias local-part, e.g. billing",
325
+ },
298
326
  },
299
- required: ['agentId', 'username'],
327
+ required: ["agentId", "username"],
300
328
  },
301
329
  },
302
330
  {
303
- name: 'delete_email_alias',
304
- description: 'Delete an active email alias from an agent.',
331
+ name: "delete_email_alias",
332
+ description: "Delete an active email alias from an agent.",
305
333
  inputSchema: {
306
- type: 'object',
334
+ type: "object",
307
335
  properties: {
308
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
309
- emailAddress: { type: 'string', description: 'Full alias address to delete' },
336
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
337
+ emailAddress: {
338
+ type: "string",
339
+ description: "Full alias address to delete",
340
+ },
310
341
  },
311
- required: ['agentId', 'emailAddress'],
342
+ required: ["agentId", "emailAddress"],
312
343
  },
313
344
  },
314
345
  {
315
- name: 'list_agent_email',
316
- description: 'List received/sent text-only email messages for an email-enabled agent, including extracted verification codes.',
346
+ name: "list_agent_email",
347
+ description: "List received/sent text-only email messages for an email-enabled agent, including extracted verification codes.",
317
348
  inputSchema: {
318
- type: 'object',
349
+ type: "object",
319
350
  properties: {
320
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
321
- limit: { type: 'number', default: 20 },
351
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
352
+ limit: { type: "number", default: 20 },
322
353
  },
323
- required: ['agentId'],
354
+ required: ["agentId"],
324
355
  },
325
356
  },
326
357
  {
327
- name: 'delete_agent_email',
328
- description: 'Permanently delete one email message from an agent inbox.',
358
+ name: "delete_agent_email",
359
+ description: "Permanently delete one email message from an agent inbox.",
329
360
  inputSchema: {
330
- type: 'object',
361
+ type: "object",
331
362
  properties: {
332
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
333
- messageId: { type: 'string', description: 'Email message ID (UUID)' },
363
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
364
+ messageId: { type: "string", description: "Email message ID (UUID)" },
334
365
  },
335
- required: ['agentId', 'messageId'],
366
+ required: ["agentId", "messageId"],
336
367
  },
337
368
  },
338
369
  {
339
- name: 'list_dns_records',
340
- description: 'List Spaceship-backed DNS records for an agent domain.',
370
+ name: "get_dns_capabilities",
371
+ description: "Get the machine-readable Spaceship DNS types, fields, limits, and safety warnings supported by AgentDomain.",
341
372
  inputSchema: {
342
- type: 'object',
373
+ type: "object",
343
374
  properties: {
344
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
375
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
345
376
  },
346
- required: ['agentId'],
377
+ required: ["agentId"],
347
378
  },
348
379
  },
349
380
  {
350
- name: 'create_dns_record',
351
- description: 'Create a user-managed DNS record and sync the full DNS state to Spaceship.',
381
+ name: "list_dns_records",
382
+ description: "List Spaceship-backed DNS records for an agent domain.",
352
383
  inputSchema: {
353
- type: 'object',
384
+ type: "object",
354
385
  properties: {
355
- agentId: { type: 'string' },
356
- type: { type: 'string', enum: ['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'TXT', 'NS', 'SRV'] },
357
- name: { type: 'string' },
358
- value: { type: 'string' },
359
- ttl: { type: 'number', default: 3600 },
360
- priority: { type: 'number' },
386
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
361
387
  },
362
- required: ['agentId', 'type', 'name', 'value'],
388
+ required: ["agentId"],
363
389
  },
364
390
  },
365
391
  {
366
- name: 'update_dns_record',
367
- description: 'Update a user-managed DNS record and sync the DNS state to Spaceship.',
392
+ name: "create_dns_record",
393
+ description: "Create a user-managed DNS record and sync the full DNS state to Spaceship.",
368
394
  inputSchema: {
369
- type: 'object',
395
+ type: "object",
370
396
  properties: {
371
- agentId: { type: 'string' },
372
- recordId: { type: 'string' },
373
- type: { type: 'string', enum: ['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'TXT', 'NS', 'SRV'] },
374
- name: { type: 'string' },
375
- value: { type: 'string' },
376
- ttl: { type: 'number' },
377
- priority: { type: 'number' },
397
+ agentId: { type: "string" },
398
+ type: { type: "string", enum: DNS_RECORD_TYPES },
399
+ name: { type: "string" },
400
+ value: {
401
+ type: "string",
402
+ description: "Legacy format; structured data is preferred",
403
+ },
404
+ data: {
405
+ type: "object",
406
+ description: "Type-specific structured DNS record data",
407
+ },
408
+ ttl: { type: "number", default: 3600 },
409
+ priority: { type: "number" },
410
+ },
411
+ required: ["agentId", "type", "name"],
412
+ },
413
+ },
414
+ {
415
+ name: "update_dns_record",
416
+ description: "Update a user-managed DNS record and sync the DNS state to Spaceship.",
417
+ inputSchema: {
418
+ type: "object",
419
+ properties: {
420
+ agentId: { type: "string" },
421
+ recordId: { type: "string" },
422
+ type: { type: "string", enum: DNS_RECORD_TYPES },
423
+ name: { type: "string" },
424
+ value: { type: "string" },
425
+ data: {
426
+ type: "object",
427
+ description: "Type-specific structured DNS record data",
428
+ },
429
+ ttl: { type: "number" },
430
+ priority: { type: "number" },
431
+ },
432
+ required: ["agentId", "recordId"],
433
+ },
434
+ },
435
+ {
436
+ name: "delete_dns_record",
437
+ description: "Delete a user-managed DNS record and sync the DNS state to Spaceship.",
438
+ inputSchema: {
439
+ type: "object",
440
+ properties: {
441
+ agentId: { type: "string" },
442
+ recordId: { type: "string" },
443
+ },
444
+ required: ["agentId", "recordId"],
445
+ },
446
+ },
447
+ {
448
+ name: "change_dns_records",
449
+ description: "Preview or apply an atomic DNS merge/replace batch. Apply requires the baseRevision returned by preview.",
450
+ inputSchema: {
451
+ type: "object",
452
+ properties: {
453
+ agentId: { type: "string" },
454
+ records: { type: "array", maxItems: 200, items: { type: "object" } },
455
+ mode: { type: "string", enum: ["merge", "replace"], default: "merge" },
456
+ dryRun: { type: "boolean", default: true },
457
+ baseRevision: {
458
+ type: "string",
459
+ description: "Required when dryRun is false",
460
+ },
461
+ },
462
+ required: ["agentId", "records"],
463
+ },
464
+ },
465
+ {
466
+ name: "import_dns_zone",
467
+ description: "Preview or apply a BIND zone import. System-managed records remain protected.",
468
+ inputSchema: {
469
+ type: "object",
470
+ properties: {
471
+ agentId: { type: "string" },
472
+ zoneFile: {
473
+ type: "string",
474
+ description: "BIND zone text, maximum 256 KiB",
475
+ },
476
+ mode: { type: "string", enum: ["merge", "replace"], default: "merge" },
477
+ dryRun: { type: "boolean", default: true },
478
+ baseRevision: {
479
+ type: "string",
480
+ description: "Required when dryRun is false",
481
+ },
378
482
  },
379
- required: ['agentId', 'recordId'],
483
+ required: ["agentId", "zoneFile"],
380
484
  },
381
485
  },
382
486
  {
383
- name: 'delete_dns_record',
384
- description: 'Delete a user-managed DNS record and sync the DNS state to Spaceship.',
487
+ name: "export_dns_zone",
488
+ description: "Export user-managed or permitted complete DNS state as a standard BIND zone file.",
385
489
  inputSchema: {
386
- type: 'object',
490
+ type: "object",
387
491
  properties: {
388
- agentId: { type: 'string' },
389
- recordId: { type: 'string' },
492
+ agentId: { type: "string" },
493
+ scope: { type: "string", enum: ["user", "all"], default: "user" },
390
494
  },
391
- required: ['agentId', 'recordId'],
495
+ required: ["agentId"],
392
496
  },
393
497
  },
394
498
  {
395
- name: 'reconfigure_ssl',
396
- description: 'Rebuild the Cloudflare SaaS SSL hostname and sync required DNS validation records.',
499
+ name: "reconfigure_ssl",
500
+ description: "Rebuild the Cloudflare SaaS SSL hostname and sync required DNS validation records.",
397
501
  inputSchema: {
398
- type: 'object',
502
+ type: "object",
399
503
  properties: {
400
- agentId: { type: 'string' },
504
+ agentId: { type: "string" },
401
505
  },
402
- required: ['agentId'],
506
+ required: ["agentId"],
403
507
  },
404
508
  },
405
509
  {
406
- name: 'fund_renewal_vault',
510
+ name: "fund_renewal_vault",
407
511
  description: "Deposit USDC into an agent's renewal vault to keep its domain alive.",
408
512
  inputSchema: {
409
- type: 'object',
513
+ type: "object",
410
514
  properties: {
411
- agentId: { type: 'string' },
412
- amountUsdc: { type: 'string', description: 'USDC amount, e.g. "10.00"' },
515
+ agentId: { type: "string" },
516
+ amountUsdc: {
517
+ type: "string",
518
+ description: 'USDC amount, e.g. "10.00"',
519
+ },
413
520
  },
414
- required: ['agentId', 'amountUsdc'],
521
+ required: ["agentId", "amountUsdc"],
415
522
  },
416
523
  },
417
524
  {
418
- name: 'withdraw_renewal_vault',
419
- description: 'Build the owner-signed withdrawal transaction for unused funds in an AgentID renewal vault.',
525
+ name: "withdraw_renewal_vault",
526
+ description: "Build the owner-signed withdrawal transaction for unused funds in an AgentID renewal vault.",
420
527
  inputSchema: {
421
- type: 'object',
528
+ type: "object",
422
529
  properties: {
423
- agentId: { type: 'string' },
424
- amountUsdc: { type: 'string', description: 'USDC amount, e.g. "5.00"' },
530
+ agentId: { type: "string" },
531
+ amountUsdc: { type: "string", description: 'USDC amount, e.g. "5.00"' },
425
532
  },
426
- required: ['agentId', 'amountUsdc'],
533
+ required: ["agentId", "amountUsdc"],
427
534
  },
428
535
  },
429
536
  {
430
- name: 'get_renewal_status',
431
- description: 'Get renewal vault status for an agent, including exact renewal amount, vault balance, missing deposit, expiry, and auto-renew readiness.',
537
+ name: "get_renewal_status",
538
+ description: "Get renewal vault status for an agent, including exact renewal amount, vault balance, missing deposit, expiry, and auto-renew readiness.",
432
539
  inputSchema: {
433
- type: 'object',
540
+ type: "object",
434
541
  properties: {
435
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
542
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
436
543
  },
437
- required: ['agentId'],
544
+ required: ["agentId"],
438
545
  },
439
546
  },
440
547
  {
441
- name: 'get_service_plan',
442
- description: 'Get the current AgentDomain Premium Plan, entitlement limits, billing interval, registry privacy, and recent purchases for one agent.',
548
+ name: "get_service_plan",
549
+ description: "Get the current AgentDomain Premium Plan, entitlement limits, billing interval, registry privacy, and recent purchases for one agent.",
443
550
  inputSchema: {
444
- type: 'object',
551
+ type: "object",
445
552
  properties: {
446
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
553
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
447
554
  },
448
- required: ['agentId'],
555
+ required: ["agentId"],
449
556
  },
450
557
  },
451
558
  {
452
- name: 'purchase_service_plan',
453
- description: 'Upgrade one agent to Starter, Pro, or Enterprise with x402 USDC. Requires AGENT_PRIVATE_KEY for the owner wallet.',
559
+ name: "purchase_service_plan",
560
+ description: "Upgrade one agent to Starter, Pro, or Enterprise with x402 USDC. Requires AGENT_PRIVATE_KEY for the owner wallet.",
454
561
  inputSchema: {
455
- type: 'object',
562
+ type: "object",
456
563
  properties: {
457
- agentId: { type: 'string' },
458
- plan: { type: 'string', enum: ['starter', 'pro', 'enterprise'] },
564
+ agentId: { type: "string" },
565
+ plan: { type: "string", enum: ["starter", "pro", "enterprise"] },
459
566
  planSku: {
460
- type: 'string',
461
- description: 'For Enterprise, e.g. enterprise-100000 through enterprise-5000000.',
567
+ type: "string",
568
+ description: "For Enterprise, e.g. enterprise-100000 through enterprise-5000000.",
462
569
  },
463
570
  },
464
- required: ['agentId', 'plan'],
571
+ required: ["agentId", "plan"],
465
572
  },
466
573
  },
467
574
  {
468
- name: 'set_registry_visibility',
469
- description: 'Hide or show one agent in the public AgentDomain registry. Hiding requires an active paid Premium Plan.',
575
+ name: "set_registry_visibility",
576
+ description: "Hide or show one agent in the public AgentDomain registry. Hiding requires an active paid Premium Plan.",
470
577
  inputSchema: {
471
- type: 'object',
578
+ type: "object",
472
579
  properties: {
473
- agentId: { type: 'string' },
580
+ agentId: { type: "string" },
474
581
  registryHidden: {
475
- type: 'boolean',
476
- description: 'true hides the agent from public registry/search; false makes it public',
582
+ type: "boolean",
583
+ description: "true hides the agent from public registry/search; false makes it public",
477
584
  },
478
585
  },
479
- required: ['agentId', 'registryHidden'],
586
+ required: ["agentId", "registryHidden"],
480
587
  },
481
588
  },
482
589
  {
483
- name: 'schedule_service_plan_renewal',
484
- description: 'Choose the exact Premium Plan SKU to charge at the next identity renewal, including any Enterprise email tier.',
590
+ name: "schedule_service_plan_renewal",
591
+ description: "Choose the exact Premium Plan SKU to charge at the next identity renewal, including any Enterprise email tier.",
485
592
  inputSchema: {
486
- type: 'object',
593
+ type: "object",
487
594
  properties: {
488
- agentId: { type: 'string' },
489
- plan: { type: 'string', enum: ['included', 'starter', 'pro', 'enterprise'] },
595
+ agentId: { type: "string" },
596
+ plan: {
597
+ type: "string",
598
+ enum: ["included", "starter", "pro", "enterprise"],
599
+ },
490
600
  planSku: {
491
- type: 'string',
492
- description: 'Exact SKU; Enterprise examples range from enterprise-100000 to enterprise-5000000.',
601
+ type: "string",
602
+ description: "Exact SKU; Enterprise examples range from enterprise-100000 to enterprise-5000000.",
493
603
  },
494
604
  },
495
- required: ['agentId', 'plan', 'planSku'],
605
+ required: ["agentId", "plan", "planSku"],
496
606
  },
497
607
  },
498
608
  {
499
- name: 'enable_auto_renew',
500
- description: 'Enable on-chain auto-renew for an agent. Requires the owner wallet private key and the RenewalVault contract address.',
609
+ name: "enable_auto_renew",
610
+ description: "Enable on-chain auto-renew for an agent. Requires the owner wallet private key and the RenewalVault contract address.",
501
611
  inputSchema: {
502
- type: 'object',
612
+ type: "object",
503
613
  properties: {
504
- agentId: { type: 'string', description: 'AgentDomain agent ID (UUID)' },
614
+ agentId: { type: "string", description: "AgentDomain agent ID (UUID)" },
505
615
  },
506
- required: ['agentId'],
616
+ required: ["agentId"],
507
617
  },
508
618
  },
509
619
  ];
@@ -518,36 +628,43 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
518
628
  const client = getClient();
519
629
  try {
520
630
  switch (name) {
521
- case 'check_domain_availability': {
631
+ case "check_domain_availability": {
522
632
  const a = z
523
- .object({ name: z.string(), tld: z.enum(SUPPORTED_TLDS).default('xyz') })
633
+ .object({
634
+ name: z.string(),
635
+ tld: z.enum(SUPPORTED_TLDS).default("xyz"),
636
+ })
524
637
  .parse(args);
525
638
  const result = await client.checkAvailability(a.name, { tld: a.tld });
526
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
639
+ return {
640
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
641
+ };
527
642
  }
528
- case 'quote_registration': {
643
+ case "quote_registration": {
529
644
  const a = z
530
645
  .object({
531
646
  preferredName: z.string(),
532
- tld: z.enum(SUPPORTED_TLDS).default('xyz'),
647
+ tld: z.enum(SUPPORTED_TLDS).default("xyz"),
533
648
  registerBasename: z.boolean().default(true),
534
649
  registerEns: z.boolean().default(false),
535
650
  emailEnabled: z.boolean().default(true),
536
651
  emailUsername: z.string().optional(),
537
- premiumPlan: z.enum(SERVICE_PLAN_KEYS).default('included'),
652
+ premiumPlan: z.enum(SERVICE_PLAN_KEYS).default("included"),
538
653
  years: z.number().int().min(1).max(10).default(1),
539
654
  })
540
655
  .parse(args);
541
656
  const result = await client.quote(a);
542
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
657
+ return {
658
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
659
+ };
543
660
  }
544
- case 'register_agent_identity': {
661
+ case "register_agent_identity": {
545
662
  if (!AGENT_PRIVATE_KEY) {
546
663
  return {
547
664
  isError: true,
548
665
  content: [
549
666
  {
550
- type: 'text',
667
+ type: "text",
551
668
  text: "AGENT_PRIVATE_KEY env var is required for registration. Set it to your agent's wallet private key.",
552
669
  },
553
670
  ],
@@ -556,7 +673,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
556
673
  const a = z
557
674
  .object({
558
675
  preferredName: z.string(),
559
- tld: z.enum(SUPPORTED_TLDS).default('xyz'),
676
+ tld: z.enum(SUPPORTED_TLDS).default("xyz"),
560
677
  registerBasename: z.boolean().default(true),
561
678
  basenameLabel: z.string().optional(),
562
679
  registerEns: z.boolean().default(false),
@@ -567,7 +684,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
567
684
  .optional(),
568
685
  emailEnabled: z.boolean().default(true),
569
686
  emailUsername: z.string().optional(),
570
- premiumPlan: z.enum(SERVICE_PLAN_KEYS).default('included'),
687
+ premiumPlan: z.enum(SERVICE_PLAN_KEYS).default("included"),
571
688
  years: z.number().int().min(1).max(10).default(1),
572
689
  autoRenew: z.boolean().default(false),
573
690
  dnsTarget: z.string().optional(),
@@ -581,19 +698,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
581
698
  ownerAddress: a.ownerAddress,
582
699
  metadata: a.metadata,
583
700
  });
584
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
701
+ return {
702
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
703
+ };
585
704
  }
586
- case 'lookup_agent': {
705
+ case "lookup_agent": {
587
706
  const a = z.object({ wallet: z.string() }).parse(args);
588
707
  const result = await client.getAgentsByWallet(a.wallet);
589
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
708
+ return {
709
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
710
+ };
590
711
  }
591
- case 'get_agent': {
712
+ case "get_agent": {
592
713
  const a = z.object({ agentId: z.string() }).parse(args);
593
714
  const result = await client.getAgentById(a.agentId);
594
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
715
+ return {
716
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
717
+ };
595
718
  }
596
- case 'search_agents': {
719
+ case "search_agents": {
597
720
  const a = z
598
721
  .object({
599
722
  q: z.string().optional(),
@@ -603,9 +726,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
603
726
  })
604
727
  .parse(args);
605
728
  const result = await client.search(a);
606
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
729
+ return {
730
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
731
+ };
607
732
  }
608
- case 'send_agent_email': {
733
+ case "send_agent_email": {
609
734
  const a = z
610
735
  .object({
611
736
  agentId: z.string(),
@@ -621,19 +746,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
621
746
  subject: a.subject,
622
747
  text: a.text,
623
748
  });
624
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
749
+ return {
750
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
751
+ };
625
752
  }
626
- case 'list_agent_email': {
627
- const a = z.object({ agentId: z.string(), limit: z.number().default(20) }).parse(args);
753
+ case "list_agent_email": {
754
+ const a = z
755
+ .object({ agentId: z.string(), limit: z.number().default(20) })
756
+ .parse(args);
628
757
  const result = await client.listEmail(a.agentId, { limit: a.limit });
629
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
758
+ return {
759
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
760
+ };
630
761
  }
631
- case 'delete_agent_email': {
632
- const a = z.object({ agentId: z.string().uuid(), messageId: z.string().uuid() }).parse(args);
762
+ case "delete_agent_email": {
763
+ const a = z
764
+ .object({ agentId: z.string().uuid(), messageId: z.string().uuid() })
765
+ .parse(args);
633
766
  const result = await client.deleteEmailMessage(a.agentId, a.messageId);
634
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
767
+ return {
768
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
769
+ };
635
770
  }
636
- case 'send_agent_email_batch': {
771
+ case "send_agent_email_batch": {
637
772
  const a = z
638
773
  .object({
639
774
  agentId: z.string(),
@@ -652,119 +787,213 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
652
787
  messages: a.messages,
653
788
  idempotencyKey: a.idempotencyKey,
654
789
  });
655
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
790
+ return {
791
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
792
+ };
656
793
  }
657
- case 'get_agent_email_usage': {
794
+ case "get_agent_email_usage": {
658
795
  const a = z.object({ agentId: z.string() }).parse(args);
659
796
  const result = await client.getEmailUsage(a.agentId);
660
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
797
+ return {
798
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
799
+ };
661
800
  }
662
- case 'configure_email_webhook': {
801
+ case "configure_email_webhook": {
663
802
  const a = z
664
803
  .object({
665
804
  agentId: z.string(),
666
805
  url: z.string().url(),
667
- payloadMode: z.enum(['metadata', 'inline_text']).default('metadata'),
806
+ payloadMode: z
807
+ .enum(["metadata", "inline_text"])
808
+ .default("metadata"),
668
809
  enabled: z.boolean().default(true),
669
810
  })
670
811
  .parse(args);
671
812
  const result = await client.setEmailWebhook(a.agentId, a);
672
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
813
+ return {
814
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
815
+ };
673
816
  }
674
- case 'update_primary_email': {
675
- const a = z.object({ agentId: z.string(), username: z.string() }).parse(args);
817
+ case "update_primary_email": {
818
+ const a = z
819
+ .object({ agentId: z.string(), username: z.string() })
820
+ .parse(args);
676
821
  const result = await client.updatePrimaryEmail(a.agentId, a.username);
677
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
822
+ return {
823
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
824
+ };
678
825
  }
679
- case 'create_email_alias': {
680
- const a = z.object({ agentId: z.string(), username: z.string() }).parse(args);
826
+ case "create_email_alias": {
827
+ const a = z
828
+ .object({ agentId: z.string(), username: z.string() })
829
+ .parse(args);
681
830
  const result = await client.createEmailAlias(a.agentId, a.username);
682
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
831
+ return {
832
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
833
+ };
683
834
  }
684
- case 'delete_email_alias': {
685
- const a = z.object({ agentId: z.string(), emailAddress: z.string().email() }).parse(args);
835
+ case "delete_email_alias": {
836
+ const a = z
837
+ .object({ agentId: z.string(), emailAddress: z.string().email() })
838
+ .parse(args);
686
839
  const result = await client.deleteEmailAlias(a.agentId, a.emailAddress);
687
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
840
+ return {
841
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
842
+ };
688
843
  }
689
- case 'list_dns_records': {
844
+ case "get_dns_capabilities": {
845
+ const a = z.object({ agentId: z.string() }).parse(args);
846
+ const result = await client.getDnsCapabilities(a.agentId);
847
+ return {
848
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
849
+ };
850
+ }
851
+ case "list_dns_records": {
690
852
  const a = z.object({ agentId: z.string() }).parse(args);
691
853
  const result = await client.listDnsRecords(a.agentId);
692
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
854
+ return {
855
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
856
+ };
693
857
  }
694
- case 'create_dns_record': {
858
+ case "create_dns_record": {
695
859
  const a = z
696
860
  .object({
697
861
  agentId: z.string(),
698
- type: z.enum(['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'TXT', 'NS', 'SRV']),
862
+ type: z.enum(DNS_RECORD_TYPES),
699
863
  name: z.string(),
700
- value: z.string(),
864
+ value: z.string().optional(),
865
+ data: z.record(z.unknown()).optional(),
701
866
  ttl: z.number().default(3600),
702
867
  priority: z.number().optional(),
703
868
  })
704
869
  .parse(args);
705
- const result = await client.createDnsRecord(a.agentId, {
706
- type: a.type,
707
- name: a.name,
708
- value: a.value,
709
- ttl: a.ttl,
710
- priority: a.priority,
711
- });
712
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
870
+ const { agentId, ...record } = a;
871
+ const result = await client.createDnsRecord(agentId, dnsRecordSchema.parse(record));
872
+ return {
873
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
874
+ };
713
875
  }
714
- case 'update_dns_record': {
876
+ case "update_dns_record": {
715
877
  const a = z
716
878
  .object({
717
879
  agentId: z.string(),
718
880
  recordId: z.string(),
719
- type: z.enum(['A', 'AAAA', 'ALIAS', 'CNAME', 'MX', 'TXT', 'NS', 'SRV']).optional(),
881
+ type: z.enum(DNS_RECORD_TYPES).optional(),
720
882
  name: z.string().optional(),
721
883
  value: z.string().optional(),
884
+ data: z.record(z.unknown()).optional(),
722
885
  ttl: z.number().optional(),
723
886
  priority: z.number().optional(),
724
887
  })
725
888
  .parse(args);
726
889
  const { agentId, recordId, ...record } = a;
727
- const result = await client.updateDnsRecord(agentId, recordId, record);
728
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
890
+ const result = await client.updateDnsRecord(agentId, recordId, dnsRecordObjectSchema
891
+ .partial()
892
+ .parse(record));
893
+ return {
894
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
895
+ };
729
896
  }
730
- case 'delete_dns_record': {
731
- const a = z.object({ agentId: z.string(), recordId: z.string() }).parse(args);
897
+ case "delete_dns_record": {
898
+ const a = z
899
+ .object({ agentId: z.string(), recordId: z.string() })
900
+ .parse(args);
732
901
  const result = await client.deleteDnsRecord(a.agentId, a.recordId);
733
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
902
+ return {
903
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
904
+ };
905
+ }
906
+ case "change_dns_records": {
907
+ const a = z
908
+ .object({
909
+ agentId: z.string(),
910
+ records: z.array(dnsRecordSchema).min(1).max(200),
911
+ mode: z.enum(["merge", "replace"]).default("merge"),
912
+ dryRun: z.boolean().default(true),
913
+ baseRevision: z.string().length(64).optional(),
914
+ })
915
+ .parse(args);
916
+ const result = a.dryRun
917
+ ? await client.previewDnsBatch(a.agentId, a.records, a.mode)
918
+ : await client.applyDnsBatch(a.agentId, a.records, requireDnsRevision(a.baseRevision), a.mode);
919
+ return {
920
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
921
+ };
734
922
  }
735
- case 'reconfigure_ssl': {
923
+ case "import_dns_zone": {
924
+ const a = z
925
+ .object({
926
+ agentId: z.string(),
927
+ zoneFile: z.string().min(1).max(262_144),
928
+ mode: z.enum(["merge", "replace"]).default("merge"),
929
+ dryRun: z.boolean().default(true),
930
+ baseRevision: z.string().length(64).optional(),
931
+ })
932
+ .parse(args);
933
+ const result = a.dryRun
934
+ ? await client.previewDnsImport(a.agentId, a.zoneFile, a.mode)
935
+ : await client.applyDnsImport(a.agentId, a.zoneFile, requireDnsRevision(a.baseRevision), a.mode);
936
+ return {
937
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
938
+ };
939
+ }
940
+ case "export_dns_zone": {
941
+ const a = z
942
+ .object({
943
+ agentId: z.string(),
944
+ scope: z.enum(["user", "all"]).default("user"),
945
+ })
946
+ .parse(args);
947
+ const result = await client.exportDnsZone(a.agentId, a.scope);
948
+ return { content: [{ type: "text", text: result }] };
949
+ }
950
+ case "reconfigure_ssl": {
736
951
  const a = z.object({ agentId: z.string() }).parse(args);
737
952
  const result = await client.reconfigureSsl(a.agentId);
738
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
953
+ return {
954
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
955
+ };
739
956
  }
740
- case 'fund_renewal_vault': {
741
- const a = z.object({ agentId: z.string(), amountUsdc: z.string() }).parse(args);
957
+ case "fund_renewal_vault": {
958
+ const a = z
959
+ .object({ agentId: z.string(), amountUsdc: z.string() })
960
+ .parse(args);
742
961
  const result = await client.fundRenewalVault(a.agentId, a.amountUsdc);
743
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
962
+ return {
963
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
964
+ };
744
965
  }
745
- case 'withdraw_renewal_vault': {
746
- const a = z.object({ agentId: z.string(), amountUsdc: z.string() }).parse(args);
966
+ case "withdraw_renewal_vault": {
967
+ const a = z
968
+ .object({ agentId: z.string(), amountUsdc: z.string() })
969
+ .parse(args);
747
970
  const result = await client.withdrawFromVault(a.agentId, a.amountUsdc);
748
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
971
+ return {
972
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
973
+ };
749
974
  }
750
- case 'get_renewal_status': {
975
+ case "get_renewal_status": {
751
976
  const a = z.object({ agentId: z.string() }).parse(args);
752
977
  const result = await client.getRenewalStatus(a.agentId);
753
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
978
+ return {
979
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
980
+ };
754
981
  }
755
- case 'get_service_plan': {
982
+ case "get_service_plan": {
756
983
  const a = z.object({ agentId: z.string() }).parse(args);
757
984
  const result = await client.getServicePlan(a.agentId);
758
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
985
+ return {
986
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
987
+ };
759
988
  }
760
- case 'purchase_service_plan': {
989
+ case "purchase_service_plan": {
761
990
  if (!AGENT_PRIVATE_KEY) {
762
991
  return {
763
992
  isError: true,
764
993
  content: [
765
994
  {
766
- type: 'text',
767
- text: 'AGENT_PRIVATE_KEY env var is required to purchase a Premium Plan.',
995
+ type: "text",
996
+ text: "AGENT_PRIVATE_KEY env var is required to purchase a Premium Plan.",
768
997
  },
769
998
  ],
770
999
  };
@@ -772,23 +1001,31 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
772
1001
  const a = z
773
1002
  .object({
774
1003
  agentId: z.string(),
775
- plan: z.enum(['starter', 'pro', 'enterprise']),
776
- planSku: z.custom().optional(),
1004
+ plan: z.enum(["starter", "pro", "enterprise"]),
1005
+ planSku: z
1006
+ .custom()
1007
+ .optional(),
777
1008
  })
778
1009
  .parse(args);
779
1010
  const result = await client.purchaseServicePlan(a);
780
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
1011
+ return {
1012
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1013
+ };
781
1014
  }
782
- case 'set_registry_visibility': {
783
- const a = z.object({ agentId: z.string(), registryHidden: z.boolean() }).parse(args);
1015
+ case "set_registry_visibility": {
1016
+ const a = z
1017
+ .object({ agentId: z.string(), registryHidden: z.boolean() })
1018
+ .parse(args);
784
1019
  const result = await client.setRegistryVisibility(a.agentId, a.registryHidden);
785
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
1020
+ return {
1021
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1022
+ };
786
1023
  }
787
- case 'schedule_service_plan_renewal': {
1024
+ case "schedule_service_plan_renewal": {
788
1025
  const a = z
789
1026
  .object({
790
1027
  agentId: z.string().uuid(),
791
- plan: z.enum(['included', 'starter', 'pro', 'enterprise']),
1028
+ plan: z.enum(["included", "starter", "pro", "enterprise"]),
792
1029
  planSku: z.custom(),
793
1030
  })
794
1031
  .parse(args);
@@ -796,16 +1033,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
796
1033
  plan: a.plan,
797
1034
  planSku: a.planSku,
798
1035
  });
799
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
1036
+ return {
1037
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1038
+ };
800
1039
  }
801
- case 'enable_auto_renew': {
1040
+ case "enable_auto_renew": {
802
1041
  if (!AGENT_PRIVATE_KEY) {
803
1042
  return {
804
1043
  isError: true,
805
1044
  content: [
806
1045
  {
807
- type: 'text',
808
- text: 'AGENT_PRIVATE_KEY env var is required to enable auto-renew. Use the owner wallet private key.',
1046
+ type: "text",
1047
+ text: "AGENT_PRIVATE_KEY env var is required to enable auto-renew. Use the owner wallet private key.",
809
1048
  },
810
1049
  ],
811
1050
  };
@@ -815,39 +1054,51 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
815
1054
  isError: true,
816
1055
  content: [
817
1056
  {
818
- type: 'text',
819
- text: 'RENEWAL_VAULT_ADDRESS env var is required to enable auto-renew on-chain.',
1057
+ type: "text",
1058
+ text: "RENEWAL_VAULT_ADDRESS env var is required to enable auto-renew on-chain.",
820
1059
  },
821
1060
  ],
822
1061
  };
823
1062
  }
824
1063
  const a = z.object({ agentId: z.string() }).parse(args);
825
1064
  const result = await client.setAutoRenew(a.agentId, true);
826
- return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
1065
+ return {
1066
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
1067
+ };
827
1068
  }
828
1069
  default:
829
1070
  return {
830
1071
  isError: true,
831
- content: [{ type: 'text', text: `Unknown tool: ${name}` }],
1072
+ content: [{ type: "text", text: `Unknown tool: ${name}` }],
832
1073
  };
833
1074
  }
834
1075
  }
835
1076
  catch (e) {
836
1077
  return {
837
1078
  isError: true,
838
- content: [{ type: 'text', text: `Error: ${e instanceof Error ? e.message : String(e)}` }],
1079
+ content: [
1080
+ {
1081
+ type: "text",
1082
+ text: `Error: ${e instanceof Error ? e.message : String(e)}`,
1083
+ },
1084
+ ],
839
1085
  };
840
1086
  }
841
1087
  });
842
1088
  // ----------------------------------------------------------------------
843
1089
  // MAIN
844
1090
  // ----------------------------------------------------------------------
1091
+ function requireDnsRevision(value) {
1092
+ if (!value)
1093
+ throw new Error("Apply requires baseRevision from a fresh DNS dry-run preview.");
1094
+ return value;
1095
+ }
845
1096
  async function main() {
846
1097
  const transport = new StdioServerTransport();
847
1098
  await server.connect(transport);
848
- console.error('AgentDomain MCP server running on stdio');
1099
+ console.error("AgentDomain MCP server running on stdio");
849
1100
  }
850
1101
  main().catch((e) => {
851
- console.error('Fatal:', e);
1102
+ console.error("Fatal:", e);
852
1103
  process.exit(1);
853
1104
  });