@centrali-io/centrali-mcp 4.2.0 → 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.
- package/README.md +25 -1
- package/dist/index.js +4 -0
- package/dist/tools/compute.js +323 -0
- package/dist/tools/describe.d.ts +10 -0
- package/dist/tools/describe.js +1485 -0
- package/dist/tools/orchestrations.js +146 -0
- package/dist/tools/pages.d.ts +3 -0
- package/dist/tools/pages.js +477 -0
- package/dist/tools/smart-queries.js +152 -0
- package/dist/tools/structures.js +117 -0
- package/package.json +2 -2
- package/src/index.ts +4 -0
- package/src/tools/compute.ts +371 -0
- package/src/tools/describe.ts +1798 -0
- package/src/tools/orchestrations.ts +167 -0
- package/src/tools/pages.ts +573 -0
- package/src/tools/smart-queries.ts +175 -0
- package/src/tools/structures.ts +123 -0
|
@@ -93,4 +93,156 @@ function registerSmartQueryTools(server, sdk) {
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
}));
|
|
96
|
+
server.tool("get_smart_query", "Get a smart query by ID. Returns the full query definition including filters, sort, and variable declarations.", {
|
|
97
|
+
recordSlug: zod_1.z.string().describe("The structure's record slug the query belongs to"),
|
|
98
|
+
queryId: zod_1.z.string().describe("The smart query ID (UUID)"),
|
|
99
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ recordSlug, queryId }) {
|
|
100
|
+
try {
|
|
101
|
+
const result = yield sdk.smartQueries.get(recordSlug, queryId);
|
|
102
|
+
return {
|
|
103
|
+
content: [
|
|
104
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
105
|
+
],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
return {
|
|
110
|
+
content: [
|
|
111
|
+
{
|
|
112
|
+
type: "text",
|
|
113
|
+
text: formatError(error, `getting smart query '${queryId}'`),
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
isError: true,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}));
|
|
120
|
+
server.tool("create_smart_query", "Create a new smart query for a collection. Smart queries are reusable, parameterized queries with filter, sort, and variable support.", {
|
|
121
|
+
recordSlug: zod_1.z.string().describe("The structure's record slug to create the query for"),
|
|
122
|
+
name: zod_1.z.string().describe("Display name for the smart query"),
|
|
123
|
+
description: zod_1.z.string().optional().describe("Optional description"),
|
|
124
|
+
queryDefinition: zod_1.z
|
|
125
|
+
.record(zod_1.z.string(), zod_1.z.any())
|
|
126
|
+
.describe("The query definition object with where, sort, limit, select, join, etc."),
|
|
127
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ recordSlug, name, description, queryDefinition }) {
|
|
128
|
+
try {
|
|
129
|
+
const input = { name, queryDefinition };
|
|
130
|
+
if (description !== undefined)
|
|
131
|
+
input.description = description;
|
|
132
|
+
const result = yield sdk.smartQueries.create(recordSlug, input);
|
|
133
|
+
return {
|
|
134
|
+
content: [
|
|
135
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
136
|
+
],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
return {
|
|
141
|
+
content: [
|
|
142
|
+
{
|
|
143
|
+
type: "text",
|
|
144
|
+
text: formatError(error, `creating smart query '${name}' for '${recordSlug}'`),
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
isError: true,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}));
|
|
151
|
+
server.tool("update_smart_query", "Update an existing smart query. Only include the fields you want to change.", {
|
|
152
|
+
recordSlug: zod_1.z.string().describe("The structure's record slug the query belongs to"),
|
|
153
|
+
queryId: zod_1.z.string().describe("The smart query ID (UUID) to update"),
|
|
154
|
+
name: zod_1.z.string().optional().describe("Updated display name"),
|
|
155
|
+
description: zod_1.z.string().optional().describe("Updated description"),
|
|
156
|
+
queryDefinition: zod_1.z
|
|
157
|
+
.record(zod_1.z.string(), zod_1.z.any())
|
|
158
|
+
.optional()
|
|
159
|
+
.describe("Updated query definition object"),
|
|
160
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ recordSlug, queryId, name, description, queryDefinition }) {
|
|
161
|
+
try {
|
|
162
|
+
const input = {};
|
|
163
|
+
if (name !== undefined)
|
|
164
|
+
input.name = name;
|
|
165
|
+
if (description !== undefined)
|
|
166
|
+
input.description = description;
|
|
167
|
+
if (queryDefinition !== undefined)
|
|
168
|
+
input.queryDefinition = queryDefinition;
|
|
169
|
+
const result = yield sdk.smartQueries.update(recordSlug, queryId, 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, `updating smart query '${queryId}'`),
|
|
182
|
+
},
|
|
183
|
+
],
|
|
184
|
+
isError: true,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}));
|
|
188
|
+
server.tool("delete_smart_query", "Delete a smart query by ID.", {
|
|
189
|
+
recordSlug: zod_1.z.string().describe("The structure's record slug the query belongs to"),
|
|
190
|
+
queryId: zod_1.z.string().describe("The smart query ID (UUID) to delete"),
|
|
191
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ recordSlug, queryId }) {
|
|
192
|
+
try {
|
|
193
|
+
yield sdk.smartQueries.delete(recordSlug, queryId);
|
|
194
|
+
return {
|
|
195
|
+
content: [
|
|
196
|
+
{
|
|
197
|
+
type: "text",
|
|
198
|
+
text: `Smart query '${queryId}' deleted from '${recordSlug}'.`,
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
catch (error) {
|
|
204
|
+
return {
|
|
205
|
+
content: [
|
|
206
|
+
{
|
|
207
|
+
type: "text",
|
|
208
|
+
text: formatError(error, `deleting smart query '${queryId}'`),
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
isError: true,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
}));
|
|
215
|
+
server.tool("test_smart_query", "Test execute a query definition without saving it. Useful for validating query syntax and previewing results before creating a smart query.", {
|
|
216
|
+
recordSlug: zod_1.z.string().describe("The structure's record slug to test against"),
|
|
217
|
+
queryDefinition: zod_1.z
|
|
218
|
+
.record(zod_1.z.string(), zod_1.z.any())
|
|
219
|
+
.describe("The query definition to test (where, sort, limit, select, etc.)"),
|
|
220
|
+
variables: zod_1.z
|
|
221
|
+
.record(zod_1.z.string(), zod_1.z.string())
|
|
222
|
+
.optional()
|
|
223
|
+
.describe("Optional variables to substitute in the query"),
|
|
224
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ recordSlug, queryDefinition, variables }) {
|
|
225
|
+
try {
|
|
226
|
+
const input = { queryDefinition };
|
|
227
|
+
if (variables !== undefined)
|
|
228
|
+
input.variables = variables;
|
|
229
|
+
const result = yield sdk.smartQueries.test(recordSlug, input);
|
|
230
|
+
return {
|
|
231
|
+
content: [
|
|
232
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
233
|
+
],
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return {
|
|
238
|
+
content: [
|
|
239
|
+
{
|
|
240
|
+
type: "text",
|
|
241
|
+
text: formatError(error, `test-executing smart query for '${recordSlug}'`),
|
|
242
|
+
},
|
|
243
|
+
],
|
|
244
|
+
isError: true,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}));
|
|
96
248
|
}
|
package/dist/tools/structures.js
CHANGED
|
@@ -135,4 +135,121 @@ function registerCollectionTools(server, sdk) {
|
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
}));
|
|
138
|
+
server.tool("create_collection", "Create a new data collection (schema). Define the name, slug, description, and properties (fields) for the collection.", {
|
|
139
|
+
name: zod_1.z.string().describe("Display name for the collection (e.g., 'Customers')"),
|
|
140
|
+
slug: zod_1.z.string().describe("URL-safe identifier used in API calls (e.g., 'customers')"),
|
|
141
|
+
description: zod_1.z.string().optional().describe("Optional description of the collection"),
|
|
142
|
+
properties: zod_1.z
|
|
143
|
+
.array(zod_1.z.record(zod_1.z.string(), zod_1.z.any()))
|
|
144
|
+
.optional()
|
|
145
|
+
.describe("Array of property definitions. Each property has name, type, and optional config (required, unique, defaultValue, description, config)"),
|
|
146
|
+
enableVersioning: zod_1.z.boolean().optional().describe("Enable record versioning (default: false)"),
|
|
147
|
+
schemaDiscoveryMode: zod_1.z
|
|
148
|
+
.enum(["strict", "flexible"])
|
|
149
|
+
.optional()
|
|
150
|
+
.describe("Schema discovery mode: 'strict' rejects unknown fields, 'flexible' auto-adds them"),
|
|
151
|
+
tags: zod_1.z.array(zod_1.z.string()).optional().describe("Optional tags for organizing collections"),
|
|
152
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ name, slug, description, properties, enableVersioning, schemaDiscoveryMode, tags }) {
|
|
153
|
+
try {
|
|
154
|
+
const input = { name, slug };
|
|
155
|
+
if (description !== undefined)
|
|
156
|
+
input.description = description;
|
|
157
|
+
if (properties !== undefined)
|
|
158
|
+
input.properties = properties;
|
|
159
|
+
if (enableVersioning !== undefined)
|
|
160
|
+
input.enableVersioning = enableVersioning;
|
|
161
|
+
if (schemaDiscoveryMode !== undefined)
|
|
162
|
+
input.schemaDiscoveryMode = schemaDiscoveryMode;
|
|
163
|
+
if (tags !== undefined)
|
|
164
|
+
input.tags = tags;
|
|
165
|
+
const result = yield sdk.collections.create(input);
|
|
166
|
+
return {
|
|
167
|
+
content: [
|
|
168
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
169
|
+
],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
return {
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: "text",
|
|
177
|
+
text: formatError(error, `creating collection '${slug}'`),
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
isError: true,
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}));
|
|
184
|
+
server.tool("update_collection", "Update an existing collection by ID. Only include the fields you want to change.", {
|
|
185
|
+
collectionId: zod_1.z.string().describe("The collection ID (UUID) to update"),
|
|
186
|
+
name: zod_1.z.string().optional().describe("Updated display name"),
|
|
187
|
+
description: zod_1.z.string().optional().describe("Updated description"),
|
|
188
|
+
properties: zod_1.z
|
|
189
|
+
.array(zod_1.z.record(zod_1.z.string(), zod_1.z.any()))
|
|
190
|
+
.optional()
|
|
191
|
+
.describe("Updated array of property definitions (replaces existing properties)"),
|
|
192
|
+
enableVersioning: zod_1.z.boolean().optional().describe("Enable or disable record versioning"),
|
|
193
|
+
tags: zod_1.z.array(zod_1.z.string()).optional().describe("Updated tags"),
|
|
194
|
+
defaultTtlSeconds: zod_1.z.number().nullable().optional().describe("Default TTL in seconds for new records. Set to null to clear."),
|
|
195
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ collectionId, name, description, properties, enableVersioning, tags, defaultTtlSeconds }) {
|
|
196
|
+
try {
|
|
197
|
+
const input = {};
|
|
198
|
+
if (name !== undefined)
|
|
199
|
+
input.name = name;
|
|
200
|
+
if (description !== undefined)
|
|
201
|
+
input.description = description;
|
|
202
|
+
if (properties !== undefined)
|
|
203
|
+
input.properties = properties;
|
|
204
|
+
if (enableVersioning !== undefined)
|
|
205
|
+
input.enableVersioning = enableVersioning;
|
|
206
|
+
if (tags !== undefined)
|
|
207
|
+
input.tags = tags;
|
|
208
|
+
if (defaultTtlSeconds !== undefined)
|
|
209
|
+
input.defaultTtlSeconds = defaultTtlSeconds;
|
|
210
|
+
const result = yield sdk.collections.update(collectionId, input);
|
|
211
|
+
return {
|
|
212
|
+
content: [
|
|
213
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
214
|
+
],
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
catch (error) {
|
|
218
|
+
return {
|
|
219
|
+
content: [
|
|
220
|
+
{
|
|
221
|
+
type: "text",
|
|
222
|
+
text: formatError(error, `updating collection '${collectionId}'`),
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
isError: true,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
}));
|
|
229
|
+
server.tool("delete_collection", "Delete a collection by ID. This permanently removes the collection schema and all its records.", {
|
|
230
|
+
collectionId: zod_1.z.string().describe("The collection ID (UUID) to delete"),
|
|
231
|
+
}, (_a) => __awaiter(this, [_a], void 0, function* ({ collectionId }) {
|
|
232
|
+
try {
|
|
233
|
+
yield sdk.collections.delete(collectionId);
|
|
234
|
+
return {
|
|
235
|
+
content: [
|
|
236
|
+
{
|
|
237
|
+
type: "text",
|
|
238
|
+
text: `Collection '${collectionId}' deleted successfully.`,
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
return {
|
|
245
|
+
content: [
|
|
246
|
+
{
|
|
247
|
+
type: "text",
|
|
248
|
+
text: formatError(error, `deleting collection '${collectionId}'`),
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
isError: true,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
}));
|
|
138
255
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@centrali-io/centrali-mcp",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.2",
|
|
4
4
|
"description": "Centrali MCP Server - AI assistant integration for Centrali workspaces",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"author": "Blueinit",
|
|
26
26
|
"license": "ISC",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@centrali-io/centrali-sdk": "^4.0
|
|
28
|
+
"@centrali-io/centrali-sdk": "^4.2.0",
|
|
29
29
|
"@modelcontextprotocol/sdk": "^1.12.1"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,8 @@ import { registerSmartQueryTools } from "./tools/smart-queries.js";
|
|
|
11
11
|
import { registerOrchestrationTools } from "./tools/orchestrations.js";
|
|
12
12
|
import { registerInsightTools } from "./tools/insights.js";
|
|
13
13
|
import { registerValidationTools } from "./tools/validation.js";
|
|
14
|
+
import { registerPageTools } from "./tools/pages.js";
|
|
15
|
+
import { registerDescribeTools } from "./tools/describe.js";
|
|
14
16
|
import { registerStructureResources, registerCollectionResources } from "./resources/structures.js";
|
|
15
17
|
|
|
16
18
|
function getRequiredEnv(name: string): string {
|
|
@@ -50,6 +52,8 @@ async function main() {
|
|
|
50
52
|
registerOrchestrationTools(server, sdk);
|
|
51
53
|
registerInsightTools(server, sdk);
|
|
52
54
|
registerValidationTools(server, sdk);
|
|
55
|
+
registerPageTools(server, sdk, baseUrl, workspaceId);
|
|
56
|
+
registerDescribeTools(server);
|
|
53
57
|
|
|
54
58
|
// Register resources
|
|
55
59
|
registerCollectionResources(server, sdk);
|
package/src/tools/compute.ts
CHANGED
|
@@ -138,4 +138,375 @@ export function registerComputeTools(server: McpServer, sdk: CentraliSDK) {
|
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
140
|
);
|
|
141
|
+
|
|
142
|
+
// ── Function CRUD tools ──────────────────────────────────────────
|
|
143
|
+
|
|
144
|
+
server.tool(
|
|
145
|
+
"get_function",
|
|
146
|
+
"Get a compute function by ID. Returns the full function definition including code.",
|
|
147
|
+
{
|
|
148
|
+
functionId: z.string().describe("The compute function ID (UUID)"),
|
|
149
|
+
},
|
|
150
|
+
async ({ functionId }) => {
|
|
151
|
+
try {
|
|
152
|
+
const result = await sdk.functions.get(functionId);
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
} catch (error: unknown) {
|
|
159
|
+
return {
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: "text",
|
|
163
|
+
text: formatError(error, `getting function '${functionId}'`),
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
isError: true,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
server.tool(
|
|
173
|
+
"create_function",
|
|
174
|
+
"Create a new compute function. Compute functions are JavaScript code blocks that run server-side.",
|
|
175
|
+
{
|
|
176
|
+
name: z.string().describe("Display name for the function"),
|
|
177
|
+
slug: z.string().describe("URL-safe unique identifier (e.g., 'process-order')"),
|
|
178
|
+
code: z.string().describe("JavaScript source code. Must export an async function: module.exports = async (ctx) => { ... }"),
|
|
179
|
+
description: z.string().optional().describe("Optional description of what the function does"),
|
|
180
|
+
timeout: z.number().optional().describe("Execution timeout in milliseconds (default: 30000)"),
|
|
181
|
+
},
|
|
182
|
+
async ({ name, slug, code, description, timeout }) => {
|
|
183
|
+
try {
|
|
184
|
+
const input: Record<string, any> = { name, slug, code };
|
|
185
|
+
if (description !== undefined) input.description = description;
|
|
186
|
+
if (timeout !== undefined) input.timeout = timeout;
|
|
187
|
+
|
|
188
|
+
const result = await sdk.functions.create(input as any);
|
|
189
|
+
return {
|
|
190
|
+
content: [
|
|
191
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
192
|
+
],
|
|
193
|
+
};
|
|
194
|
+
} catch (error: unknown) {
|
|
195
|
+
return {
|
|
196
|
+
content: [
|
|
197
|
+
{
|
|
198
|
+
type: "text",
|
|
199
|
+
text: formatError(error, `creating function '${slug}'`),
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
isError: true,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
server.tool(
|
|
209
|
+
"update_function",
|
|
210
|
+
"Update an existing compute function by ID. Only include the fields you want to change.",
|
|
211
|
+
{
|
|
212
|
+
functionId: z.string().describe("The compute function ID (UUID) to update"),
|
|
213
|
+
name: z.string().optional().describe("Updated display name"),
|
|
214
|
+
description: z.string().optional().describe("Updated description"),
|
|
215
|
+
code: z.string().optional().describe("Updated JavaScript source code"),
|
|
216
|
+
timeout: z.number().optional().describe("Updated execution timeout in milliseconds"),
|
|
217
|
+
},
|
|
218
|
+
async ({ functionId, name, description, code, timeout }) => {
|
|
219
|
+
try {
|
|
220
|
+
const input: Record<string, any> = {};
|
|
221
|
+
if (name !== undefined) input.name = name;
|
|
222
|
+
if (description !== undefined) input.description = description;
|
|
223
|
+
if (code !== undefined) input.code = code;
|
|
224
|
+
if (timeout !== undefined) input.timeout = timeout;
|
|
225
|
+
|
|
226
|
+
const result = await sdk.functions.update(functionId, input as any);
|
|
227
|
+
return {
|
|
228
|
+
content: [
|
|
229
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
230
|
+
],
|
|
231
|
+
};
|
|
232
|
+
} catch (error: unknown) {
|
|
233
|
+
return {
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
236
|
+
type: "text",
|
|
237
|
+
text: formatError(error, `updating function '${functionId}'`),
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
isError: true,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
);
|
|
245
|
+
|
|
246
|
+
server.tool(
|
|
247
|
+
"delete_function",
|
|
248
|
+
"Delete a compute function by ID.",
|
|
249
|
+
{
|
|
250
|
+
functionId: z.string().describe("The compute function ID (UUID) to delete"),
|
|
251
|
+
},
|
|
252
|
+
async ({ functionId }) => {
|
|
253
|
+
try {
|
|
254
|
+
await sdk.functions.delete(functionId);
|
|
255
|
+
return {
|
|
256
|
+
content: [
|
|
257
|
+
{
|
|
258
|
+
type: "text",
|
|
259
|
+
text: `Function '${functionId}' deleted successfully.`,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
} catch (error: unknown) {
|
|
264
|
+
return {
|
|
265
|
+
content: [
|
|
266
|
+
{
|
|
267
|
+
type: "text",
|
|
268
|
+
text: formatError(error, `deleting function '${functionId}'`),
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
isError: true,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
server.tool(
|
|
278
|
+
"test_function",
|
|
279
|
+
"Test execute code without saving it as a function. Useful for validating function code before creating or updating.",
|
|
280
|
+
{
|
|
281
|
+
code: z.string().describe("JavaScript code to test. Must export an async function: module.exports = async (ctx) => { ... }"),
|
|
282
|
+
input: z
|
|
283
|
+
.record(z.string(), z.any())
|
|
284
|
+
.optional()
|
|
285
|
+
.describe("Optional input data passed to the function as ctx.input"),
|
|
286
|
+
},
|
|
287
|
+
async ({ code, input }) => {
|
|
288
|
+
try {
|
|
289
|
+
const testInput: Record<string, any> = { code };
|
|
290
|
+
if (input !== undefined) testInput.input = input;
|
|
291
|
+
|
|
292
|
+
const result = await sdk.functions.testExecute(testInput as any);
|
|
293
|
+
return {
|
|
294
|
+
content: [
|
|
295
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
296
|
+
],
|
|
297
|
+
};
|
|
298
|
+
} catch (error: unknown) {
|
|
299
|
+
return {
|
|
300
|
+
content: [
|
|
301
|
+
{
|
|
302
|
+
type: "text",
|
|
303
|
+
text: formatError(error, "test-executing function"),
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
isError: true,
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
// ── Trigger CRUD tools ───────────────────────────────────────────
|
|
313
|
+
|
|
314
|
+
server.tool(
|
|
315
|
+
"get_trigger",
|
|
316
|
+
"Get a function trigger by ID. Returns full trigger details including execution type and metadata.",
|
|
317
|
+
{
|
|
318
|
+
triggerId: z.string().describe("The trigger ID (UUID)"),
|
|
319
|
+
},
|
|
320
|
+
async ({ triggerId }) => {
|
|
321
|
+
try {
|
|
322
|
+
const result = await sdk.triggers.getDetails(triggerId);
|
|
323
|
+
return {
|
|
324
|
+
content: [
|
|
325
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
326
|
+
],
|
|
327
|
+
};
|
|
328
|
+
} catch (error: unknown) {
|
|
329
|
+
return {
|
|
330
|
+
content: [
|
|
331
|
+
{
|
|
332
|
+
type: "text",
|
|
333
|
+
text: formatError(error, `getting trigger '${triggerId}'`),
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
isError: true,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
server.tool(
|
|
343
|
+
"create_trigger",
|
|
344
|
+
"Create a new function trigger. Triggers define how and when a compute function is executed.",
|
|
345
|
+
{
|
|
346
|
+
name: z.string().describe("Display name for the trigger"),
|
|
347
|
+
functionId: z.string().describe("The compute function ID (UUID) to execute"),
|
|
348
|
+
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)"),
|
|
351
|
+
description: z.string().optional().describe("Optional description"),
|
|
352
|
+
triggerMetadata: z
|
|
353
|
+
.record(z.string(), z.any())
|
|
354
|
+
.optional()
|
|
355
|
+
.describe("Type-specific configuration. For event-driven: { event, recordSlug }. For scheduled: { scheduleType, cronExpression, timezone }. For webhook: auto-generated URL."),
|
|
356
|
+
enabled: z.boolean().optional().describe("Whether the trigger is enabled (default: true)"),
|
|
357
|
+
},
|
|
358
|
+
async ({ name, functionId, executionType, description, triggerMetadata, enabled }) => {
|
|
359
|
+
try {
|
|
360
|
+
const input: Record<string, any> = { name, functionId, executionType };
|
|
361
|
+
if (description !== undefined) input.description = description;
|
|
362
|
+
if (triggerMetadata !== undefined) input.triggerMetadata = triggerMetadata;
|
|
363
|
+
if (enabled !== undefined) input.enabled = enabled;
|
|
364
|
+
|
|
365
|
+
const result = await sdk.triggers.create(input as any);
|
|
366
|
+
return {
|
|
367
|
+
content: [
|
|
368
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
369
|
+
],
|
|
370
|
+
};
|
|
371
|
+
} catch (error: unknown) {
|
|
372
|
+
return {
|
|
373
|
+
content: [
|
|
374
|
+
{
|
|
375
|
+
type: "text",
|
|
376
|
+
text: formatError(error, `creating trigger '${name}'`),
|
|
377
|
+
},
|
|
378
|
+
],
|
|
379
|
+
isError: true,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
server.tool(
|
|
386
|
+
"update_trigger",
|
|
387
|
+
"Update an existing function trigger by ID. Only include the fields you want to change.",
|
|
388
|
+
{
|
|
389
|
+
triggerId: z.string().describe("The trigger ID (UUID) to update"),
|
|
390
|
+
name: z.string().optional().describe("Updated display name"),
|
|
391
|
+
description: z.string().optional().describe("Updated description"),
|
|
392
|
+
enabled: z.boolean().optional().describe("Enable or disable the trigger"),
|
|
393
|
+
triggerMetadata: z
|
|
394
|
+
.record(z.string(), z.any())
|
|
395
|
+
.optional()
|
|
396
|
+
.describe("Updated type-specific configuration"),
|
|
397
|
+
},
|
|
398
|
+
async ({ triggerId, name, description, enabled, triggerMetadata }) => {
|
|
399
|
+
try {
|
|
400
|
+
const input: Record<string, any> = {};
|
|
401
|
+
if (name !== undefined) input.name = name;
|
|
402
|
+
if (description !== undefined) input.description = description;
|
|
403
|
+
if (enabled !== undefined) input.enabled = enabled;
|
|
404
|
+
if (triggerMetadata !== undefined) input.triggerMetadata = triggerMetadata;
|
|
405
|
+
|
|
406
|
+
const result = await sdk.triggers.update(triggerId, input as any);
|
|
407
|
+
return {
|
|
408
|
+
content: [
|
|
409
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
410
|
+
],
|
|
411
|
+
};
|
|
412
|
+
} catch (error: unknown) {
|
|
413
|
+
return {
|
|
414
|
+
content: [
|
|
415
|
+
{
|
|
416
|
+
type: "text",
|
|
417
|
+
text: formatError(error, `updating trigger '${triggerId}'`),
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
isError: true,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
server.tool(
|
|
427
|
+
"delete_trigger",
|
|
428
|
+
"Delete a function trigger by ID.",
|
|
429
|
+
{
|
|
430
|
+
triggerId: z.string().describe("The trigger ID (UUID) to delete"),
|
|
431
|
+
},
|
|
432
|
+
async ({ triggerId }) => {
|
|
433
|
+
try {
|
|
434
|
+
await sdk.triggers.delete(triggerId);
|
|
435
|
+
return {
|
|
436
|
+
content: [
|
|
437
|
+
{
|
|
438
|
+
type: "text",
|
|
439
|
+
text: `Trigger '${triggerId}' deleted successfully.`,
|
|
440
|
+
},
|
|
441
|
+
],
|
|
442
|
+
};
|
|
443
|
+
} catch (error: unknown) {
|
|
444
|
+
return {
|
|
445
|
+
content: [
|
|
446
|
+
{
|
|
447
|
+
type: "text",
|
|
448
|
+
text: formatError(error, `deleting trigger '${triggerId}'`),
|
|
449
|
+
},
|
|
450
|
+
],
|
|
451
|
+
isError: true,
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
server.tool(
|
|
458
|
+
"pause_trigger",
|
|
459
|
+
"Pause a function trigger. Paused triggers will not fire until resumed.",
|
|
460
|
+
{
|
|
461
|
+
triggerId: z.string().describe("The trigger ID (UUID) to pause"),
|
|
462
|
+
},
|
|
463
|
+
async ({ triggerId }) => {
|
|
464
|
+
try {
|
|
465
|
+
const result = await sdk.triggers.pauseTrigger(triggerId);
|
|
466
|
+
return {
|
|
467
|
+
content: [
|
|
468
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
469
|
+
],
|
|
470
|
+
};
|
|
471
|
+
} catch (error: unknown) {
|
|
472
|
+
return {
|
|
473
|
+
content: [
|
|
474
|
+
{
|
|
475
|
+
type: "text",
|
|
476
|
+
text: formatError(error, `pausing trigger '${triggerId}'`),
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
isError: true,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
);
|
|
484
|
+
|
|
485
|
+
server.tool(
|
|
486
|
+
"resume_trigger",
|
|
487
|
+
"Resume a paused function trigger. The trigger will start firing again on matching events or schedules.",
|
|
488
|
+
{
|
|
489
|
+
triggerId: z.string().describe("The trigger ID (UUID) to resume"),
|
|
490
|
+
},
|
|
491
|
+
async ({ triggerId }) => {
|
|
492
|
+
try {
|
|
493
|
+
const result = await sdk.triggers.resumeTrigger(triggerId);
|
|
494
|
+
return {
|
|
495
|
+
content: [
|
|
496
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
497
|
+
],
|
|
498
|
+
};
|
|
499
|
+
} catch (error: unknown) {
|
|
500
|
+
return {
|
|
501
|
+
content: [
|
|
502
|
+
{
|
|
503
|
+
type: "text",
|
|
504
|
+
text: formatError(error, `resuming trigger '${triggerId}'`),
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
isError: true,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
);
|
|
141
512
|
}
|