@centrali-io/centrali-mcp 4.2.5 → 4.2.7

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.
@@ -63,9 +63,9 @@ function registerComputeTools(server, sdk) {
63
63
  };
64
64
  }
65
65
  }));
66
- server.tool("list_triggers", "List function triggers in the workspace. Triggers define how and when compute functions are executed (on-demand, event-driven, scheduled, webhook).", {
66
+ server.tool("list_triggers", "List function triggers in the workspace. Triggers define how and when compute functions are executed (on-demand, event-driven, scheduled, http-trigger).", {
67
67
  executionType: zod_1.z
68
- .enum(["on-demand", "event-driven", "scheduled", "webhook"])
68
+ .enum(["on-demand", "event-driven", "scheduled", "http-trigger"])
69
69
  .optional()
70
70
  .describe("Filter by trigger execution type"),
71
71
  page: zod_1.z.number().optional().describe("Page number"),
@@ -155,17 +155,16 @@ function registerComputeTools(server, sdk) {
155
155
  }));
156
156
  server.tool("create_function", "Create a new compute function. Compute functions are JavaScript code blocks that run server-side.", {
157
157
  name: zod_1.z.string().describe("Display name for the function"),
158
- slug: zod_1.z.string().describe("URL-safe unique identifier (e.g., 'process-order')"),
159
158
  code: zod_1.z.string().describe("JavaScript source code. Must export an async function: module.exports = async (ctx) => { ... }"),
160
159
  description: zod_1.z.string().optional().describe("Optional description of what the function does"),
161
- timeout: zod_1.z.number().optional().describe("Execution timeout in milliseconds (default: 30000)"),
162
- }, (_a) => __awaiter(this, [_a], void 0, function* ({ name, slug, code, description, timeout }) {
160
+ timeoutMs: zod_1.z.number().optional().describe("Execution timeout in milliseconds (default: 30000, min: 1000, max: 300000)"),
161
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ name, code, description, timeoutMs }) {
163
162
  try {
164
- const input = { name, slug, code };
163
+ const input = { name, code };
165
164
  if (description !== undefined)
166
165
  input.description = description;
167
- if (timeout !== undefined)
168
- input.timeout = timeout;
166
+ if (timeoutMs !== undefined)
167
+ input.timeoutMs = timeoutMs;
169
168
  const result = yield sdk.functions.create(input);
170
169
  return {
171
170
  content: [
@@ -178,7 +177,7 @@ function registerComputeTools(server, sdk) {
178
177
  content: [
179
178
  {
180
179
  type: "text",
181
- text: formatError(error, `creating function '${slug}'`),
180
+ text: formatError(error, `creating function '${name}'`),
182
181
  },
183
182
  ],
184
183
  isError: true,
@@ -190,8 +189,8 @@ function registerComputeTools(server, sdk) {
190
189
  name: zod_1.z.string().optional().describe("Updated display name"),
191
190
  description: zod_1.z.string().optional().describe("Updated description"),
192
191
  code: zod_1.z.string().optional().describe("Updated JavaScript source code"),
193
- timeout: zod_1.z.number().optional().describe("Updated execution timeout in milliseconds"),
194
- }, (_a) => __awaiter(this, [_a], void 0, function* ({ functionId, name, description, code, timeout }) {
192
+ timeoutMs: zod_1.z.number().optional().describe("Updated execution timeout in milliseconds (min: 1000, max: 300000)"),
193
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ functionId, name, description, code, timeoutMs }) {
195
194
  try {
196
195
  const input = {};
197
196
  if (name !== undefined)
@@ -200,8 +199,8 @@ function registerComputeTools(server, sdk) {
200
199
  input.description = description;
201
200
  if (code !== undefined)
202
201
  input.code = code;
203
- if (timeout !== undefined)
204
- input.timeout = timeout;
202
+ if (timeoutMs !== undefined)
203
+ input.timeoutMs = timeoutMs;
205
204
  const result = yield sdk.functions.update(functionId, input);
206
205
  return {
207
206
  content: [
@@ -249,15 +248,18 @@ function registerComputeTools(server, sdk) {
249
248
  }));
250
249
  server.tool("test_function", "Test execute code without saving it as a function. Useful for validating function code before creating or updating.", {
251
250
  code: zod_1.z.string().describe("JavaScript code to test. Must export an async function: module.exports = async (ctx) => { ... }"),
252
- input: zod_1.z
251
+ params: zod_1.z
253
252
  .record(zod_1.z.string(), zod_1.z.any())
254
253
  .optional()
255
- .describe("Optional input data passed to the function as ctx.input"),
256
- }, (_a) => __awaiter(this, [_a], void 0, function* ({ code, input }) {
254
+ .describe("Optional parameters passed to the function as executionParams"),
255
+ timeoutMs: zod_1.z.number().optional().describe("Execution timeout in milliseconds (default: 30000, min: 1000, max: 300000)"),
256
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ code, params, timeoutMs }) {
257
257
  try {
258
258
  const testInput = { code };
259
- if (input !== undefined)
260
- testInput.input = input;
259
+ if (params !== undefined)
260
+ testInput.params = params;
261
+ if (timeoutMs !== undefined)
262
+ testInput.timeoutMs = timeoutMs;
261
263
  const result = yield sdk.functions.testExecute(testInput);
262
264
  return {
263
265
  content: [
@@ -305,13 +307,13 @@ function registerComputeTools(server, sdk) {
305
307
  name: zod_1.z.string().describe("Display name for the trigger"),
306
308
  functionId: zod_1.z.string().describe("The compute function ID (UUID) to execute"),
307
309
  executionType: zod_1.z
308
- .enum(["on-demand", "event-driven", "scheduled", "webhook"])
309
- .describe("How the trigger fires: on-demand (manual), event-driven (data events), scheduled (cron), or webhook (HTTP)"),
310
+ .enum(["on-demand", "event-driven", "scheduled", "http-trigger"])
311
+ .describe("How the trigger fires: on-demand (manual), event-driven (data events), scheduled (cron), or http-trigger (external HTTP POST)"),
310
312
  description: zod_1.z.string().optional().describe("Optional description"),
311
313
  triggerMetadata: zod_1.z
312
314
  .record(zod_1.z.string(), zod_1.z.any())
313
315
  .optional()
314
- .describe("Type-specific configuration. For event-driven: { event, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For webhook: auto-generated URL."),
316
+ .describe("Type-specific configuration. For event-driven: { event, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For http-trigger: auto-generated URL."),
315
317
  enabled: zod_1.z.boolean().optional().describe("Whether the trigger is enabled (default: true)"),
316
318
  }, (_a) => __awaiter(this, [_a], void 0, function* ({ name, functionId, executionType, description, triggerMetadata, enabled }) {
317
319
  try {
@@ -452,4 +454,75 @@ function registerComputeTools(server, sdk) {
452
454
  };
453
455
  }
454
456
  }));
457
+ // ── Allowed Domains tools ──────────────────────────────────────────
458
+ server.tool("list_allowed_domains", "List all allowed domains for compute function HTTP requests. Functions can only call external APIs on domains in this allowlist.", {}, () => __awaiter(this, void 0, void 0, function* () {
459
+ try {
460
+ const result = yield sdk.allowedDomains.list();
461
+ return {
462
+ content: [
463
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
464
+ ],
465
+ };
466
+ }
467
+ catch (error) {
468
+ return {
469
+ content: [
470
+ {
471
+ type: "text",
472
+ text: formatError(error, "listing allowed domains"),
473
+ },
474
+ ],
475
+ isError: true,
476
+ };
477
+ }
478
+ }));
479
+ server.tool("add_allowed_domain", "Add a domain to the allowlist so compute functions can make HTTP requests to it. Supports wildcards (e.g., '*.example.com').", {
480
+ domain: zod_1.z.string().describe("Domain to allow (e.g., 'api.stripe.com' or '*.googleapis.com')"),
481
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ domain }) {
482
+ try {
483
+ const result = yield sdk.allowedDomains.add({ domain });
484
+ return {
485
+ content: [
486
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
487
+ ],
488
+ };
489
+ }
490
+ catch (error) {
491
+ return {
492
+ content: [
493
+ {
494
+ type: "text",
495
+ text: formatError(error, `adding allowed domain '${domain}'`),
496
+ },
497
+ ],
498
+ isError: true,
499
+ };
500
+ }
501
+ }));
502
+ server.tool("remove_allowed_domain", "Remove a domain from the allowlist. Compute functions will no longer be able to call this domain.", {
503
+ domainId: zod_1.z.string().describe("The allowed domain ID (UUID) to remove"),
504
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ domainId }) {
505
+ try {
506
+ yield sdk.allowedDomains.remove(domainId);
507
+ return {
508
+ content: [
509
+ {
510
+ type: "text",
511
+ text: `Allowed domain '${domainId}' removed successfully.`,
512
+ },
513
+ ],
514
+ };
515
+ }
516
+ catch (error) {
517
+ return {
518
+ content: [
519
+ {
520
+ type: "text",
521
+ text: formatError(error, `removing allowed domain '${domainId}'`),
522
+ },
523
+ ],
524
+ isError: true,
525
+ };
526
+ }
527
+ }));
455
528
  }
@@ -62,7 +62,7 @@ function registerDescribeTools(server) {
62
62
  tools: ["search_records"],
63
63
  },
64
64
  compute: {
65
- summary: "Server-side JavaScript functions with triggers (on-demand, event-driven, scheduled, webhook).",
65
+ summary: "Server-side JavaScript functions with triggers (on-demand, event-driven, scheduled, http-trigger) and domain allowlisting for external API calls.",
66
66
  describeWith: "describe_compute",
67
67
  tools: [
68
68
  "list_functions",
@@ -79,6 +79,9 @@ function registerDescribeTools(server) {
79
79
  "invoke_trigger",
80
80
  "pause_trigger",
81
81
  "resume_trigger",
82
+ "list_allowed_domains",
83
+ "add_allowed_domain",
84
+ "remove_allowed_domain",
82
85
  ],
83
86
  },
84
87
  smart_queries: {
@@ -211,8 +214,8 @@ function registerDescribeTools(server) {
211
214
  },
212
215
  crud_tools: {
213
216
  create_collection: {
214
- description: "Create a new collection with name, slug, properties, and optional settings",
215
- required_params: ["name", "slug"],
217
+ description: "Create a new collection with name, recordSlug, properties, and optional settings",
218
+ required_params: ["name", "recordSlug"],
216
219
  optional_params: ["description", "properties", "enableVersioning", "schemaDiscoveryMode", "tags"],
217
220
  },
218
221
  update_collection: {
@@ -369,11 +372,14 @@ function registerDescribeTools(server) {
369
372
  function_shape: {
370
373
  id: "UUID",
371
374
  name: "string — display name",
372
- slug: "string — unique identifier",
373
375
  description: "string | null",
374
376
  code: "string — the JavaScript source code",
375
- status: "'active' | 'inactive'",
376
- testPayload: "object | null — sample payload for testing",
377
+ timeoutMs: "number | null — execution timeout in milliseconds (default: 30000, max: 300000)",
378
+ workspaceSlug: "string",
379
+ createdBy: "UUID",
380
+ updatedBy: "UUID | null",
381
+ createdAt: "ISO 8601 datetime",
382
+ updatedAt: "ISO 8601 datetime",
377
383
  },
378
384
  trigger_types: {
379
385
  "on-demand": {
@@ -398,18 +404,24 @@ function registerDescribeTools(server) {
398
404
  description: "Runs on a cron schedule (e.g., every hour, daily at midnight).",
399
405
  config: "Uses standard cron expression syntax (e.g., '0 * * * *' for hourly)",
400
406
  },
401
- webhook: {
407
+ "http-trigger": {
402
408
  description: "Triggered by an external HTTP POST to a generated webhook URL.",
403
- config: "Each webhook trigger gets a unique URL to share with external services",
409
+ config: "Each http-trigger gets a unique URL to share with external services",
404
410
  },
405
411
  },
406
412
  trigger_shape: {
407
413
  id: "UUID",
408
414
  name: "string",
415
+ description: "string | null",
409
416
  functionId: "UUID — the compute function to execute",
410
- executionType: "'on-demand' | 'event-driven' | 'scheduled' | 'webhook'",
411
- status: "'active' | 'paused'",
412
- config: "objecttype-specific configuration (cron, event filters, etc.)",
417
+ executionType: "'on-demand' | 'event-driven' | 'scheduled' | 'http-trigger'",
418
+ triggerMetadata: "object type-specific configuration (event, cron, params, etc.)",
419
+ enabled: "booleanwhether the trigger is active (default: true)",
420
+ workspaceSlug: "string",
421
+ createdBy: "UUID",
422
+ updatedBy: "UUID",
423
+ createdAt: "ISO 8601 datetime",
424
+ updatedAt: "ISO 8601 datetime",
413
425
  },
414
426
  function_crud: {
415
427
  get_function: {
@@ -418,14 +430,14 @@ function registerDescribeTools(server) {
418
430
  },
419
431
  create_function: {
420
432
  description: "Create a new compute function",
421
- required_params: ["name", "slug", "code"],
422
- optional_params: ["description", "timeout"],
433
+ required_params: ["name", "code"],
434
+ optional_params: ["description", "timeoutMs"],
423
435
  code_format: "module.exports = async (ctx) => { /* your code */ return result; }",
424
436
  },
425
437
  update_function: {
426
438
  description: "Update an existing function. Partial updates supported.",
427
439
  required_params: ["functionId"],
428
- optional_params: ["name", "description", "code", "timeout"],
440
+ optional_params: ["name", "description", "code", "timeoutMs"],
429
441
  },
430
442
  delete_function: {
431
443
  description: "Delete a compute function by ID",
@@ -434,7 +446,7 @@ function registerDescribeTools(server) {
434
446
  test_function: {
435
447
  description: "Test execute code without saving. Returns output, duration, and logs.",
436
448
  required_params: ["code"],
437
- optional_params: ["input"],
449
+ optional_params: ["params", "timeoutMs"],
438
450
  },
439
451
  },
440
452
  trigger_crud: {
@@ -469,6 +481,30 @@ function registerDescribeTools(server) {
469
481
  required_params: ["triggerId"],
470
482
  },
471
483
  },
484
+ allowed_domains: {
485
+ description: "Workspace-level allowlist controlling which external domains compute functions can call via api.httpGet/httpPost/etc. Functions attempting to reach unlisted domains get an error.",
486
+ domain_shape: {
487
+ id: "UUID",
488
+ domain: "string — the allowed domain (e.g., 'api.stripe.com' or '*.googleapis.com')",
489
+ createdAt: "ISO 8601 datetime",
490
+ createdBy: "UUID",
491
+ },
492
+ tools: {
493
+ list_allowed_domains: {
494
+ description: "List all allowed domains in the workspace",
495
+ },
496
+ add_allowed_domain: {
497
+ description: "Add a domain to the allowlist",
498
+ required_params: ["domain"],
499
+ },
500
+ remove_allowed_domain: {
501
+ description: "Remove a domain from the allowlist by ID",
502
+ required_params: ["domainId"],
503
+ },
504
+ },
505
+ wildcards: "Use '*.example.com' to allow all subdomains of example.com",
506
+ note: "Functions can only make HTTP requests to domains on this list. Add domains before creating functions that call external APIs.",
507
+ },
472
508
  sandbox_api: {
473
509
  description: "Functions receive an `api` object with built-in utilities. Key crypto methods:",
474
510
  crypto: {
@@ -488,6 +524,7 @@ function registerDescribeTools(server) {
488
524
  "Use test_function to validate code before creating or updating a function",
489
525
  "Use create_function + create_trigger together to set up a complete compute pipeline",
490
526
  "Use api.crypto.signJwt() for GitHub App, Google Cloud, or Azure AD authentication flows",
527
+ "Before creating functions that call external APIs, add the target domains with add_allowed_domain",
491
528
  ],
492
529
  }, null, 2),
493
530
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centrali-io/centrali-mcp",
3
- "version": "4.2.5",
3
+ "version": "4.2.7",
4
4
  "description": "Centrali MCP Server - AI assistant integration for Centrali workspaces",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
@@ -61,10 +61,10 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
61
61
 
62
62
  server.tool(
63
63
  "list_triggers",
64
- "List function triggers in the workspace. Triggers define how and when compute functions are executed (on-demand, event-driven, scheduled, webhook).",
64
+ "List function triggers in the workspace. Triggers define how and when compute functions are executed (on-demand, event-driven, scheduled, http-trigger).",
65
65
  {
66
66
  executionType: z
67
- .enum(["on-demand", "event-driven", "scheduled", "webhook"])
67
+ .enum(["on-demand", "event-driven", "scheduled", "http-trigger"])
68
68
  .optional()
69
69
  .describe("Filter by trigger execution type"),
70
70
  page: z.number().optional().describe("Page number"),
@@ -174,16 +174,15 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
174
174
  "Create a new compute function. Compute functions are JavaScript code blocks that run server-side.",
175
175
  {
176
176
  name: z.string().describe("Display name for the function"),
177
- slug: z.string().describe("URL-safe unique identifier (e.g., 'process-order')"),
178
177
  code: z.string().describe("JavaScript source code. Must export an async function: module.exports = async (ctx) => { ... }"),
179
178
  description: z.string().optional().describe("Optional description of what the function does"),
180
- timeout: z.number().optional().describe("Execution timeout in milliseconds (default: 30000)"),
179
+ timeoutMs: z.number().optional().describe("Execution timeout in milliseconds (default: 30000, min: 1000, max: 300000)"),
181
180
  },
182
- async ({ name, slug, code, description, timeout }) => {
181
+ async ({ name, code, description, timeoutMs }) => {
183
182
  try {
184
- const input: Record<string, any> = { name, slug, code };
183
+ const input: Record<string, any> = { name, code };
185
184
  if (description !== undefined) input.description = description;
186
- if (timeout !== undefined) input.timeout = timeout;
185
+ if (timeoutMs !== undefined) input.timeoutMs = timeoutMs;
187
186
 
188
187
  const result = await sdk.functions.create(input as any);
189
188
  return {
@@ -196,7 +195,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
196
195
  content: [
197
196
  {
198
197
  type: "text",
199
- text: formatError(error, `creating function '${slug}'`),
198
+ text: formatError(error, `creating function '${name}'`),
200
199
  },
201
200
  ],
202
201
  isError: true,
@@ -213,15 +212,15 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
213
212
  name: z.string().optional().describe("Updated display name"),
214
213
  description: z.string().optional().describe("Updated description"),
215
214
  code: z.string().optional().describe("Updated JavaScript source code"),
216
- timeout: z.number().optional().describe("Updated execution timeout in milliseconds"),
215
+ timeoutMs: z.number().optional().describe("Updated execution timeout in milliseconds (min: 1000, max: 300000)"),
217
216
  },
218
- async ({ functionId, name, description, code, timeout }) => {
217
+ async ({ functionId, name, description, code, timeoutMs }) => {
219
218
  try {
220
219
  const input: Record<string, any> = {};
221
220
  if (name !== undefined) input.name = name;
222
221
  if (description !== undefined) input.description = description;
223
222
  if (code !== undefined) input.code = code;
224
- if (timeout !== undefined) input.timeout = timeout;
223
+ if (timeoutMs !== undefined) input.timeoutMs = timeoutMs;
225
224
 
226
225
  const result = await sdk.functions.update(functionId, input as any);
227
226
  return {
@@ -279,15 +278,17 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
279
278
  "Test execute code without saving it as a function. Useful for validating function code before creating or updating.",
280
279
  {
281
280
  code: z.string().describe("JavaScript code to test. Must export an async function: module.exports = async (ctx) => { ... }"),
282
- input: z
281
+ params: z
283
282
  .record(z.string(), z.any())
284
283
  .optional()
285
- .describe("Optional input data passed to the function as ctx.input"),
284
+ .describe("Optional parameters passed to the function as executionParams"),
285
+ timeoutMs: z.number().optional().describe("Execution timeout in milliseconds (default: 30000, min: 1000, max: 300000)"),
286
286
  },
287
- async ({ code, input }) => {
287
+ async ({ code, params, timeoutMs }) => {
288
288
  try {
289
289
  const testInput: Record<string, any> = { code };
290
- if (input !== undefined) testInput.input = input;
290
+ if (params !== undefined) testInput.params = params;
291
+ if (timeoutMs !== undefined) testInput.timeoutMs = timeoutMs;
291
292
 
292
293
  const result = await sdk.functions.testExecute(testInput as any);
293
294
  return {
@@ -346,13 +347,13 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
346
347
  name: z.string().describe("Display name for the trigger"),
347
348
  functionId: z.string().describe("The compute function ID (UUID) to execute"),
348
349
  executionType: z
349
- .enum(["on-demand", "event-driven", "scheduled", "webhook"])
350
- .describe("How the trigger fires: on-demand (manual), event-driven (data events), scheduled (cron), or webhook (HTTP)"),
350
+ .enum(["on-demand", "event-driven", "scheduled", "http-trigger"])
351
+ .describe("How the trigger fires: on-demand (manual), event-driven (data events), scheduled (cron), or http-trigger (external HTTP POST)"),
351
352
  description: z.string().optional().describe("Optional description"),
352
353
  triggerMetadata: z
353
354
  .record(z.string(), z.any())
354
355
  .optional()
355
- .describe("Type-specific configuration. For event-driven: { event, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For webhook: auto-generated URL."),
356
+ .describe("Type-specific configuration. For event-driven: { event, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For http-trigger: auto-generated URL."),
356
357
  enabled: z.boolean().optional().describe("Whether the trigger is enabled (default: true)"),
357
358
  },
358
359
  async ({ name, functionId, executionType, description, triggerMetadata, enabled }) => {
@@ -509,4 +510,91 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
509
510
  }
510
511
  }
511
512
  );
513
+
514
+ // ── Allowed Domains tools ──────────────────────────────────────────
515
+
516
+ server.tool(
517
+ "list_allowed_domains",
518
+ "List all allowed domains for compute function HTTP requests. Functions can only call external APIs on domains in this allowlist.",
519
+ {},
520
+ async () => {
521
+ try {
522
+ const result = await sdk.allowedDomains.list();
523
+ return {
524
+ content: [
525
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
526
+ ],
527
+ };
528
+ } catch (error: unknown) {
529
+ return {
530
+ content: [
531
+ {
532
+ type: "text",
533
+ text: formatError(error, "listing allowed domains"),
534
+ },
535
+ ],
536
+ isError: true,
537
+ };
538
+ }
539
+ }
540
+ );
541
+
542
+ server.tool(
543
+ "add_allowed_domain",
544
+ "Add a domain to the allowlist so compute functions can make HTTP requests to it. Supports wildcards (e.g., '*.example.com').",
545
+ {
546
+ domain: z.string().describe("Domain to allow (e.g., 'api.stripe.com' or '*.googleapis.com')"),
547
+ },
548
+ async ({ domain }) => {
549
+ try {
550
+ const result = await sdk.allowedDomains.add({ domain });
551
+ return {
552
+ content: [
553
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
554
+ ],
555
+ };
556
+ } catch (error: unknown) {
557
+ return {
558
+ content: [
559
+ {
560
+ type: "text",
561
+ text: formatError(error, `adding allowed domain '${domain}'`),
562
+ },
563
+ ],
564
+ isError: true,
565
+ };
566
+ }
567
+ }
568
+ );
569
+
570
+ server.tool(
571
+ "remove_allowed_domain",
572
+ "Remove a domain from the allowlist. Compute functions will no longer be able to call this domain.",
573
+ {
574
+ domainId: z.string().describe("The allowed domain ID (UUID) to remove"),
575
+ },
576
+ async ({ domainId }) => {
577
+ try {
578
+ await sdk.allowedDomains.remove(domainId);
579
+ return {
580
+ content: [
581
+ {
582
+ type: "text",
583
+ text: `Allowed domain '${domainId}' removed successfully.`,
584
+ },
585
+ ],
586
+ };
587
+ } catch (error: unknown) {
588
+ return {
589
+ content: [
590
+ {
591
+ type: "text",
592
+ text: formatError(error, `removing allowed domain '${domainId}'`),
593
+ },
594
+ ],
595
+ isError: true,
596
+ };
597
+ }
598
+ }
599
+ );
512
600
  }
@@ -62,7 +62,7 @@ export function registerDescribeTools(server: McpServer) {
62
62
  },
63
63
  compute: {
64
64
  summary:
65
- "Server-side JavaScript functions with triggers (on-demand, event-driven, scheduled, webhook).",
65
+ "Server-side JavaScript functions with triggers (on-demand, event-driven, scheduled, http-trigger) and domain allowlisting for external API calls.",
66
66
  describeWith: "describe_compute",
67
67
  tools: [
68
68
  "list_functions",
@@ -79,6 +79,9 @@ export function registerDescribeTools(server: McpServer) {
79
79
  "invoke_trigger",
80
80
  "pause_trigger",
81
81
  "resume_trigger",
82
+ "list_allowed_domains",
83
+ "add_allowed_domain",
84
+ "remove_allowed_domain",
82
85
  ],
83
86
  },
84
87
  smart_queries: {
@@ -239,8 +242,8 @@ export function registerDescribeTools(server: McpServer) {
239
242
  },
240
243
  crud_tools: {
241
244
  create_collection: {
242
- description: "Create a new collection with name, slug, properties, and optional settings",
243
- required_params: ["name", "slug"],
245
+ description: "Create a new collection with name, recordSlug, properties, and optional settings",
246
+ required_params: ["name", "recordSlug"],
244
247
  optional_params: ["description", "properties", "enableVersioning", "schemaDiscoveryMode", "tags"],
245
248
  },
246
249
  update_collection: {
@@ -434,11 +437,14 @@ export function registerDescribeTools(server: McpServer) {
434
437
  function_shape: {
435
438
  id: "UUID",
436
439
  name: "string — display name",
437
- slug: "string — unique identifier",
438
440
  description: "string | null",
439
441
  code: "string — the JavaScript source code",
440
- status: "'active' | 'inactive'",
441
- testPayload: "object | null — sample payload for testing",
442
+ timeoutMs: "number | null — execution timeout in milliseconds (default: 30000, max: 300000)",
443
+ workspaceSlug: "string",
444
+ createdBy: "UUID",
445
+ updatedBy: "UUID | null",
446
+ createdAt: "ISO 8601 datetime",
447
+ updatedAt: "ISO 8601 datetime",
442
448
  },
443
449
  trigger_types: {
444
450
  "on-demand": {
@@ -467,19 +473,25 @@ export function registerDescribeTools(server: McpServer) {
467
473
  "Runs on a cron schedule (e.g., every hour, daily at midnight).",
468
474
  config: "Uses standard cron expression syntax (e.g., '0 * * * *' for hourly)",
469
475
  },
470
- webhook: {
476
+ "http-trigger": {
471
477
  description:
472
478
  "Triggered by an external HTTP POST to a generated webhook URL.",
473
- config: "Each webhook trigger gets a unique URL to share with external services",
479
+ config: "Each http-trigger gets a unique URL to share with external services",
474
480
  },
475
481
  },
476
482
  trigger_shape: {
477
483
  id: "UUID",
478
484
  name: "string",
485
+ description: "string | null",
479
486
  functionId: "UUID — the compute function to execute",
480
- executionType: "'on-demand' | 'event-driven' | 'scheduled' | 'webhook'",
481
- status: "'active' | 'paused'",
482
- config: "objecttype-specific configuration (cron, event filters, etc.)",
487
+ executionType: "'on-demand' | 'event-driven' | 'scheduled' | 'http-trigger'",
488
+ triggerMetadata: "object type-specific configuration (event, cron, params, etc.)",
489
+ enabled: "booleanwhether the trigger is active (default: true)",
490
+ workspaceSlug: "string",
491
+ createdBy: "UUID",
492
+ updatedBy: "UUID",
493
+ createdAt: "ISO 8601 datetime",
494
+ updatedAt: "ISO 8601 datetime",
483
495
  },
484
496
  function_crud: {
485
497
  get_function: {
@@ -488,14 +500,14 @@ export function registerDescribeTools(server: McpServer) {
488
500
  },
489
501
  create_function: {
490
502
  description: "Create a new compute function",
491
- required_params: ["name", "slug", "code"],
492
- optional_params: ["description", "timeout"],
503
+ required_params: ["name", "code"],
504
+ optional_params: ["description", "timeoutMs"],
493
505
  code_format: "module.exports = async (ctx) => { /* your code */ return result; }",
494
506
  },
495
507
  update_function: {
496
508
  description: "Update an existing function. Partial updates supported.",
497
509
  required_params: ["functionId"],
498
- optional_params: ["name", "description", "code", "timeout"],
510
+ optional_params: ["name", "description", "code", "timeoutMs"],
499
511
  },
500
512
  delete_function: {
501
513
  description: "Delete a compute function by ID",
@@ -504,7 +516,7 @@ export function registerDescribeTools(server: McpServer) {
504
516
  test_function: {
505
517
  description: "Test execute code without saving. Returns output, duration, and logs.",
506
518
  required_params: ["code"],
507
- optional_params: ["input"],
519
+ optional_params: ["params", "timeoutMs"],
508
520
  },
509
521
  },
510
522
  trigger_crud: {
@@ -539,6 +551,30 @@ export function registerDescribeTools(server: McpServer) {
539
551
  required_params: ["triggerId"],
540
552
  },
541
553
  },
554
+ allowed_domains: {
555
+ description: "Workspace-level allowlist controlling which external domains compute functions can call via api.httpGet/httpPost/etc. Functions attempting to reach unlisted domains get an error.",
556
+ domain_shape: {
557
+ id: "UUID",
558
+ domain: "string — the allowed domain (e.g., 'api.stripe.com' or '*.googleapis.com')",
559
+ createdAt: "ISO 8601 datetime",
560
+ createdBy: "UUID",
561
+ },
562
+ tools: {
563
+ list_allowed_domains: {
564
+ description: "List all allowed domains in the workspace",
565
+ },
566
+ add_allowed_domain: {
567
+ description: "Add a domain to the allowlist",
568
+ required_params: ["domain"],
569
+ },
570
+ remove_allowed_domain: {
571
+ description: "Remove a domain from the allowlist by ID",
572
+ required_params: ["domainId"],
573
+ },
574
+ },
575
+ wildcards: "Use '*.example.com' to allow all subdomains of example.com",
576
+ note: "Functions can only make HTTP requests to domains on this list. Add domains before creating functions that call external APIs.",
577
+ },
542
578
  sandbox_api: {
543
579
  description: "Functions receive an `api` object with built-in utilities. Key crypto methods:",
544
580
  crypto: {
@@ -558,6 +594,7 @@ export function registerDescribeTools(server: McpServer) {
558
594
  "Use test_function to validate code before creating or updating a function",
559
595
  "Use create_function + create_trigger together to set up a complete compute pipeline",
560
596
  "Use api.crypto.signJwt() for GitHub App, Google Cloud, or Azure AD authentication flows",
597
+ "Before creating functions that call external APIs, add the target domains with add_allowed_domain",
561
598
  ],
562
599
  },
563
600
  null,