@centrali-io/centrali-mcp 4.2.1 → 4.2.2

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.
@@ -129,4 +129,327 @@ function registerComputeTools(server, sdk) {
129
129
  };
130
130
  }
131
131
  }));
132
+ // ── Function CRUD tools ──────────────────────────────────────────
133
+ server.tool("get_function", "Get a compute function by ID. Returns the full function definition including code.", {
134
+ functionId: zod_1.z.string().describe("The compute function ID (UUID)"),
135
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ functionId }) {
136
+ try {
137
+ const result = yield sdk.functions.get(functionId);
138
+ return {
139
+ content: [
140
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
141
+ ],
142
+ };
143
+ }
144
+ catch (error) {
145
+ return {
146
+ content: [
147
+ {
148
+ type: "text",
149
+ text: formatError(error, `getting function '${functionId}'`),
150
+ },
151
+ ],
152
+ isError: true,
153
+ };
154
+ }
155
+ }));
156
+ server.tool("create_function", "Create a new compute function. Compute functions are JavaScript code blocks that run server-side.", {
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
+ code: zod_1.z.string().describe("JavaScript source code. Must export an async function: module.exports = async (ctx) => { ... }"),
160
+ 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 }) {
163
+ try {
164
+ const input = { name, slug, code };
165
+ if (description !== undefined)
166
+ input.description = description;
167
+ if (timeout !== undefined)
168
+ input.timeout = timeout;
169
+ const result = yield sdk.functions.create(input);
170
+ return {
171
+ content: [
172
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
173
+ ],
174
+ };
175
+ }
176
+ catch (error) {
177
+ return {
178
+ content: [
179
+ {
180
+ type: "text",
181
+ text: formatError(error, `creating function '${slug}'`),
182
+ },
183
+ ],
184
+ isError: true,
185
+ };
186
+ }
187
+ }));
188
+ server.tool("update_function", "Update an existing compute function by ID. Only include the fields you want to change.", {
189
+ functionId: zod_1.z.string().describe("The compute function ID (UUID) to update"),
190
+ name: zod_1.z.string().optional().describe("Updated display name"),
191
+ description: zod_1.z.string().optional().describe("Updated description"),
192
+ 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 }) {
195
+ try {
196
+ const input = {};
197
+ if (name !== undefined)
198
+ input.name = name;
199
+ if (description !== undefined)
200
+ input.description = description;
201
+ if (code !== undefined)
202
+ input.code = code;
203
+ if (timeout !== undefined)
204
+ input.timeout = timeout;
205
+ const result = yield sdk.functions.update(functionId, input);
206
+ return {
207
+ content: [
208
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
209
+ ],
210
+ };
211
+ }
212
+ catch (error) {
213
+ return {
214
+ content: [
215
+ {
216
+ type: "text",
217
+ text: formatError(error, `updating function '${functionId}'`),
218
+ },
219
+ ],
220
+ isError: true,
221
+ };
222
+ }
223
+ }));
224
+ server.tool("delete_function", "Delete a compute function by ID.", {
225
+ functionId: zod_1.z.string().describe("The compute function ID (UUID) to delete"),
226
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ functionId }) {
227
+ try {
228
+ yield sdk.functions.delete(functionId);
229
+ return {
230
+ content: [
231
+ {
232
+ type: "text",
233
+ text: `Function '${functionId}' deleted successfully.`,
234
+ },
235
+ ],
236
+ };
237
+ }
238
+ catch (error) {
239
+ return {
240
+ content: [
241
+ {
242
+ type: "text",
243
+ text: formatError(error, `deleting function '${functionId}'`),
244
+ },
245
+ ],
246
+ isError: true,
247
+ };
248
+ }
249
+ }));
250
+ server.tool("test_function", "Test execute code without saving it as a function. Useful for validating function code before creating or updating.", {
251
+ code: zod_1.z.string().describe("JavaScript code to test. Must export an async function: module.exports = async (ctx) => { ... }"),
252
+ input: zod_1.z
253
+ .record(zod_1.z.string(), zod_1.z.any())
254
+ .optional()
255
+ .describe("Optional input data passed to the function as ctx.input"),
256
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ code, input }) {
257
+ try {
258
+ const testInput = { code };
259
+ if (input !== undefined)
260
+ testInput.input = input;
261
+ const result = yield sdk.functions.testExecute(testInput);
262
+ return {
263
+ content: [
264
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
265
+ ],
266
+ };
267
+ }
268
+ catch (error) {
269
+ return {
270
+ content: [
271
+ {
272
+ type: "text",
273
+ text: formatError(error, "test-executing function"),
274
+ },
275
+ ],
276
+ isError: true,
277
+ };
278
+ }
279
+ }));
280
+ // ── Trigger CRUD tools ───────────────────────────────────────────
281
+ server.tool("get_trigger", "Get a function trigger by ID. Returns full trigger details including execution type and metadata.", {
282
+ triggerId: zod_1.z.string().describe("The trigger ID (UUID)"),
283
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ triggerId }) {
284
+ try {
285
+ const result = yield sdk.triggers.getDetails(triggerId);
286
+ return {
287
+ content: [
288
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
289
+ ],
290
+ };
291
+ }
292
+ catch (error) {
293
+ return {
294
+ content: [
295
+ {
296
+ type: "text",
297
+ text: formatError(error, `getting trigger '${triggerId}'`),
298
+ },
299
+ ],
300
+ isError: true,
301
+ };
302
+ }
303
+ }));
304
+ server.tool("create_trigger", "Create a new function trigger. Triggers define how and when a compute function is executed.", {
305
+ name: zod_1.z.string().describe("Display name for the trigger"),
306
+ functionId: zod_1.z.string().describe("The compute function ID (UUID) to execute"),
307
+ 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
+ description: zod_1.z.string().optional().describe("Optional description"),
311
+ triggerMetadata: zod_1.z
312
+ .record(zod_1.z.string(), zod_1.z.any())
313
+ .optional()
314
+ .describe("Type-specific configuration. For event-driven: { event, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For webhook: auto-generated URL."),
315
+ enabled: zod_1.z.boolean().optional().describe("Whether the trigger is enabled (default: true)"),
316
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ name, functionId, executionType, description, triggerMetadata, enabled }) {
317
+ try {
318
+ const input = { name, functionId, executionType };
319
+ if (description !== undefined)
320
+ input.description = description;
321
+ if (triggerMetadata !== undefined)
322
+ input.triggerMetadata = triggerMetadata;
323
+ if (enabled !== undefined)
324
+ input.enabled = enabled;
325
+ const result = yield sdk.triggers.create(input);
326
+ return {
327
+ content: [
328
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
329
+ ],
330
+ };
331
+ }
332
+ catch (error) {
333
+ return {
334
+ content: [
335
+ {
336
+ type: "text",
337
+ text: formatError(error, `creating trigger '${name}'`),
338
+ },
339
+ ],
340
+ isError: true,
341
+ };
342
+ }
343
+ }));
344
+ server.tool("update_trigger", "Update an existing function trigger by ID. Only include the fields you want to change.", {
345
+ triggerId: zod_1.z.string().describe("The trigger ID (UUID) to update"),
346
+ name: zod_1.z.string().optional().describe("Updated display name"),
347
+ description: zod_1.z.string().optional().describe("Updated description"),
348
+ enabled: zod_1.z.boolean().optional().describe("Enable or disable the trigger"),
349
+ triggerMetadata: zod_1.z
350
+ .record(zod_1.z.string(), zod_1.z.any())
351
+ .optional()
352
+ .describe("Updated type-specific configuration"),
353
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ triggerId, name, description, enabled, triggerMetadata }) {
354
+ try {
355
+ const input = {};
356
+ if (name !== undefined)
357
+ input.name = name;
358
+ if (description !== undefined)
359
+ input.description = description;
360
+ if (enabled !== undefined)
361
+ input.enabled = enabled;
362
+ if (triggerMetadata !== undefined)
363
+ input.triggerMetadata = triggerMetadata;
364
+ const result = yield sdk.triggers.update(triggerId, input);
365
+ return {
366
+ content: [
367
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
368
+ ],
369
+ };
370
+ }
371
+ catch (error) {
372
+ return {
373
+ content: [
374
+ {
375
+ type: "text",
376
+ text: formatError(error, `updating trigger '${triggerId}'`),
377
+ },
378
+ ],
379
+ isError: true,
380
+ };
381
+ }
382
+ }));
383
+ server.tool("delete_trigger", "Delete a function trigger by ID.", {
384
+ triggerId: zod_1.z.string().describe("The trigger ID (UUID) to delete"),
385
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ triggerId }) {
386
+ try {
387
+ yield sdk.triggers.delete(triggerId);
388
+ return {
389
+ content: [
390
+ {
391
+ type: "text",
392
+ text: `Trigger '${triggerId}' deleted successfully.`,
393
+ },
394
+ ],
395
+ };
396
+ }
397
+ catch (error) {
398
+ return {
399
+ content: [
400
+ {
401
+ type: "text",
402
+ text: formatError(error, `deleting trigger '${triggerId}'`),
403
+ },
404
+ ],
405
+ isError: true,
406
+ };
407
+ }
408
+ }));
409
+ server.tool("pause_trigger", "Pause a function trigger. Paused triggers will not fire until resumed.", {
410
+ triggerId: zod_1.z.string().describe("The trigger ID (UUID) to pause"),
411
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ triggerId }) {
412
+ try {
413
+ const result = yield sdk.triggers.pauseTrigger(triggerId);
414
+ return {
415
+ content: [
416
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
417
+ ],
418
+ };
419
+ }
420
+ catch (error) {
421
+ return {
422
+ content: [
423
+ {
424
+ type: "text",
425
+ text: formatError(error, `pausing trigger '${triggerId}'`),
426
+ },
427
+ ],
428
+ isError: true,
429
+ };
430
+ }
431
+ }));
432
+ server.tool("resume_trigger", "Resume a paused function trigger. The trigger will start firing again on matching events or schedules.", {
433
+ triggerId: zod_1.z.string().describe("The trigger ID (UUID) to resume"),
434
+ }, (_a) => __awaiter(this, [_a], void 0, function* ({ triggerId }) {
435
+ try {
436
+ const result = yield sdk.triggers.resumeTrigger(triggerId);
437
+ return {
438
+ content: [
439
+ { type: "text", text: JSON.stringify(result.data, null, 2) },
440
+ ],
441
+ };
442
+ }
443
+ catch (error) {
444
+ return {
445
+ content: [
446
+ {
447
+ type: "text",
448
+ text: formatError(error, `resuming trigger '${triggerId}'`),
449
+ },
450
+ ],
451
+ isError: true,
452
+ };
453
+ }
454
+ }));
132
455
  }
@@ -35,6 +35,9 @@ function registerDescribeTools(server) {
35
35
  tools: [
36
36
  "list_collections",
37
37
  "get_collection",
38
+ "create_collection",
39
+ "update_collection",
40
+ "delete_collection",
38
41
  "list_structures (deprecated)",
39
42
  "get_structure (deprecated)",
40
43
  ],
@@ -61,12 +64,35 @@ function registerDescribeTools(server) {
61
64
  compute: {
62
65
  summary: "Server-side JavaScript functions with triggers (on-demand, event-driven, scheduled, webhook).",
63
66
  describeWith: "describe_compute",
64
- tools: ["list_functions", "list_triggers", "invoke_trigger"],
67
+ tools: [
68
+ "list_functions",
69
+ "get_function",
70
+ "create_function",
71
+ "update_function",
72
+ "delete_function",
73
+ "test_function",
74
+ "list_triggers",
75
+ "get_trigger",
76
+ "create_trigger",
77
+ "update_trigger",
78
+ "delete_trigger",
79
+ "invoke_trigger",
80
+ "pause_trigger",
81
+ "resume_trigger",
82
+ ],
65
83
  },
66
84
  smart_queries: {
67
85
  summary: "Reusable, parameterized queries defined in the console. Support {{variable}} substitution.",
68
86
  describeWith: "describe_smart_queries",
69
- tools: ["list_smart_queries", "execute_smart_query"],
87
+ tools: [
88
+ "list_smart_queries",
89
+ "get_smart_query",
90
+ "create_smart_query",
91
+ "update_smart_query",
92
+ "delete_smart_query",
93
+ "execute_smart_query",
94
+ "test_smart_query",
95
+ ],
70
96
  },
71
97
  orchestrations: {
72
98
  summary: "Multi-step workflows that chain compute functions. Support sequential execution with input/output passing between steps.",
@@ -74,6 +100,11 @@ function registerDescribeTools(server) {
74
100
  tools: [
75
101
  "list_orchestrations",
76
102
  "get_orchestration",
103
+ "create_orchestration",
104
+ "update_orchestration",
105
+ "delete_orchestration",
106
+ "activate_orchestration",
107
+ "pause_orchestration",
77
108
  "trigger_orchestration",
78
109
  "list_orchestration_runs",
79
110
  "get_orchestration_run",
@@ -176,11 +207,30 @@ function registerDescribeTools(server) {
176
207
  json: "Arbitrary JSON object",
177
208
  auto_increment: "Auto-incrementing integer (read-only)",
178
209
  },
210
+ crud_tools: {
211
+ create_collection: {
212
+ description: "Create a new collection with name, slug, properties, and optional settings",
213
+ required_params: ["name", "slug"],
214
+ optional_params: ["description", "properties", "enableVersioning", "schemaDiscoveryMode", "tags"],
215
+ },
216
+ update_collection: {
217
+ description: "Update an existing collection by ID. Partial updates supported.",
218
+ required_params: ["collectionId"],
219
+ optional_params: ["name", "description", "properties", "enableVersioning", "tags", "defaultTtlSeconds"],
220
+ },
221
+ delete_collection: {
222
+ description: "Delete a collection by ID. Permanently removes the schema and all records.",
223
+ required_params: ["collectionId"],
224
+ },
225
+ },
179
226
  tips: [
180
227
  "Use list_collections to see all collections in the workspace",
181
228
  "Use get_collection with a recordSlug to see the full property definitions",
182
229
  "The recordSlug is what you use in query_records, create_record, etc.",
183
230
  "Reference fields create relationships between collections — use 'expand' parameter in queries to join them",
231
+ "Use create_collection to define new data schemas with typed properties",
232
+ "Properties array defines the fields — each needs at minimum a name and type",
233
+ "Use schemaDiscoveryMode: 'flexible' to auto-add new fields when records are created",
184
234
  ],
185
235
  }, null, 2),
186
236
  },
@@ -355,12 +405,72 @@ function registerDescribeTools(server) {
355
405
  status: "'active' | 'paused'",
356
406
  config: "object — type-specific configuration (cron, event filters, etc.)",
357
407
  },
408
+ function_crud: {
409
+ get_function: {
410
+ description: "Get a compute function by ID, including its code",
411
+ required_params: ["functionId"],
412
+ },
413
+ create_function: {
414
+ description: "Create a new compute function",
415
+ required_params: ["name", "slug", "code"],
416
+ optional_params: ["description", "timeout"],
417
+ code_format: "module.exports = async (ctx) => { /* your code */ return result; }",
418
+ },
419
+ update_function: {
420
+ description: "Update an existing function. Partial updates supported.",
421
+ required_params: ["functionId"],
422
+ optional_params: ["name", "description", "code", "timeout"],
423
+ },
424
+ delete_function: {
425
+ description: "Delete a compute function by ID",
426
+ required_params: ["functionId"],
427
+ },
428
+ test_function: {
429
+ description: "Test execute code without saving. Returns output, duration, and logs.",
430
+ required_params: ["code"],
431
+ optional_params: ["input"],
432
+ },
433
+ },
434
+ trigger_crud: {
435
+ get_trigger: {
436
+ description: "Get any trigger by ID (all execution types)",
437
+ required_params: ["triggerId"],
438
+ },
439
+ create_trigger: {
440
+ description: "Create a new function trigger",
441
+ required_params: ["name", "functionId", "executionType"],
442
+ optional_params: ["description", "triggerMetadata", "enabled"],
443
+ triggerMetadata_examples: {
444
+ "event-driven": { event: "record.created", recordSlug: "orders" },
445
+ scheduled: { scheduleType: "cron", cronExpression: "0 9 * * *", timezone: "America/New_York" },
446
+ },
447
+ },
448
+ update_trigger: {
449
+ description: "Update an existing trigger. Partial updates supported.",
450
+ required_params: ["triggerId"],
451
+ optional_params: ["name", "description", "enabled", "triggerMetadata"],
452
+ },
453
+ delete_trigger: {
454
+ description: "Delete a trigger by ID",
455
+ required_params: ["triggerId"],
456
+ },
457
+ pause_trigger: {
458
+ description: "Pause a trigger to temporarily disable it",
459
+ required_params: ["triggerId"],
460
+ },
461
+ resume_trigger: {
462
+ description: "Resume a paused trigger",
463
+ required_params: ["triggerId"],
464
+ },
465
+ },
358
466
  tips: [
359
467
  "Use list_functions to see all available functions",
360
468
  "Use list_triggers to see how functions are wired to execution events",
361
469
  "Only on-demand triggers can be invoked via invoke_trigger — other types fire automatically",
362
470
  "Functions receive the trigger payload in their execution context",
363
- "Triggers can be paused (status: 'paused') without deleting them",
471
+ "Use pause_trigger/resume_trigger to temporarily disable triggers without deleting them",
472
+ "Use test_function to validate code before creating or updating a function",
473
+ "Use create_function + create_trigger together to set up a complete compute pipeline",
364
474
  ],
365
475
  }, null, 2),
366
476
  },
@@ -398,11 +508,43 @@ function registerDescribeTools(server) {
398
508
  },
399
509
  note: "Variable values are always passed as strings — the query engine handles type coercion",
400
510
  },
511
+ crud_tools: {
512
+ get_smart_query: {
513
+ description: "Get a smart query by ID, including its full definition",
514
+ required_params: ["recordSlug", "queryId"],
515
+ },
516
+ create_smart_query: {
517
+ description: "Create a new smart query for a collection",
518
+ required_params: ["recordSlug", "name", "queryDefinition"],
519
+ optional_params: ["description"],
520
+ queryDefinition_example: {
521
+ where: { status: { "$eq": "active" } },
522
+ sort: [{ field: "createdAt", direction: "desc" }],
523
+ limit: 100,
524
+ },
525
+ },
526
+ update_smart_query: {
527
+ description: "Update an existing smart query. Partial updates supported.",
528
+ required_params: ["recordSlug", "queryId"],
529
+ optional_params: ["name", "description", "queryDefinition"],
530
+ },
531
+ delete_smart_query: {
532
+ description: "Delete a smart query by ID",
533
+ required_params: ["recordSlug", "queryId"],
534
+ },
535
+ test_smart_query: {
536
+ description: "Test execute a query definition without saving it. Preview results before creating.",
537
+ required_params: ["recordSlug", "queryDefinition"],
538
+ optional_params: ["variables"],
539
+ },
540
+ },
401
541
  tips: [
402
542
  "Use list_smart_queries to discover available queries (optionally filter by collection slug)",
403
543
  "Smart queries return the same result shape as query_records",
404
544
  "Variables are defined when creating the query in the console — check the query's variables array to see what's expected",
405
545
  "Prefer smart queries over ad-hoc query_records filters for complex/reusable logic",
546
+ "Use test_smart_query to validate query syntax and preview results before saving",
547
+ "Use create_smart_query to save reusable queries that can be executed with execute_smart_query",
406
548
  ],
407
549
  }, null, 2),
408
550
  },
@@ -453,8 +595,42 @@ function registerDescribeTools(server) {
453
595
  startedAt: "ISO 8601 datetime | null",
454
596
  completedAt: "ISO 8601 datetime | null",
455
597
  },
598
+ crud_tools: {
599
+ create_orchestration: {
600
+ description: "Create a new orchestration workflow",
601
+ required_params: ["slug", "name", "trigger", "steps"],
602
+ optional_params: ["description"],
603
+ trigger_example: { type: "on-demand" },
604
+ step_example: {
605
+ id: "validate",
606
+ type: "compute",
607
+ functionId: "func-uuid",
608
+ onSuccess: { nextStepId: "process" },
609
+ },
610
+ },
611
+ update_orchestration: {
612
+ description: "Update an existing orchestration. Partial updates supported.",
613
+ required_params: ["orchestrationId"],
614
+ optional_params: ["name", "description", "status", "trigger", "steps"],
615
+ },
616
+ delete_orchestration: {
617
+ description: "Delete an orchestration and all its runs",
618
+ required_params: ["orchestrationId"],
619
+ },
620
+ activate_orchestration: {
621
+ description: "Set orchestration status to 'active' so it can be triggered",
622
+ required_params: ["orchestrationId"],
623
+ },
624
+ pause_orchestration: {
625
+ description: "Set orchestration status to 'paused' to prevent triggering",
626
+ required_params: ["orchestrationId"],
627
+ },
628
+ },
456
629
  tips: [
457
630
  "Use list_orchestrations to see available workflows",
631
+ "Use create_orchestration to define new multi-step workflows",
632
+ "Use activate_orchestration to enable a draft orchestration for triggering",
633
+ "Use pause_orchestration to temporarily disable an orchestration without deleting it",
458
634
  "Use trigger_orchestration with an input object to start a run",
459
635
  "Use get_orchestration_run with includeSteps=true to see step-by-step execution details",
460
636
  "Orchestrations must be 'active' to be triggered — draft orchestrations cannot run",