@centrali-io/centrali-mcp 4.2.1 → 4.2.3
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/dist/tools/compute.js +323 -0
- package/dist/tools/describe.js +204 -22
- package/dist/tools/orchestrations.js +146 -0
- package/dist/tools/smart-queries.js +152 -0
- package/dist/tools/structures.js +121 -0
- package/package.json +1 -1
- package/src/tools/compute.ts +371 -0
- package/src/tools/describe.ts +214 -25
- package/src/tools/orchestrations.ts +167 -0
- package/src/tools/smart-queries.ts +175 -0
- package/src/tools/structures.ts +127 -0
package/src/tools/describe.ts
CHANGED
|
@@ -32,6 +32,9 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
32
32
|
tools: [
|
|
33
33
|
"list_collections",
|
|
34
34
|
"get_collection",
|
|
35
|
+
"create_collection",
|
|
36
|
+
"update_collection",
|
|
37
|
+
"delete_collection",
|
|
35
38
|
"list_structures (deprecated)",
|
|
36
39
|
"get_structure (deprecated)",
|
|
37
40
|
],
|
|
@@ -61,13 +64,36 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
61
64
|
summary:
|
|
62
65
|
"Server-side JavaScript functions with triggers (on-demand, event-driven, scheduled, webhook).",
|
|
63
66
|
describeWith: "describe_compute",
|
|
64
|
-
tools: [
|
|
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:
|
|
68
86
|
"Reusable, parameterized queries defined in the console. Support {{variable}} substitution.",
|
|
69
87
|
describeWith: "describe_smart_queries",
|
|
70
|
-
tools: [
|
|
88
|
+
tools: [
|
|
89
|
+
"list_smart_queries",
|
|
90
|
+
"get_smart_query",
|
|
91
|
+
"create_smart_query",
|
|
92
|
+
"update_smart_query",
|
|
93
|
+
"delete_smart_query",
|
|
94
|
+
"execute_smart_query",
|
|
95
|
+
"test_smart_query",
|
|
96
|
+
],
|
|
71
97
|
},
|
|
72
98
|
orchestrations: {
|
|
73
99
|
summary:
|
|
@@ -76,6 +102,11 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
76
102
|
tools: [
|
|
77
103
|
"list_orchestrations",
|
|
78
104
|
"get_orchestration",
|
|
105
|
+
"create_orchestration",
|
|
106
|
+
"update_orchestration",
|
|
107
|
+
"delete_orchestration",
|
|
108
|
+
"activate_orchestration",
|
|
109
|
+
"pause_orchestration",
|
|
79
110
|
"trigger_orchestration",
|
|
80
111
|
"list_orchestration_runs",
|
|
81
112
|
"get_orchestration_run",
|
|
@@ -170,38 +201,70 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
170
201
|
},
|
|
171
202
|
property_shape: {
|
|
172
203
|
name: "string — field name (e.g., 'email', 'totalAmount')",
|
|
173
|
-
type: "string —
|
|
204
|
+
type: "string — one of: string, number, boolean, datetime, array, object, reference",
|
|
205
|
+
description: "string | null — optional human-readable description",
|
|
174
206
|
required: "boolean — whether the field is mandatory",
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
207
|
+
nullable: "boolean — whether the field accepts null values",
|
|
208
|
+
isUnique: "boolean — whether values must be unique across records",
|
|
209
|
+
immutable: "boolean — field cannot be changed after creation",
|
|
210
|
+
default: "any | null — default value for new records",
|
|
211
|
+
enum: "any[] | null — restrict to specific allowed values",
|
|
180
212
|
},
|
|
181
213
|
field_types: {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
number:
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
datetime:
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
214
|
+
string:
|
|
215
|
+
"Text field. Options: minLength, maxLength, pattern (regex), renderAs ('textarea'|'secret'|'color'|'code'|'html'|'markdown'), enum (string[]), not (disallowed values), isSecret (boolean). Use enum for select-like behavior.",
|
|
216
|
+
number:
|
|
217
|
+
"Numeric field (integer or decimal). Options: minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, enum (number[]), autoIncrement ({ startAt, incrementBy? }).",
|
|
218
|
+
boolean: "True/false toggle. Options: default (boolean), enum ([true]|[false]).",
|
|
219
|
+
datetime:
|
|
220
|
+
"ISO 8601 date/time field. Options: earliestDate, latestDate, exclusiveEarliest, exclusiveLatest, default (ISO string), enum (ISO string[]).",
|
|
221
|
+
array:
|
|
222
|
+
"Array of typed items. Required: items: { type: 'string'|'number'|'boolean'|'datetime'|'object' }. Options: minItems, maxItems, uniqueItems, itemSchema (PropertyDefinition[] when items.type='object').",
|
|
223
|
+
object:
|
|
224
|
+
"Nested object. Options: properties (PropertyDefinition[]), requiredProperties (string[]), strictProperties (boolean — reject unknown fields).",
|
|
225
|
+
reference:
|
|
226
|
+
"Foreign key to another collection. Required: target (collection recordSlug), relationship ('many-to-one'|'one-to-one'|'many-to-many'), onDelete ('restrict'|'cascade'|'set_null'). Options: targetField (default: 'id'), displayField, nullable (required if onDelete='set_null').",
|
|
227
|
+
},
|
|
228
|
+
examples: {
|
|
229
|
+
string_with_enum:
|
|
230
|
+
'{ "name": "status", "type": "string", "required": true, "enum": ["active", "inactive", "archived"] }',
|
|
231
|
+
number_with_range:
|
|
232
|
+
'{ "name": "price", "type": "number", "minimum": 0, "maximum": 10000 }',
|
|
194
233
|
reference:
|
|
195
|
-
"
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
234
|
+
'{ "name": "categoryId", "type": "reference", "target": "categories", "relationship": "many-to-one", "onDelete": "restrict" }',
|
|
235
|
+
array_of_strings:
|
|
236
|
+
'{ "name": "tags", "type": "array", "items": { "type": "string" } }',
|
|
237
|
+
nested_object:
|
|
238
|
+
'{ "name": "address", "type": "object", "properties": [{ "name": "street", "type": "string" }, { "name": "city", "type": "string" }] }',
|
|
239
|
+
},
|
|
240
|
+
crud_tools: {
|
|
241
|
+
create_collection: {
|
|
242
|
+
description: "Create a new collection with name, slug, properties, and optional settings",
|
|
243
|
+
required_params: ["name", "slug"],
|
|
244
|
+
optional_params: ["description", "properties", "enableVersioning", "schemaDiscoveryMode", "tags"],
|
|
245
|
+
},
|
|
246
|
+
update_collection: {
|
|
247
|
+
description: "Update an existing collection by ID. Partial updates supported.",
|
|
248
|
+
required_params: ["collectionId"],
|
|
249
|
+
optional_params: ["name", "description", "properties", "enableVersioning", "tags", "defaultTtlSeconds"],
|
|
250
|
+
},
|
|
251
|
+
delete_collection: {
|
|
252
|
+
description: "Delete a collection by ID. Permanently removes the schema and all records.",
|
|
253
|
+
required_params: ["collectionId"],
|
|
254
|
+
},
|
|
199
255
|
},
|
|
200
256
|
tips: [
|
|
201
257
|
"Use list_collections to see all collections in the workspace",
|
|
202
258
|
"Use get_collection with a recordSlug to see the full property definitions",
|
|
203
259
|
"The recordSlug is what you use in query_records, create_record, etc.",
|
|
204
260
|
"Reference fields create relationships between collections — use 'expand' parameter in queries to join them",
|
|
261
|
+
"Use create_collection to define new data schemas with typed properties",
|
|
262
|
+
"Properties array defines the fields — each needs at minimum a name and type",
|
|
263
|
+
"Use schemaDiscoveryMode: 'flexible' to auto-add new fields when records are created",
|
|
264
|
+
"For enum/select behavior, use type 'string' with an 'enum' array — there is no 'select' type",
|
|
265
|
+
"For multi-line text, use type 'string' with renderAs: 'textarea'",
|
|
266
|
+
"For JSON blobs, use type 'object' with strictProperties: false",
|
|
267
|
+
"Property options go at the top level of the property object, NOT nested inside a 'config' key",
|
|
205
268
|
],
|
|
206
269
|
},
|
|
207
270
|
null,
|
|
@@ -418,12 +481,72 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
418
481
|
status: "'active' | 'paused'",
|
|
419
482
|
config: "object — type-specific configuration (cron, event filters, etc.)",
|
|
420
483
|
},
|
|
484
|
+
function_crud: {
|
|
485
|
+
get_function: {
|
|
486
|
+
description: "Get a compute function by ID, including its code",
|
|
487
|
+
required_params: ["functionId"],
|
|
488
|
+
},
|
|
489
|
+
create_function: {
|
|
490
|
+
description: "Create a new compute function",
|
|
491
|
+
required_params: ["name", "slug", "code"],
|
|
492
|
+
optional_params: ["description", "timeout"],
|
|
493
|
+
code_format: "module.exports = async (ctx) => { /* your code */ return result; }",
|
|
494
|
+
},
|
|
495
|
+
update_function: {
|
|
496
|
+
description: "Update an existing function. Partial updates supported.",
|
|
497
|
+
required_params: ["functionId"],
|
|
498
|
+
optional_params: ["name", "description", "code", "timeout"],
|
|
499
|
+
},
|
|
500
|
+
delete_function: {
|
|
501
|
+
description: "Delete a compute function by ID",
|
|
502
|
+
required_params: ["functionId"],
|
|
503
|
+
},
|
|
504
|
+
test_function: {
|
|
505
|
+
description: "Test execute code without saving. Returns output, duration, and logs.",
|
|
506
|
+
required_params: ["code"],
|
|
507
|
+
optional_params: ["input"],
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
trigger_crud: {
|
|
511
|
+
get_trigger: {
|
|
512
|
+
description: "Get any trigger by ID (all execution types)",
|
|
513
|
+
required_params: ["triggerId"],
|
|
514
|
+
},
|
|
515
|
+
create_trigger: {
|
|
516
|
+
description: "Create a new function trigger",
|
|
517
|
+
required_params: ["name", "functionId", "executionType"],
|
|
518
|
+
optional_params: ["description", "triggerMetadata", "enabled"],
|
|
519
|
+
triggerMetadata_examples: {
|
|
520
|
+
"event-driven": { event: "record.created", recordSlug: "orders" },
|
|
521
|
+
scheduled: { scheduleType: "cron", cronExpression: "0 9 * * *", timezone: "America/New_York" },
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
update_trigger: {
|
|
525
|
+
description: "Update an existing trigger. Partial updates supported.",
|
|
526
|
+
required_params: ["triggerId"],
|
|
527
|
+
optional_params: ["name", "description", "enabled", "triggerMetadata"],
|
|
528
|
+
},
|
|
529
|
+
delete_trigger: {
|
|
530
|
+
description: "Delete a trigger by ID",
|
|
531
|
+
required_params: ["triggerId"],
|
|
532
|
+
},
|
|
533
|
+
pause_trigger: {
|
|
534
|
+
description: "Pause a trigger to temporarily disable it",
|
|
535
|
+
required_params: ["triggerId"],
|
|
536
|
+
},
|
|
537
|
+
resume_trigger: {
|
|
538
|
+
description: "Resume a paused trigger",
|
|
539
|
+
required_params: ["triggerId"],
|
|
540
|
+
},
|
|
541
|
+
},
|
|
421
542
|
tips: [
|
|
422
543
|
"Use list_functions to see all available functions",
|
|
423
544
|
"Use list_triggers to see how functions are wired to execution events",
|
|
424
545
|
"Only on-demand triggers can be invoked via invoke_trigger — other types fire automatically",
|
|
425
546
|
"Functions receive the trigger payload in their execution context",
|
|
426
|
-
"
|
|
547
|
+
"Use pause_trigger/resume_trigger to temporarily disable triggers without deleting them",
|
|
548
|
+
"Use test_function to validate code before creating or updating a function",
|
|
549
|
+
"Use create_function + create_trigger together to set up a complete compute pipeline",
|
|
427
550
|
],
|
|
428
551
|
},
|
|
429
552
|
null,
|
|
@@ -474,11 +597,43 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
474
597
|
},
|
|
475
598
|
note: "Variable values are always passed as strings — the query engine handles type coercion",
|
|
476
599
|
},
|
|
600
|
+
crud_tools: {
|
|
601
|
+
get_smart_query: {
|
|
602
|
+
description: "Get a smart query by ID, including its full definition",
|
|
603
|
+
required_params: ["recordSlug", "queryId"],
|
|
604
|
+
},
|
|
605
|
+
create_smart_query: {
|
|
606
|
+
description: "Create a new smart query for a collection",
|
|
607
|
+
required_params: ["recordSlug", "name", "queryDefinition"],
|
|
608
|
+
optional_params: ["description"],
|
|
609
|
+
queryDefinition_example: {
|
|
610
|
+
where: { status: { "$eq": "active" } },
|
|
611
|
+
sort: [{ field: "createdAt", direction: "desc" }],
|
|
612
|
+
limit: 100,
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
update_smart_query: {
|
|
616
|
+
description: "Update an existing smart query. Partial updates supported.",
|
|
617
|
+
required_params: ["recordSlug", "queryId"],
|
|
618
|
+
optional_params: ["name", "description", "queryDefinition"],
|
|
619
|
+
},
|
|
620
|
+
delete_smart_query: {
|
|
621
|
+
description: "Delete a smart query by ID",
|
|
622
|
+
required_params: ["recordSlug", "queryId"],
|
|
623
|
+
},
|
|
624
|
+
test_smart_query: {
|
|
625
|
+
description: "Test execute a query definition without saving it. Preview results before creating.",
|
|
626
|
+
required_params: ["recordSlug", "queryDefinition"],
|
|
627
|
+
optional_params: ["variables"],
|
|
628
|
+
},
|
|
629
|
+
},
|
|
477
630
|
tips: [
|
|
478
631
|
"Use list_smart_queries to discover available queries (optionally filter by collection slug)",
|
|
479
632
|
"Smart queries return the same result shape as query_records",
|
|
480
633
|
"Variables are defined when creating the query in the console — check the query's variables array to see what's expected",
|
|
481
634
|
"Prefer smart queries over ad-hoc query_records filters for complex/reusable logic",
|
|
635
|
+
"Use test_smart_query to validate query syntax and preview results before saving",
|
|
636
|
+
"Use create_smart_query to save reusable queries that can be executed with execute_smart_query",
|
|
482
637
|
],
|
|
483
638
|
},
|
|
484
639
|
null,
|
|
@@ -541,8 +696,42 @@ export function registerDescribeTools(server: McpServer) {
|
|
|
541
696
|
startedAt: "ISO 8601 datetime | null",
|
|
542
697
|
completedAt: "ISO 8601 datetime | null",
|
|
543
698
|
},
|
|
699
|
+
crud_tools: {
|
|
700
|
+
create_orchestration: {
|
|
701
|
+
description: "Create a new orchestration workflow",
|
|
702
|
+
required_params: ["slug", "name", "trigger", "steps"],
|
|
703
|
+
optional_params: ["description"],
|
|
704
|
+
trigger_example: { type: "on-demand" },
|
|
705
|
+
step_example: {
|
|
706
|
+
id: "validate",
|
|
707
|
+
type: "compute",
|
|
708
|
+
functionId: "func-uuid",
|
|
709
|
+
onSuccess: { nextStepId: "process" },
|
|
710
|
+
},
|
|
711
|
+
},
|
|
712
|
+
update_orchestration: {
|
|
713
|
+
description: "Update an existing orchestration. Partial updates supported.",
|
|
714
|
+
required_params: ["orchestrationId"],
|
|
715
|
+
optional_params: ["name", "description", "status", "trigger", "steps"],
|
|
716
|
+
},
|
|
717
|
+
delete_orchestration: {
|
|
718
|
+
description: "Delete an orchestration and all its runs",
|
|
719
|
+
required_params: ["orchestrationId"],
|
|
720
|
+
},
|
|
721
|
+
activate_orchestration: {
|
|
722
|
+
description: "Set orchestration status to 'active' so it can be triggered",
|
|
723
|
+
required_params: ["orchestrationId"],
|
|
724
|
+
},
|
|
725
|
+
pause_orchestration: {
|
|
726
|
+
description: "Set orchestration status to 'paused' to prevent triggering",
|
|
727
|
+
required_params: ["orchestrationId"],
|
|
728
|
+
},
|
|
729
|
+
},
|
|
544
730
|
tips: [
|
|
545
731
|
"Use list_orchestrations to see available workflows",
|
|
732
|
+
"Use create_orchestration to define new multi-step workflows",
|
|
733
|
+
"Use activate_orchestration to enable a draft orchestration for triggering",
|
|
734
|
+
"Use pause_orchestration to temporarily disable an orchestration without deleting it",
|
|
546
735
|
"Use trigger_orchestration with an input object to start a run",
|
|
547
736
|
"Use get_orchestration_run with includeSteps=true to see step-by-step execution details",
|
|
548
737
|
"Orchestrations must be 'active' to be triggered — draft orchestrations cannot run",
|
|
@@ -206,4 +206,171 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
|
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
208
|
);
|
|
209
|
+
|
|
210
|
+
server.tool(
|
|
211
|
+
"create_orchestration",
|
|
212
|
+
"Create a new orchestration workflow. Orchestrations chain compute functions together in multi-step workflows.",
|
|
213
|
+
{
|
|
214
|
+
slug: z.string().describe("URL-friendly unique slug (e.g., 'order-processing')"),
|
|
215
|
+
name: z.string().describe("Human-readable name"),
|
|
216
|
+
description: z.string().optional().describe("Optional description of the workflow"),
|
|
217
|
+
trigger: z
|
|
218
|
+
.record(z.string(), z.any())
|
|
219
|
+
.describe("Trigger configuration object. Must include 'type' (on-demand, event-driven, scheduled, webhook)"),
|
|
220
|
+
steps: z
|
|
221
|
+
.array(z.record(z.string(), z.any()))
|
|
222
|
+
.describe("Array of step definitions. Each step has id, type, functionId, and optional onSuccess/onFailure routing"),
|
|
223
|
+
},
|
|
224
|
+
async ({ slug, name, description, trigger, steps }) => {
|
|
225
|
+
try {
|
|
226
|
+
const input: Record<string, any> = { slug, name, trigger, steps };
|
|
227
|
+
if (description !== undefined) input.description = description;
|
|
228
|
+
|
|
229
|
+
const result = await sdk.orchestrations.create(input as any);
|
|
230
|
+
return {
|
|
231
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }],
|
|
232
|
+
};
|
|
233
|
+
} catch (error: unknown) {
|
|
234
|
+
return {
|
|
235
|
+
content: [
|
|
236
|
+
{
|
|
237
|
+
type: "text",
|
|
238
|
+
text: formatError(error, `creating orchestration '${slug}'`),
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
isError: true,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
server.tool(
|
|
248
|
+
"update_orchestration",
|
|
249
|
+
"Update an existing orchestration by ID. Only include the fields you want to change.",
|
|
250
|
+
{
|
|
251
|
+
orchestrationId: z.string().describe("The orchestration ID (UUID) to update"),
|
|
252
|
+
name: z.string().optional().describe("Updated name"),
|
|
253
|
+
description: z.string().optional().describe("Updated description"),
|
|
254
|
+
status: z
|
|
255
|
+
.enum(["draft", "active", "paused"])
|
|
256
|
+
.optional()
|
|
257
|
+
.describe("Updated status"),
|
|
258
|
+
trigger: z
|
|
259
|
+
.record(z.string(), z.any())
|
|
260
|
+
.optional()
|
|
261
|
+
.describe("Updated trigger configuration"),
|
|
262
|
+
steps: z
|
|
263
|
+
.array(z.record(z.string(), z.any()))
|
|
264
|
+
.optional()
|
|
265
|
+
.describe("Updated step definitions"),
|
|
266
|
+
},
|
|
267
|
+
async ({ orchestrationId, name, description, status, trigger, steps }) => {
|
|
268
|
+
try {
|
|
269
|
+
const input: Record<string, any> = {};
|
|
270
|
+
if (name !== undefined) input.name = name;
|
|
271
|
+
if (description !== undefined) input.description = description;
|
|
272
|
+
if (status !== undefined) input.status = status;
|
|
273
|
+
if (trigger !== undefined) input.trigger = trigger;
|
|
274
|
+
if (steps !== undefined) input.steps = steps;
|
|
275
|
+
|
|
276
|
+
const result = await sdk.orchestrations.update(orchestrationId, input as any);
|
|
277
|
+
return {
|
|
278
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }],
|
|
279
|
+
};
|
|
280
|
+
} catch (error: unknown) {
|
|
281
|
+
return {
|
|
282
|
+
content: [
|
|
283
|
+
{
|
|
284
|
+
type: "text",
|
|
285
|
+
text: formatError(error, `updating orchestration '${orchestrationId}'`),
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
isError: true,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
);
|
|
293
|
+
|
|
294
|
+
server.tool(
|
|
295
|
+
"delete_orchestration",
|
|
296
|
+
"Delete an orchestration by ID. This also deletes all runs associated with the orchestration.",
|
|
297
|
+
{
|
|
298
|
+
orchestrationId: z.string().describe("The orchestration ID (UUID) to delete"),
|
|
299
|
+
},
|
|
300
|
+
async ({ orchestrationId }) => {
|
|
301
|
+
try {
|
|
302
|
+
await sdk.orchestrations.delete(orchestrationId);
|
|
303
|
+
return {
|
|
304
|
+
content: [
|
|
305
|
+
{
|
|
306
|
+
type: "text",
|
|
307
|
+
text: `Orchestration '${orchestrationId}' deleted successfully.`,
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
};
|
|
311
|
+
} catch (error: unknown) {
|
|
312
|
+
return {
|
|
313
|
+
content: [
|
|
314
|
+
{
|
|
315
|
+
type: "text",
|
|
316
|
+
text: formatError(error, `deleting orchestration '${orchestrationId}'`),
|
|
317
|
+
},
|
|
318
|
+
],
|
|
319
|
+
isError: true,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
);
|
|
324
|
+
|
|
325
|
+
server.tool(
|
|
326
|
+
"activate_orchestration",
|
|
327
|
+
"Activate an orchestration. Active orchestrations can be triggered by scheduled events, record events, and webhooks.",
|
|
328
|
+
{
|
|
329
|
+
orchestrationId: z.string().describe("The orchestration ID (UUID) to activate"),
|
|
330
|
+
},
|
|
331
|
+
async ({ orchestrationId }) => {
|
|
332
|
+
try {
|
|
333
|
+
const result = await sdk.orchestrations.activate(orchestrationId);
|
|
334
|
+
return {
|
|
335
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }],
|
|
336
|
+
};
|
|
337
|
+
} catch (error: unknown) {
|
|
338
|
+
return {
|
|
339
|
+
content: [
|
|
340
|
+
{
|
|
341
|
+
type: "text",
|
|
342
|
+
text: formatError(error, `activating orchestration '${orchestrationId}'`),
|
|
343
|
+
},
|
|
344
|
+
],
|
|
345
|
+
isError: true,
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
);
|
|
350
|
+
|
|
351
|
+
server.tool(
|
|
352
|
+
"pause_orchestration",
|
|
353
|
+
"Pause an orchestration. Paused orchestrations cannot be triggered by any mechanism.",
|
|
354
|
+
{
|
|
355
|
+
orchestrationId: z.string().describe("The orchestration ID (UUID) to pause"),
|
|
356
|
+
},
|
|
357
|
+
async ({ orchestrationId }) => {
|
|
358
|
+
try {
|
|
359
|
+
const result = await sdk.orchestrations.pause(orchestrationId);
|
|
360
|
+
return {
|
|
361
|
+
content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }],
|
|
362
|
+
};
|
|
363
|
+
} catch (error: unknown) {
|
|
364
|
+
return {
|
|
365
|
+
content: [
|
|
366
|
+
{
|
|
367
|
+
type: "text",
|
|
368
|
+
text: formatError(error, `pausing orchestration '${orchestrationId}'`),
|
|
369
|
+
},
|
|
370
|
+
],
|
|
371
|
+
isError: true,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
);
|
|
209
376
|
}
|
|
@@ -100,4 +100,179 @@ export function registerSmartQueryTools(server: McpServer, sdk: CentraliSDK) {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
);
|
|
103
|
+
|
|
104
|
+
server.tool(
|
|
105
|
+
"get_smart_query",
|
|
106
|
+
"Get a smart query by ID. Returns the full query definition including filters, sort, and variable declarations.",
|
|
107
|
+
{
|
|
108
|
+
recordSlug: z.string().describe("The structure's record slug the query belongs to"),
|
|
109
|
+
queryId: z.string().describe("The smart query ID (UUID)"),
|
|
110
|
+
},
|
|
111
|
+
async ({ recordSlug, queryId }) => {
|
|
112
|
+
try {
|
|
113
|
+
const result = await sdk.smartQueries.get(recordSlug, queryId);
|
|
114
|
+
return {
|
|
115
|
+
content: [
|
|
116
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
} catch (error: unknown) {
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: formatError(error, `getting smart query '${queryId}'`),
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
isError: true,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
server.tool(
|
|
134
|
+
"create_smart_query",
|
|
135
|
+
"Create a new smart query for a collection. Smart queries are reusable, parameterized queries with filter, sort, and variable support.",
|
|
136
|
+
{
|
|
137
|
+
recordSlug: z.string().describe("The structure's record slug to create the query for"),
|
|
138
|
+
name: z.string().describe("Display name for the smart query"),
|
|
139
|
+
description: z.string().optional().describe("Optional description"),
|
|
140
|
+
queryDefinition: z
|
|
141
|
+
.record(z.string(), z.any())
|
|
142
|
+
.describe("The query definition object with where, sort, limit, select, join, etc."),
|
|
143
|
+
},
|
|
144
|
+
async ({ recordSlug, name, description, queryDefinition }) => {
|
|
145
|
+
try {
|
|
146
|
+
const input: Record<string, any> = { name, queryDefinition };
|
|
147
|
+
if (description !== undefined) input.description = description;
|
|
148
|
+
|
|
149
|
+
const result = await sdk.smartQueries.create(recordSlug, input as any);
|
|
150
|
+
return {
|
|
151
|
+
content: [
|
|
152
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
153
|
+
],
|
|
154
|
+
};
|
|
155
|
+
} catch (error: unknown) {
|
|
156
|
+
return {
|
|
157
|
+
content: [
|
|
158
|
+
{
|
|
159
|
+
type: "text",
|
|
160
|
+
text: formatError(error, `creating smart query '${name}' for '${recordSlug}'`),
|
|
161
|
+
},
|
|
162
|
+
],
|
|
163
|
+
isError: true,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
server.tool(
|
|
170
|
+
"update_smart_query",
|
|
171
|
+
"Update an existing smart query. Only include the fields you want to change.",
|
|
172
|
+
{
|
|
173
|
+
recordSlug: z.string().describe("The structure's record slug the query belongs to"),
|
|
174
|
+
queryId: z.string().describe("The smart query ID (UUID) to update"),
|
|
175
|
+
name: z.string().optional().describe("Updated display name"),
|
|
176
|
+
description: z.string().optional().describe("Updated description"),
|
|
177
|
+
queryDefinition: z
|
|
178
|
+
.record(z.string(), z.any())
|
|
179
|
+
.optional()
|
|
180
|
+
.describe("Updated query definition object"),
|
|
181
|
+
},
|
|
182
|
+
async ({ recordSlug, queryId, name, description, queryDefinition }) => {
|
|
183
|
+
try {
|
|
184
|
+
const input: Record<string, any> = {};
|
|
185
|
+
if (name !== undefined) input.name = name;
|
|
186
|
+
if (description !== undefined) input.description = description;
|
|
187
|
+
if (queryDefinition !== undefined) input.queryDefinition = queryDefinition;
|
|
188
|
+
|
|
189
|
+
const result = await sdk.smartQueries.update(recordSlug, queryId, input as any);
|
|
190
|
+
return {
|
|
191
|
+
content: [
|
|
192
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
} catch (error: unknown) {
|
|
196
|
+
return {
|
|
197
|
+
content: [
|
|
198
|
+
{
|
|
199
|
+
type: "text",
|
|
200
|
+
text: formatError(error, `updating smart query '${queryId}'`),
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
isError: true,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
server.tool(
|
|
210
|
+
"delete_smart_query",
|
|
211
|
+
"Delete a smart query by ID.",
|
|
212
|
+
{
|
|
213
|
+
recordSlug: z.string().describe("The structure's record slug the query belongs to"),
|
|
214
|
+
queryId: z.string().describe("The smart query ID (UUID) to delete"),
|
|
215
|
+
},
|
|
216
|
+
async ({ recordSlug, queryId }) => {
|
|
217
|
+
try {
|
|
218
|
+
await sdk.smartQueries.delete(recordSlug, queryId);
|
|
219
|
+
return {
|
|
220
|
+
content: [
|
|
221
|
+
{
|
|
222
|
+
type: "text",
|
|
223
|
+
text: `Smart query '${queryId}' deleted from '${recordSlug}'.`,
|
|
224
|
+
},
|
|
225
|
+
],
|
|
226
|
+
};
|
|
227
|
+
} catch (error: unknown) {
|
|
228
|
+
return {
|
|
229
|
+
content: [
|
|
230
|
+
{
|
|
231
|
+
type: "text",
|
|
232
|
+
text: formatError(error, `deleting smart query '${queryId}'`),
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
isError: true,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
server.tool(
|
|
242
|
+
"test_smart_query",
|
|
243
|
+
"Test execute a query definition without saving it. Useful for validating query syntax and previewing results before creating a smart query.",
|
|
244
|
+
{
|
|
245
|
+
recordSlug: z.string().describe("The structure's record slug to test against"),
|
|
246
|
+
queryDefinition: z
|
|
247
|
+
.record(z.string(), z.any())
|
|
248
|
+
.describe("The query definition to test (where, sort, limit, select, etc.)"),
|
|
249
|
+
variables: z
|
|
250
|
+
.record(z.string(), z.string())
|
|
251
|
+
.optional()
|
|
252
|
+
.describe("Optional variables to substitute in the query"),
|
|
253
|
+
},
|
|
254
|
+
async ({ recordSlug, queryDefinition, variables }) => {
|
|
255
|
+
try {
|
|
256
|
+
const input: Record<string, any> = { queryDefinition };
|
|
257
|
+
if (variables !== undefined) input.variables = variables;
|
|
258
|
+
|
|
259
|
+
const result = await sdk.smartQueries.test(recordSlug, input as any);
|
|
260
|
+
return {
|
|
261
|
+
content: [
|
|
262
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
263
|
+
],
|
|
264
|
+
};
|
|
265
|
+
} catch (error: unknown) {
|
|
266
|
+
return {
|
|
267
|
+
content: [
|
|
268
|
+
{
|
|
269
|
+
type: "text",
|
|
270
|
+
text: formatError(error, `test-executing smart query for '${recordSlug}'`),
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
isError: true,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
);
|
|
103
278
|
}
|