@centrali-io/centrali-mcp 5.2.0 → 5.4.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/README.md +15 -0
- package/dist/index.js +2 -0
- package/dist/tools/_register.d.ts +24 -0
- package/dist/tools/_register.js +44 -0
- package/dist/tools/auth-providers.js +15 -30
- package/dist/tools/compute.js +48 -69
- package/dist/tools/describe.js +174 -21
- package/dist/tools/insights.js +13 -36
- package/dist/tools/orchestrations.js +21 -44
- package/dist/tools/pages.js +39 -61
- package/dist/tools/records.js +29 -50
- package/dist/tools/search.js +3 -24
- package/dist/tools/service-accounts.js +93 -108
- package/dist/tools/smart-queries.js +15 -36
- package/dist/tools/structures.js +23 -61
- package/dist/tools/validation.js +11 -34
- package/dist/tools/webhook-subscriptions.d.ts +3 -0
- package/dist/tools/webhook-subscriptions.js +292 -0
- package/package.json +5 -6
- package/src/index.ts +2 -0
- package/src/tools/_register.ts +53 -0
- package/src/tools/auth-providers.ts +8 -24
- package/src/tools/compute.ts +25 -46
- package/src/tools/describe.ts +200 -21
- package/src/tools/insights.ts +19 -28
- package/src/tools/orchestrations.ts +11 -34
- package/src/tools/pages.ts +20 -41
- package/src/tools/records.ts +15 -36
- package/src/tools/search.ts +7 -22
- package/src/tools/service-accounts.ts +47 -63
- package/src/tools/smart-queries.ts +8 -29
- package/src/tools/structures.ts +12 -50
- package/src/tools/validation.ts +21 -27
- package/src/tools/webhook-subscriptions.ts +363 -0
package/src/tools/compute.ts
CHANGED
|
@@ -2,28 +2,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
2
2
|
import { CentraliSDK } from "@centrali-io/centrali-sdk";
|
|
3
3
|
import axios from "axios";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
|
|
6
|
-
function formatError(error: unknown, context: string): string {
|
|
7
|
-
if (error && typeof error === 'object') {
|
|
8
|
-
const e = error as Record<string, any>;
|
|
9
|
-
if ('message' in e) {
|
|
10
|
-
let msg = `Error ${context}`;
|
|
11
|
-
if ('code' in e || 'status' in e) {
|
|
12
|
-
msg += `: [${e.code ?? e.status ?? 'ERROR'}] ${e.message}`;
|
|
13
|
-
} else {
|
|
14
|
-
msg += `: ${e.message}`;
|
|
15
|
-
}
|
|
16
|
-
if (Array.isArray(e.fieldErrors) && e.fieldErrors.length > 0) {
|
|
17
|
-
msg += '\nField errors:\n' + (e.fieldErrors as Array<{field: string; message: string}>)
|
|
18
|
-
.map(f => ` ${f.field}: ${f.message}`)
|
|
19
|
-
.join('\n');
|
|
20
|
-
}
|
|
21
|
-
return msg;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
|
|
25
|
-
}
|
|
26
|
-
|
|
5
|
+
import { registerTool, formatError } from "./_register.js";
|
|
27
6
|
/**
|
|
28
7
|
* Ensures the SDK has a valid token.
|
|
29
8
|
*/
|
|
@@ -37,7 +16,7 @@ async function ensureToken(sdk: CentraliSDK): Promise<string | null> {
|
|
|
37
16
|
}
|
|
38
17
|
|
|
39
18
|
export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centraliUrl: string, workspaceId: string) {
|
|
40
|
-
server
|
|
19
|
+
registerTool<any>(server,
|
|
41
20
|
"list_functions",
|
|
42
21
|
"List all compute functions in the workspace. Compute functions are JavaScript code blocks that run server-side.",
|
|
43
22
|
{
|
|
@@ -72,7 +51,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
72
51
|
}
|
|
73
52
|
);
|
|
74
53
|
|
|
75
|
-
server
|
|
54
|
+
registerTool<any>(server,
|
|
76
55
|
"list_triggers",
|
|
77
56
|
"List function triggers in the workspace. Triggers define how and when compute functions are executed (on-demand, event-driven, scheduled, http-trigger, endpoint).",
|
|
78
57
|
{
|
|
@@ -112,7 +91,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
112
91
|
}
|
|
113
92
|
);
|
|
114
93
|
|
|
115
|
-
server
|
|
94
|
+
registerTool<any>(server,
|
|
116
95
|
"invoke_trigger",
|
|
117
96
|
"Invoke an on-demand function trigger by ID. Optionally pass a custom payload. Returns the queued job ID.",
|
|
118
97
|
{
|
|
@@ -156,7 +135,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
156
135
|
}
|
|
157
136
|
);
|
|
158
137
|
|
|
159
|
-
server
|
|
138
|
+
registerTool<any>(server,
|
|
160
139
|
"get_compute_job_status",
|
|
161
140
|
"Check the status of an async compute job by job ID. Returns the current state (queued, running, completed, failed), the return value on success, or the failure reason on error. Use this after invoke_trigger to poll for results.",
|
|
162
141
|
{
|
|
@@ -195,7 +174,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
195
174
|
|
|
196
175
|
// ── Function CRUD tools ──────────────────────────────────────────
|
|
197
176
|
|
|
198
|
-
server
|
|
177
|
+
registerTool<any>(server,
|
|
199
178
|
"get_function",
|
|
200
179
|
"Get a compute function by ID. Returns the full function definition including code.",
|
|
201
180
|
{
|
|
@@ -223,7 +202,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
223
202
|
}
|
|
224
203
|
);
|
|
225
204
|
|
|
226
|
-
server
|
|
205
|
+
registerTool<any>(server,
|
|
227
206
|
"create_function",
|
|
228
207
|
"Create a new compute function. Compute functions are JavaScript code blocks that run server-side.",
|
|
229
208
|
{
|
|
@@ -270,7 +249,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
270
249
|
}
|
|
271
250
|
);
|
|
272
251
|
|
|
273
|
-
server
|
|
252
|
+
registerTool<any>(server,
|
|
274
253
|
"update_function",
|
|
275
254
|
"Update an existing compute function by ID. Only include the fields you want to change.",
|
|
276
255
|
{
|
|
@@ -320,7 +299,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
320
299
|
}
|
|
321
300
|
);
|
|
322
301
|
|
|
323
|
-
server
|
|
302
|
+
registerTool<any>(server,
|
|
324
303
|
"delete_function",
|
|
325
304
|
"Delete a compute function by ID.",
|
|
326
305
|
{
|
|
@@ -351,7 +330,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
351
330
|
}
|
|
352
331
|
);
|
|
353
332
|
|
|
354
|
-
server
|
|
333
|
+
registerTool<any>(server,
|
|
355
334
|
"test_function",
|
|
356
335
|
"Test execute code without saving it as a function. Useful for validating function code before creating or updating.",
|
|
357
336
|
{
|
|
@@ -402,7 +381,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
402
381
|
|
|
403
382
|
// ── Trigger CRUD tools ───────────────────────────────────────────
|
|
404
383
|
|
|
405
|
-
server
|
|
384
|
+
registerTool<any>(server,
|
|
406
385
|
"get_trigger",
|
|
407
386
|
"Get a function trigger by ID. Returns full trigger details including execution type and metadata.",
|
|
408
387
|
{
|
|
@@ -430,7 +409,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
430
409
|
}
|
|
431
410
|
);
|
|
432
411
|
|
|
433
|
-
server
|
|
412
|
+
registerTool<any>(server,
|
|
434
413
|
"create_trigger",
|
|
435
414
|
"Create a new function trigger. Triggers define how and when a compute function is executed.",
|
|
436
415
|
{
|
|
@@ -443,7 +422,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
443
422
|
triggerMetadata: z
|
|
444
423
|
.record(z.string(), z.any())
|
|
445
424
|
.optional()
|
|
446
|
-
.describe("Type-specific configuration. For event-driven: { eventType, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For http-trigger: auto-generated URL. For endpoint: { path, allowedMethods?, timeoutMs?, auth? } where path is URL-safe (e.g., 'create-order'), allowedMethods defaults to ['POST'], timeoutMs 1000-30000 (default 30000), auth is { mode: 'bearer'|'public'|'apiKey'|'hmac' }."),
|
|
425
|
+
.describe("Type-specific configuration. For event-driven: { eventType, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For http-trigger: auto-generated URL. For endpoint: { path, allowedMethods?, timeoutMs?, auth? } where path is URL-safe (e.g., 'create-order'), allowedMethods defaults to ['POST'], timeoutMs 1000-30000 (default 30000), auth is { mode: 'bearer'|'public'|'apiKey'|'hmac' }. All trigger types accept params: a dictionary of static values passed to the function as triggerParams. Mark any secret with { value: 'plaintext', encrypt: true } to store it AES-256-GCM-encrypted at rest; it arrives as plaintext in triggerParams at execution time."),
|
|
447
426
|
enabled: z.boolean().optional().describe("Whether the trigger is enabled (default: true)"),
|
|
448
427
|
},
|
|
449
428
|
async ({ name, functionId, executionType, description, triggerMetadata, enabled }) => {
|
|
@@ -473,7 +452,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
473
452
|
}
|
|
474
453
|
);
|
|
475
454
|
|
|
476
|
-
server
|
|
455
|
+
registerTool<any>(server,
|
|
477
456
|
"update_trigger",
|
|
478
457
|
"Update an existing function trigger by ID. Only include the fields you want to change.",
|
|
479
458
|
{
|
|
@@ -484,7 +463,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
484
463
|
triggerMetadata: z
|
|
485
464
|
.record(z.string(), z.any())
|
|
486
465
|
.optional()
|
|
487
|
-
.describe("Updated type-specific configuration"),
|
|
466
|
+
.describe("Updated type-specific configuration. To rotate an encrypted params value, send params: { KEY: { value: 'new-plaintext', encrypt: true } }. To preserve an existing encrypted value without rotating, echo back the stored shape: params: { KEY: { value: '********', encrypted: true, keyVersion: N } } (use get_trigger to read the current shape). Omit a key from params entirely to remove it."),
|
|
488
467
|
},
|
|
489
468
|
async ({ triggerId, name, description, enabled, triggerMetadata }) => {
|
|
490
469
|
try {
|
|
@@ -514,7 +493,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
514
493
|
}
|
|
515
494
|
);
|
|
516
495
|
|
|
517
|
-
server
|
|
496
|
+
registerTool<any>(server,
|
|
518
497
|
"delete_trigger",
|
|
519
498
|
"Delete a function trigger by ID.",
|
|
520
499
|
{
|
|
@@ -545,7 +524,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
545
524
|
}
|
|
546
525
|
);
|
|
547
526
|
|
|
548
|
-
server
|
|
527
|
+
registerTool<any>(server,
|
|
549
528
|
"pause_trigger",
|
|
550
529
|
"Pause a function trigger. Paused triggers will not fire until resumed.",
|
|
551
530
|
{
|
|
@@ -573,7 +552,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
573
552
|
}
|
|
574
553
|
);
|
|
575
554
|
|
|
576
|
-
server
|
|
555
|
+
registerTool<any>(server,
|
|
577
556
|
"resume_trigger",
|
|
578
557
|
"Resume a paused function trigger. The trigger will start firing again on matching events or schedules.",
|
|
579
558
|
{
|
|
@@ -603,7 +582,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
603
582
|
|
|
604
583
|
// ── Function Runs tools ────────────────────────────────────────────
|
|
605
584
|
|
|
606
|
-
server
|
|
585
|
+
registerTool<any>(server,
|
|
607
586
|
"get_function_run",
|
|
608
587
|
"Get a function run by ID. Returns status, output, error, timing, and execution metadata. Use this to check the result of an async trigger invocation or test execution.",
|
|
609
588
|
{
|
|
@@ -631,7 +610,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
631
610
|
}
|
|
632
611
|
);
|
|
633
612
|
|
|
634
|
-
server
|
|
613
|
+
registerTool<any>(server,
|
|
635
614
|
"list_function_runs",
|
|
636
615
|
"List function runs filtered by trigger ID or function ID. Returns execution history with status, timing, and errors. Useful for checking whether a trigger invocation completed and what it returned.",
|
|
637
616
|
{
|
|
@@ -689,7 +668,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
689
668
|
|
|
690
669
|
// ── Endpoint Trigger (Sync Execution) ─────────────────────────────
|
|
691
670
|
|
|
692
|
-
server
|
|
671
|
+
registerTool<any>(server,
|
|
693
672
|
"invoke_endpoint",
|
|
694
673
|
"Invoke a compute endpoint trigger by path. The function executes synchronously — Centrali waits for the function to complete and returns its output directly in the response. No polling needed. Max execution time: 30 seconds (configurable via triggerMetadata.timeoutMs, range 1–30s). If the function exceeds the timeout, returns 504. Endpoint triggers must be created first with executionType='endpoint'. Use this for real-time API responses; use invoke_trigger for long-running background work that doesn't need an immediate response.",
|
|
695
674
|
{
|
|
@@ -744,7 +723,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
744
723
|
|
|
745
724
|
// ── Allowed Domains tools ──────────────────────────────────────────
|
|
746
725
|
|
|
747
|
-
server
|
|
726
|
+
registerTool<any>(server,
|
|
748
727
|
"list_allowed_domains",
|
|
749
728
|
"List all allowed domains for compute function HTTP requests. Functions can only call external APIs on domains in this allowlist.",
|
|
750
729
|
{},
|
|
@@ -770,7 +749,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
770
749
|
}
|
|
771
750
|
);
|
|
772
751
|
|
|
773
|
-
server
|
|
752
|
+
registerTool<any>(server,
|
|
774
753
|
"add_allowed_domain",
|
|
775
754
|
"Add a domain to the allowlist so compute functions can make HTTP requests to it. Supports wildcards (e.g., '*.example.com').",
|
|
776
755
|
{
|
|
@@ -798,7 +777,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
798
777
|
}
|
|
799
778
|
);
|
|
800
779
|
|
|
801
|
-
server
|
|
780
|
+
registerTool<any>(server,
|
|
802
781
|
"remove_allowed_domain",
|
|
803
782
|
"Remove a domain from the allowlist. Compute functions will no longer be able to call this domain.",
|
|
804
783
|
{
|
|
@@ -831,7 +810,7 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK, centra
|
|
|
831
810
|
|
|
832
811
|
// ── Scaffold (function + trigger in one step) ─────────────────────
|
|
833
812
|
|
|
834
|
-
server
|
|
813
|
+
registerTool<any>(server,
|
|
835
814
|
"scaffold_function",
|
|
836
815
|
"Create a compute function with boilerplate code and optionally wire a trigger — all in one step. The function uses the required `async function run()` pattern with `api.*` globals, `triggerParams`, and `executionParams` available.",
|
|
837
816
|
{
|
package/src/tools/describe.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { registerTool } from "./_register.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Introspection tools that teach AI assistants the valid shapes, schemas,
|
|
@@ -11,7 +12,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
11
12
|
export function registerDescribeTools(server: McpServer) {
|
|
12
13
|
// ── Master describe tool ────────────────────────────────────────────
|
|
13
14
|
|
|
14
|
-
server
|
|
15
|
+
registerTool<any>(server,
|
|
15
16
|
"describe_centrali",
|
|
16
17
|
"Get an overview of all Centrali platform capabilities and API domains. Call this first to understand what Centrali can do and which describe_* tool to call for deeper schema details.",
|
|
17
18
|
{},
|
|
@@ -184,6 +185,23 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
184
185
|
"refresh_auth_provider_jwks",
|
|
185
186
|
],
|
|
186
187
|
},
|
|
188
|
+
webhooks: {
|
|
189
|
+
summary:
|
|
190
|
+
"Outbound webhook subscriptions for record events. Centrali POSTs a signed JSON payload to your URL on record_created, record_updated, record_deleted, and records_bulk_created. Each dispatch is signed with HMAC-SHA256 under the subscription's whsec_ secret and every attempt is recorded in the delivery log for inspection and replay.",
|
|
191
|
+
describeWith: "describe_webhooks",
|
|
192
|
+
tools: [
|
|
193
|
+
"list_webhook_subscriptions",
|
|
194
|
+
"get_webhook_subscription",
|
|
195
|
+
"create_webhook_subscription",
|
|
196
|
+
"update_webhook_subscription",
|
|
197
|
+
"delete_webhook_subscription",
|
|
198
|
+
"rotate_webhook_subscription_secret",
|
|
199
|
+
"list_webhook_deliveries",
|
|
200
|
+
"get_webhook_delivery",
|
|
201
|
+
"retry_webhook_delivery",
|
|
202
|
+
"cancel_webhook_delivery",
|
|
203
|
+
],
|
|
204
|
+
},
|
|
187
205
|
service_accounts: {
|
|
188
206
|
summary:
|
|
189
207
|
"Machine identities for backend-to-backend API access. Create service accounts with client_credentials OAuth2 flow, manage roles and groups for fine-grained permissions, and introspect access with permission scanning.",
|
|
@@ -278,6 +296,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
278
296
|
"Anomaly insights": { sdk: true, mcp: true, console: true },
|
|
279
297
|
"Search": { sdk: true, mcp: true, console: true },
|
|
280
298
|
"Function runs (execution history)": { sdk: true, mcp: true, console: true },
|
|
299
|
+
"Outbound webhooks": { sdk: true, mcp: true, console: true, note: "SDK namespace (client.webhookSubscriptions) and MCP tools wrap the REST surface including delivery replay" },
|
|
281
300
|
"Service accounts & IAM": { sdk: false, mcp: true, console: true, note: "MCP tools for full SA lifecycle, roles, groups, and permission introspection" },
|
|
282
301
|
"File uploads": { sdk: true, mcp: false, console: true, note: "SDK-only — use client.uploadFile() in app code" },
|
|
283
302
|
},
|
|
@@ -502,7 +521,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
502
521
|
|
|
503
522
|
// ── Collections ────────────────────────────────────────────────────
|
|
504
523
|
|
|
505
|
-
server
|
|
524
|
+
registerTool<any>(server,
|
|
506
525
|
"describe_collections",
|
|
507
526
|
"Get the schema reference for Centrali collections. Explains field types, property shapes, constraints, and how to define data models.",
|
|
508
527
|
{},
|
|
@@ -602,7 +621,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
602
621
|
|
|
603
622
|
// ── Records ────────────────────────────────────────────────────────
|
|
604
623
|
|
|
605
|
-
server
|
|
624
|
+
registerTool<any>(server,
|
|
606
625
|
"describe_records",
|
|
607
626
|
"Get the schema reference for Centrali record operations. Explains filter syntax, sort syntax, pagination, expand, and the data. prefix convention.",
|
|
608
627
|
{},
|
|
@@ -720,7 +739,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
720
739
|
|
|
721
740
|
// ── Search ─────────────────────────────────────────────────────────
|
|
722
741
|
|
|
723
|
-
server
|
|
742
|
+
registerTool<any>(server,
|
|
724
743
|
"describe_search",
|
|
725
744
|
"Get the schema reference for Centrali full-text search. Explains search behavior, filtering, and result format.",
|
|
726
745
|
{},
|
|
@@ -762,7 +781,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
762
781
|
|
|
763
782
|
// ── Compute ────────────────────────────────────────────────────────
|
|
764
783
|
|
|
765
|
-
server
|
|
784
|
+
registerTool<any>(server,
|
|
766
785
|
"describe_compute",
|
|
767
786
|
"Get the schema reference for Centrali compute functions and triggers. Explains function types, trigger execution modes, and invocation patterns.",
|
|
768
787
|
{},
|
|
@@ -979,10 +998,12 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
979
998
|
utilities: "api.uuid, api.formatDate, api.chunk, api.merge, api.math, api.evaluate, api.renderTemplate, api.log, api.logError, api.toCSV, api.toJSON",
|
|
980
999
|
},
|
|
981
1000
|
secrets: {
|
|
982
|
-
description: "
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1001
|
+
description: "Set encrypted params directly on any trigger's triggerMetadata.params. Shape at create/update: { paramName: { value: 'plaintext', encrypt: true } }. Stored AES-256-GCM at rest, decrypted at execution time, arrive in triggerParams[paramName] as plaintext.",
|
|
1002
|
+
works_on: "event-driven, scheduled, http-trigger, endpoint, and on-demand triggers — plus orchestration compute steps (same mechanism, scoped to a step via encryptedParams).",
|
|
1003
|
+
example_event_driven: "create_trigger({ executionType: 'event-driven', triggerMetadata: { eventType: 'record_created', recordSlug: 'stripe-events', params: { SLACK_WEBHOOK_URL: { value: 'https://hooks.slack.com/...', encrypt: true } } } }) — function accesses triggerParams.SLACK_WEBHOOK_URL as plaintext.",
|
|
1004
|
+
update_semantics: "To rotate a value: send { KEY: { value: 'new-plaintext', encrypt: true } }. To preserve an existing encrypted value without rotating: send { KEY: { value: '********', encrypted: true, keyVersion: N } } (use get_trigger to see the stored shape).",
|
|
1005
|
+
alternative: "Pass secrets in the invocation payload via executionParams — only when the caller is already holding the secret and you don't want to store it on the trigger.",
|
|
1006
|
+
orchestration_note: "Orchestration compute steps use encryptedParams with the same { value, encrypt: true } shape — equivalent mechanism, just scoped to a single step.",
|
|
986
1007
|
},
|
|
987
1008
|
async_execution: {
|
|
988
1009
|
description: "Trigger invocation is ASYNCHRONOUS. invoke_trigger returns a job ID, not the execution result. There are two ways to get the result.",
|
|
@@ -1020,7 +1041,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1020
1041
|
"Use get_function_run or list_function_runs to check execution results after invoking a trigger",
|
|
1021
1042
|
"Use api.crypto.signJwt() for GitHub App, Google Cloud, or Azure AD authentication flows",
|
|
1022
1043
|
"Before creating functions that call external APIs, add the target domains with add_allowed_domain",
|
|
1023
|
-
"For secrets (API keys, credentials),
|
|
1044
|
+
"For secrets (API keys, credentials), set encrypted params on the trigger (triggerMetadata.params with { value, encrypt: true }) — see the 'secrets' section above",
|
|
1024
1045
|
],
|
|
1025
1046
|
},
|
|
1026
1047
|
null,
|
|
@@ -1033,7 +1054,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1033
1054
|
|
|
1034
1055
|
// ── Smart Queries ──────────────────────────────────────────────────
|
|
1035
1056
|
|
|
1036
|
-
server
|
|
1057
|
+
registerTool<any>(server,
|
|
1037
1058
|
"describe_smart_queries",
|
|
1038
1059
|
"Get the schema reference for Centrali smart queries. Explains parameterized queries, variable substitution, and execution.",
|
|
1039
1060
|
{},
|
|
@@ -1120,7 +1141,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1120
1141
|
|
|
1121
1142
|
// ── Orchestrations ─────────────────────────────────────────────────
|
|
1122
1143
|
|
|
1123
|
-
server
|
|
1144
|
+
registerTool<any>(server,
|
|
1124
1145
|
"describe_orchestrations",
|
|
1125
1146
|
"Get the schema reference for Centrali orchestrations. Explains multi-step workflows, runs, steps, and execution model.",
|
|
1126
1147
|
{},
|
|
@@ -1298,9 +1319,167 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1298
1319
|
})
|
|
1299
1320
|
);
|
|
1300
1321
|
|
|
1322
|
+
// ── Webhooks ───────────────────────────────────────────────────────
|
|
1323
|
+
|
|
1324
|
+
registerTool<any>(server,
|
|
1325
|
+
"describe_webhooks",
|
|
1326
|
+
"Get the schema reference for Centrali outbound webhooks. Explains subscription shape, supported event types, signature verification, retry behavior, and delivery-status lifecycle.",
|
|
1327
|
+
{},
|
|
1328
|
+
async () => ({
|
|
1329
|
+
content: [
|
|
1330
|
+
{
|
|
1331
|
+
type: "text",
|
|
1332
|
+
text: JSON.stringify(
|
|
1333
|
+
{
|
|
1334
|
+
domain: "Webhook Subscriptions",
|
|
1335
|
+
description:
|
|
1336
|
+
"Centrali emits record lifecycle events to external URLs. A subscription binds an HTTPS URL to one or more event types (optionally scoped to a subset of collections). Every dispatch is signed with HMAC-SHA256 and recorded in the delivery log — successes, retries, and terminal failures are all preserved.",
|
|
1337
|
+
subscription_shape: {
|
|
1338
|
+
id: "UUID",
|
|
1339
|
+
name: "string",
|
|
1340
|
+
url: "string — HTTPS URL that receives the POSTed payload",
|
|
1341
|
+
events: "RecordEventType[] — subscribed events",
|
|
1342
|
+
recordSlugs: "string[] — restrict to these collections. An empty array (or null on a read from an older row) means the subscription receives events for all collections. On update_webhook_subscription, pass [] to clear the restriction; omit the field to leave scope unchanged.",
|
|
1343
|
+
active: "boolean — when false, dispatches are skipped",
|
|
1344
|
+
secret: "string | undefined — `whsec_<base64url>` signing secret. Returned ONLY on create_webhook_subscription and rotate_webhook_subscription_secret; omitted on list/get.",
|
|
1345
|
+
createdAt: "ISO 8601 datetime",
|
|
1346
|
+
updatedAt: "ISO 8601 datetime",
|
|
1347
|
+
},
|
|
1348
|
+
event_types: {
|
|
1349
|
+
record_created: "A new record was inserted",
|
|
1350
|
+
record_updated: "An existing record was modified",
|
|
1351
|
+
record_deleted: "A record was deleted (soft or hard)",
|
|
1352
|
+
records_bulk_created: "Multiple records were inserted in a batch",
|
|
1353
|
+
},
|
|
1354
|
+
outbound_payload_shape: {
|
|
1355
|
+
description:
|
|
1356
|
+
"Body shape Centrali POSTs to the subscribed URL. JSON-serialized; the raw bytes of this body are what gets HMAC-signed into X-Signature.",
|
|
1357
|
+
event: "string — one of 'record_created' | 'record_updated' | 'record_deleted' | 'records_bulk_created'",
|
|
1358
|
+
workspaceSlug: "string — the workspace that produced the event",
|
|
1359
|
+
recordSlug: "string | undefined — the collection slug (absent on some bulk events)",
|
|
1360
|
+
recordId: "string — the affected record's UUID (or the batch marker for bulk events)",
|
|
1361
|
+
data: "object | undefined — the record snapshot for created/updated events (absent on deletes)",
|
|
1362
|
+
timestamp: "string | undefined — ISO 8601 time the event was emitted",
|
|
1363
|
+
createdBy: "string | undefined — actor user ID; populated on 'record_created'",
|
|
1364
|
+
updatedBy: "string | undefined — actor user ID; populated on 'record_updated'",
|
|
1365
|
+
deletedBy: "string | undefined — actor user ID; populated on 'record_deleted'",
|
|
1366
|
+
note:
|
|
1367
|
+
"Actor fields are per-event: a create delivery carries createdBy, an update carries updatedBy, a delete carries deletedBy. They are the source of truth for 'who did this' — don't infer it from `data`.",
|
|
1368
|
+
},
|
|
1369
|
+
signature: {
|
|
1370
|
+
header: "X-Signature",
|
|
1371
|
+
algorithm: "HMAC-SHA256",
|
|
1372
|
+
secret_format:
|
|
1373
|
+
"`whsec_<base64url>` — strip the `whsec_` prefix and base64url-decode the remainder to get the raw HMAC key bytes.",
|
|
1374
|
+
signed_value:
|
|
1375
|
+
"The raw JSON request body (the outbound_payload_shape above, as bytes). Verify before parsing.",
|
|
1376
|
+
output_encoding: "base64 (standard, not base64url)",
|
|
1377
|
+
verify_example: [
|
|
1378
|
+
"// Node.js verification",
|
|
1379
|
+
"const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64url');",
|
|
1380
|
+
"const expected = crypto.createHmac('sha256', key).update(rawBody).digest('base64');",
|
|
1381
|
+
"// then timing-safe compare expected to req.headers['x-signature']",
|
|
1382
|
+
].join("\n"),
|
|
1383
|
+
},
|
|
1384
|
+
delivery_shape: {
|
|
1385
|
+
id: "UUID",
|
|
1386
|
+
webhookSubscriptionId: "UUID — parent subscription",
|
|
1387
|
+
event: "string — the event name that triggered the dispatch",
|
|
1388
|
+
status: "'success' | 'failed' | 'retrying'",
|
|
1389
|
+
attemptCount: "number — number of HTTP attempts made against the target",
|
|
1390
|
+
httpStatus: "number | null — the response status on the last attempt",
|
|
1391
|
+
lastError: "string | null — last error message; 'Cancelled by user' for cancelled retries",
|
|
1392
|
+
lastAttemptAt: "ISO 8601 datetime",
|
|
1393
|
+
nextAttemptAt: "ISO 8601 datetime | null — scheduled time of the next retry (null when terminal)",
|
|
1394
|
+
requestPayload:
|
|
1395
|
+
"object — only present on get_webhook_delivery (list_webhook_deliveries trims it for efficiency)",
|
|
1396
|
+
responseBody:
|
|
1397
|
+
"string | null — first 1000 chars of the target response; only present on get_webhook_delivery",
|
|
1398
|
+
replayedFrom: "UUID | null — delivery ID this row was replayed from; null for originals",
|
|
1399
|
+
createdAt: "ISO 8601 datetime",
|
|
1400
|
+
updatedAt: "ISO 8601 datetime",
|
|
1401
|
+
},
|
|
1402
|
+
retry_behavior: {
|
|
1403
|
+
description:
|
|
1404
|
+
"Failed deliveries retry with fixed backoffs. After exhausting all attempts the row terminates as 'failed'. Circuit-open rejections count as spent attempts.",
|
|
1405
|
+
max_attempts: 5,
|
|
1406
|
+
terminal_statuses: ["success", "failed"],
|
|
1407
|
+
replay:
|
|
1408
|
+
"retry_webhook_delivery inserts a new delivery row and preserves the original payload and signature. The retry counter restarts for the replay.",
|
|
1409
|
+
cancel:
|
|
1410
|
+
"cancel_webhook_delivery only works on 'retrying' rows. It flips the row to 'failed' with lastError='Cancelled by user' and clears nextAttemptAt.",
|
|
1411
|
+
},
|
|
1412
|
+
crud_tools: {
|
|
1413
|
+
create_webhook_subscription: {
|
|
1414
|
+
description:
|
|
1415
|
+
"Create a subscription. The signing secret is ONLY returned on this call — surface it to the user once.",
|
|
1416
|
+
required_params: ["name", "url", "events"],
|
|
1417
|
+
optional_params: ["recordSlugs", "active"],
|
|
1418
|
+
example: {
|
|
1419
|
+
name: "Orders webhook",
|
|
1420
|
+
url: "https://api.example.com/hooks/centrali",
|
|
1421
|
+
events: ["record_created", "record_updated"],
|
|
1422
|
+
recordSlugs: ["orders"],
|
|
1423
|
+
},
|
|
1424
|
+
},
|
|
1425
|
+
update_webhook_subscription: {
|
|
1426
|
+
description: "Update editable fields. The signing secret is server-managed — use rotate instead.",
|
|
1427
|
+
required_params: ["subscriptionId"],
|
|
1428
|
+
optional_params: ["name", "url", "events", "recordSlugs", "active"],
|
|
1429
|
+
},
|
|
1430
|
+
rotate_webhook_subscription_secret: {
|
|
1431
|
+
description:
|
|
1432
|
+
"Regenerate the signing secret. Immediate cutover — surface the new secret to the user; it is not returned on reads.",
|
|
1433
|
+
required_params: ["subscriptionId"],
|
|
1434
|
+
},
|
|
1435
|
+
delete_webhook_subscription: {
|
|
1436
|
+
description: "Delete a subscription. Historical delivery rows are retained for audit.",
|
|
1437
|
+
required_params: ["subscriptionId"],
|
|
1438
|
+
},
|
|
1439
|
+
list_webhook_deliveries: {
|
|
1440
|
+
description:
|
|
1441
|
+
"List deliveries for a subscription. Rows omit the request payload and response body — fetch them via get_webhook_delivery when needed.",
|
|
1442
|
+
required_params: ["subscriptionId"],
|
|
1443
|
+
optional_params: ["status", "since", "until", "limit", "offset"],
|
|
1444
|
+
},
|
|
1445
|
+
get_webhook_delivery: {
|
|
1446
|
+
description: "Get a single delivery including the full request payload and response body.",
|
|
1447
|
+
required_params: ["subscriptionId", "deliveryId"],
|
|
1448
|
+
},
|
|
1449
|
+
retry_webhook_delivery: {
|
|
1450
|
+
description:
|
|
1451
|
+
"Replay a delivery. Works on any non-retrying row (use cancel first if the row is still retrying).",
|
|
1452
|
+
required_params: ["deliveryId"],
|
|
1453
|
+
note:
|
|
1454
|
+
"deliveryId is the global delivery ID — it does NOT need to be nested under a subscription because the backend route is /webhook-subscriptions/deliveries/{id}/retry.",
|
|
1455
|
+
},
|
|
1456
|
+
cancel_webhook_delivery: {
|
|
1457
|
+
description:
|
|
1458
|
+
"Cancel a delivery that is currently retrying. Returns 409 if the row is not retrying or is mid-dispatch.",
|
|
1459
|
+
required_params: ["deliveryId"],
|
|
1460
|
+
},
|
|
1461
|
+
},
|
|
1462
|
+
tips: [
|
|
1463
|
+
"Store the `whsec_` secret the moment create_webhook_subscription or rotate_webhook_subscription_secret returns it — it is not retrievable afterwards.",
|
|
1464
|
+
"Use recordSlugs to keep webhook traffic scoped to the collections that matter — cuts noise and reduces retry pressure.",
|
|
1465
|
+
"The signed value is the raw request body, not a canonical JSON; verify signatures before parsing.",
|
|
1466
|
+
"get_webhook_delivery is the only tool that returns requestPayload and responseBody — list_webhook_deliveries trims them to keep responses manageable.",
|
|
1467
|
+
"Use since/until on list_webhook_deliveries to scope a forensic pass to a time window.",
|
|
1468
|
+
"retry_webhook_delivery preserves the original signature — pair it with a fixed bug on the receiver's side instead of regenerating payloads.",
|
|
1469
|
+
"cancel_webhook_delivery only works while the row is 'retrying'. If the dispatcher has already claimed the row the call returns 409; wait a second and try again.",
|
|
1470
|
+
],
|
|
1471
|
+
},
|
|
1472
|
+
null,
|
|
1473
|
+
2
|
|
1474
|
+
),
|
|
1475
|
+
},
|
|
1476
|
+
],
|
|
1477
|
+
})
|
|
1478
|
+
);
|
|
1479
|
+
|
|
1301
1480
|
// ── Insights ───────────────────────────────────────────────────────
|
|
1302
1481
|
|
|
1303
|
-
server
|
|
1482
|
+
registerTool<any>(server,
|
|
1304
1483
|
"describe_insights",
|
|
1305
1484
|
"Get the schema reference for Centrali anomaly insights. Explains anomaly detection, severity levels, and the acknowledge/dismiss workflow.",
|
|
1306
1485
|
{},
|
|
@@ -1355,7 +1534,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1355
1534
|
|
|
1356
1535
|
// ── Validation ─────────────────────────────────────────────────────
|
|
1357
1536
|
|
|
1358
|
-
server
|
|
1537
|
+
registerTool<any>(server,
|
|
1359
1538
|
"describe_validation",
|
|
1360
1539
|
"Get the schema reference for Centrali data quality validation. Explains scan types, suggestion lifecycle, and how to review/apply fixes.",
|
|
1361
1540
|
{},
|
|
@@ -1419,7 +1598,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1419
1598
|
|
|
1420
1599
|
// ── Pages ──────────────────────────────────────────────────────────
|
|
1421
1600
|
|
|
1422
|
-
server
|
|
1601
|
+
registerTool<any>(server,
|
|
1423
1602
|
"describe_pages",
|
|
1424
1603
|
"Get the schema reference for Centrali pages. Explains page types, the definition structure, sections, blocks, and the publish lifecycle.",
|
|
1425
1604
|
{},
|
|
@@ -1544,7 +1723,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1544
1723
|
|
|
1545
1724
|
// ── Page Definition Schema ─────────────────────────────────────────
|
|
1546
1725
|
|
|
1547
|
-
server
|
|
1726
|
+
registerTool<any>(server,
|
|
1548
1727
|
"describe_page_definition",
|
|
1549
1728
|
"Get the full schema for a page definition — the JSON structure passed to save_page_draft. Explains sections, blocks, data sources, and how they compose together.",
|
|
1550
1729
|
{},
|
|
@@ -1781,7 +1960,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
1781
1960
|
|
|
1782
1961
|
// ── Page Block Types ───────────────────────────────────────────────
|
|
1783
1962
|
|
|
1784
|
-
server
|
|
1963
|
+
registerTool<any>(server,
|
|
1785
1964
|
"describe_page_blocks",
|
|
1786
1965
|
"Get all available page block types and their configuration shapes. Each block type has specific data source requirements and presentation options.",
|
|
1787
1966
|
{},
|
|
@@ -2101,7 +2280,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
2101
2280
|
|
|
2102
2281
|
// ── Page Actions ───────────────────────────────────────────────────
|
|
2103
2282
|
|
|
2104
|
-
server
|
|
2283
|
+
registerTool<any>(server,
|
|
2105
2284
|
"describe_page_actions",
|
|
2106
2285
|
"Get all available page action types and their configuration shapes. Actions define interactive behaviors on blocks (button clicks, row clicks, form submissions).",
|
|
2107
2286
|
{},
|
|
@@ -2247,7 +2426,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
2247
2426
|
|
|
2248
2427
|
// ── Navigation ─────────────────────────────────────────────────────
|
|
2249
2428
|
|
|
2250
|
-
server
|
|
2429
|
+
registerTool<any>(server,
|
|
2251
2430
|
"describe_navigation",
|
|
2252
2431
|
"Get the full schema for the workspace navigation configuration. Explains how to construct the sidebar/nav shell that wraps published pages — item types, grouping, branding, and limits.",
|
|
2253
2432
|
{},
|
|
@@ -2387,7 +2566,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
2387
2566
|
|
|
2388
2567
|
// ── Auth Providers (BYOT) ──────────────────────────────────────────
|
|
2389
2568
|
|
|
2390
|
-
server
|
|
2569
|
+
registerTool<any>(server,
|
|
2391
2570
|
"describe_auth_providers",
|
|
2392
2571
|
"Get the full reference for configuring external auth providers (BYOT — Bring Your Own Token). Explains how to connect Clerk, Auth0, Okta, or any OIDC provider so your app's users authenticate with their existing IdP while Centrali handles authorization.",
|
|
2393
2572
|
{},
|
|
@@ -2516,7 +2695,7 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
2516
2695
|
|
|
2517
2696
|
// ── Service Accounts & IAM ──────────────────────────────────────
|
|
2518
2697
|
|
|
2519
|
-
server
|
|
2698
|
+
registerTool<any>(server,
|
|
2520
2699
|
"describe_service_accounts",
|
|
2521
2700
|
"Get the full reference for managing service accounts, roles, groups, and permissions. Explains the complete IAM setup flow from creating a service account to granting fine-grained access.",
|
|
2522
2701
|
{},
|