@centrali-io/centrali-mcp 5.2.0 → 5.3.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.
@@ -1,32 +1,18 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { CentraliSDK } from "@centrali-io/centrali-sdk";
3
3
  import { z } from "zod";
4
+ import { registerTool, formatError } from "./_register.js";
4
5
 
5
- function formatError(error: unknown, context: string): string {
6
- if (error && typeof error === "object") {
7
- const e = error as Record<string, any>;
8
- if ("message" in e) {
9
- let msg = `Error ${context}`;
10
- if ("code" in e || "status" in e) {
11
- msg += `: [${e.code ?? e.status ?? "ERROR"}] ${e.message}`;
12
- } else {
13
- msg += `: ${e.message}`;
14
- }
15
- if (Array.isArray(e.fieldErrors) && e.fieldErrors.length > 0) {
16
- msg +=
17
- "\nField errors:\n" +
18
- (e.fieldErrors as Array<{ field: string; message: string }>)
19
- .map((f) => ` ${f.field}: ${f.message}`)
20
- .join("\n");
21
- }
22
- return msg;
23
- }
24
- }
25
- return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
26
- }
6
+ type InsightStatus = "active" | "acknowledged" | "dismissed";
7
+ type InsightSeverity = "info" | "warning" | "critical";
27
8
 
28
9
  export function registerInsightTools(server: McpServer, sdk: CentraliSDK) {
29
- server.tool(
10
+ registerTool<{
11
+ recordSlug?: string;
12
+ status?: InsightStatus;
13
+ severity?: InsightSeverity;
14
+ }>(
15
+ server,
30
16
  "list_insights",
31
17
  "List anomaly insights detected by Centrali's AI analysis. Insights flag unusual patterns in your data such as spikes, drops, or outliers.",
32
18
  {
@@ -67,7 +53,8 @@ export function registerInsightTools(server: McpServer, sdk: CentraliSDK) {
67
53
  }
68
54
  );
69
55
 
70
- server.tool(
56
+ registerTool<{ insightId: string }>(
57
+ server,
71
58
  "get_insight",
72
59
  "Get full details of a single anomaly insight by ID.",
73
60
  {
@@ -90,7 +77,8 @@ export function registerInsightTools(server: McpServer, sdk: CentraliSDK) {
90
77
  }
91
78
  );
92
79
 
93
- server.tool(
80
+ registerTool<{ insightId: string }>(
81
+ server,
94
82
  "acknowledge_insight",
95
83
  "Mark an anomaly insight as acknowledged (reviewed/handled). The insight remains visible but is flagged as addressed.",
96
84
  {
@@ -116,7 +104,8 @@ export function registerInsightTools(server: McpServer, sdk: CentraliSDK) {
116
104
  }
117
105
  );
118
106
 
119
- server.tool(
107
+ registerTool<{ insightId: string }>(
108
+ server,
120
109
  "dismiss_insight",
121
110
  "Dismiss an anomaly insight, marking it as a false positive or not relevant.",
122
111
  {
@@ -139,7 +128,8 @@ export function registerInsightTools(server: McpServer, sdk: CentraliSDK) {
139
128
  }
140
129
  );
141
130
 
142
- server.tool(
131
+ registerTool<{ recordSlug?: string }>(
132
+ server,
143
133
  "get_insights_summary",
144
134
  "Get a summary of anomaly insights in the workspace — counts by status and severity. Optionally filter by collection.",
145
135
  {
@@ -167,7 +157,8 @@ export function registerInsightTools(server: McpServer, sdk: CentraliSDK) {
167
157
  }
168
158
  );
169
159
 
170
- server.tool(
160
+ registerTool<{ recordSlug: string }>(
161
+ server,
171
162
  "trigger_anomaly_analysis",
172
163
  "Trigger AI-powered anomaly analysis for a collection. Starts a background analysis to detect unusual patterns. Check list_insights after the scan completes.",
173
164
  {
@@ -1,32 +1,9 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { CentraliSDK } from "@centrali-io/centrali-sdk";
3
3
  import { z } from "zod";
4
-
5
- function formatError(error: unknown, context: string): string {
6
- if (error && typeof error === "object") {
7
- const e = error as Record<string, any>;
8
- if ("message" in e) {
9
- let msg = `Error ${context}`;
10
- if ("code" in e || "status" in e) {
11
- msg += `: [${e.code ?? e.status ?? "ERROR"}] ${e.message}`;
12
- } else {
13
- msg += `: ${e.message}`;
14
- }
15
- if (Array.isArray(e.fieldErrors) && e.fieldErrors.length > 0) {
16
- msg +=
17
- "\nField errors:\n" +
18
- (e.fieldErrors as Array<{ field: string; message: string }>)
19
- .map((f) => ` ${f.field}: ${f.message}`)
20
- .join("\n");
21
- }
22
- return msg;
23
- }
24
- }
25
- return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
26
- }
27
-
4
+ import { registerTool, formatError } from "./_register.js";
28
5
  export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK) {
29
- server.tool(
6
+ registerTool<any>(server,
30
7
  "list_orchestrations",
31
8
  "List all orchestrations in the workspace. Orchestrations are multi-step workflows that chain compute functions together.",
32
9
  {
@@ -59,7 +36,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
59
36
  }
60
37
  );
61
38
 
62
- server.tool(
39
+ registerTool<any>(server,
63
40
  "get_orchestration",
64
41
  "Get full details of a single orchestration by ID, including its step definitions.",
65
42
  {
@@ -85,7 +62,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
85
62
  }
86
63
  );
87
64
 
88
- server.tool(
65
+ registerTool<any>(server,
89
66
  "trigger_orchestration",
90
67
  "Trigger an orchestration run. Creates a new run instance and starts executing the workflow. Optionally pass input data to the run.",
91
68
  {
@@ -126,7 +103,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
126
103
  }
127
104
  );
128
105
 
129
- server.tool(
106
+ registerTool<any>(server,
130
107
  "list_orchestration_runs",
131
108
  "List all runs for an orchestration. Runs represent individual executions of the workflow.",
132
109
  {
@@ -169,7 +146,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
169
146
  }
170
147
  );
171
148
 
172
- server.tool(
149
+ registerTool<any>(server,
173
150
  "get_orchestration_run",
174
151
  "Get details of a specific orchestration run. Set includeSteps=true to see step-by-step execution history.",
175
152
  {
@@ -207,7 +184,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
207
184
  }
208
185
  );
209
186
 
210
- server.tool(
187
+ registerTool<any>(server,
211
188
  "create_orchestration",
212
189
  "Create a new orchestration workflow. Orchestrations chain compute functions together in multi-step workflows.",
213
190
  {
@@ -244,7 +221,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
244
221
  }
245
222
  );
246
223
 
247
- server.tool(
224
+ registerTool<any>(server,
248
225
  "update_orchestration",
249
226
  "Update an existing orchestration by ID. Only include the fields you want to change.",
250
227
  {
@@ -291,7 +268,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
291
268
  }
292
269
  );
293
270
 
294
- server.tool(
271
+ registerTool<any>(server,
295
272
  "delete_orchestration",
296
273
  "Delete an orchestration by ID. This also deletes all runs associated with the orchestration.",
297
274
  {
@@ -322,7 +299,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
322
299
  }
323
300
  );
324
301
 
325
- server.tool(
302
+ registerTool<any>(server,
326
303
  "activate_orchestration",
327
304
  "Activate an orchestration. Active orchestrations can be triggered by scheduled events, record events, and webhooks.",
328
305
  {
@@ -348,7 +325,7 @@ export function registerOrchestrationTools(server: McpServer, sdk: CentraliSDK)
348
325
  }
349
326
  );
350
327
 
351
- server.tool(
328
+ registerTool<any>(server,
352
329
  "pause_orchestration",
353
330
  "Pause an orchestration. Paused orchestrations cannot be triggered by any mechanism.",
354
331
  {
@@ -1,30 +1,9 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { CentraliSDK } from "@centrali-io/centrali-sdk";
3
3
  import { z } from "zod";
4
+ import { registerTool, formatError } from "./_register.js";
4
5
  import axios, { AxiosInstance } from "axios";
5
6
 
6
- function formatError(error: unknown, context: string): string {
7
- if (axios.isAxiosError(error) && error.response?.data) {
8
- const body = error.response.data;
9
- const status = error.response.status;
10
- const message = body.message || body.error || error.message;
11
- return `Error ${context}: [${status}] ${message}`;
12
- }
13
- if (error && typeof error === "object") {
14
- const e = error as Record<string, any>;
15
- if ("message" in e) {
16
- let msg = `Error ${context}`;
17
- if ("code" in e || "status" in e) {
18
- msg += `: [${e.code ?? e.status ?? "ERROR"}] ${e.message}`;
19
- } else {
20
- msg += `: ${e.message}`;
21
- }
22
- return msg;
23
- }
24
- }
25
- return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
26
- }
27
-
28
7
  /**
29
8
  * Derives the pages API base URL from the CENTRALI_URL.
30
9
  * Pattern: https://centrali.io -> https://api.centrali.io/pages
@@ -122,7 +101,7 @@ export function registerPageTools(
122
101
 
123
102
  // ── Page CRUD ──────────────────────────────────────────────────────
124
103
 
125
- server.tool(
104
+ registerTool<any>(server,
126
105
  "list_pages",
127
106
  "List all pages in the workspace. Pages are pre-built UI views (lists, detail views, forms, dashboards) that surface data from collections.",
128
107
  {
@@ -153,7 +132,7 @@ export function registerPageTools(
153
132
  }
154
133
  );
155
134
 
156
- server.tool(
135
+ registerTool<any>(server,
157
136
  "get_page",
158
137
  "Get a page by its ID. Returns the page metadata including name, slug, type, and description.",
159
138
  {
@@ -174,7 +153,7 @@ export function registerPageTools(
174
153
  }
175
154
  );
176
155
 
177
- server.tool(
156
+ registerTool<any>(server,
178
157
  "create_page",
179
158
  `Create a new page in the workspace. A page is a UI view backed by data from collections. Specify the page type: 'list' for data tables, 'detail' for single-record views, 'form' for data entry, 'dashboard' for metrics and charts.
180
159
 
@@ -202,7 +181,7 @@ Navigate-to-page actions can use config.useQueryParams: true to pass selected ro
202
181
  }
203
182
  );
204
183
 
205
- server.tool(
184
+ registerTool<any>(server,
206
185
  "update_page",
207
186
  "Update a page's metadata (name, slug, description). Does not modify the page definition — use save_page_draft for that.",
208
187
  {
@@ -233,7 +212,7 @@ Navigate-to-page actions can use config.useQueryParams: true to pass selected ro
233
212
  }
234
213
  );
235
214
 
236
- server.tool(
215
+ registerTool<any>(server,
237
216
  "delete_page",
238
217
  "Soft-delete a page by its ID. The page will no longer be accessible but can potentially be restored.",
239
218
  {
@@ -256,7 +235,7 @@ Navigate-to-page actions can use config.useQueryParams: true to pass selected ro
256
235
 
257
236
  // ── Drafts & Versions ─────────────────────────────────────────────
258
237
 
259
- server.tool(
238
+ registerTool<any>(server,
260
239
  "save_page_draft",
261
240
  `Save or update the draft definition for a page. The definition describes the page's layout: sections, blocks, data sources, actions, and presentation. This does NOT publish the page — use publish_page after saving.
262
241
 
@@ -305,7 +284,7 @@ Common patterns:
305
284
  }
306
285
  );
307
286
 
308
- server.tool(
287
+ registerTool<any>(server,
309
288
  "get_page_draft",
310
289
  "Get the current draft version of a page, including its full definition (sections, blocks, data sources).",
311
290
  {
@@ -326,7 +305,7 @@ Common patterns:
326
305
  }
327
306
  );
328
307
 
329
- server.tool(
308
+ registerTool<any>(server,
330
309
  "list_page_versions",
331
310
  "List all versions of a page. Each version captures a snapshot of the page definition at a point in time.",
332
311
  {
@@ -355,7 +334,7 @@ Common patterns:
355
334
 
356
335
  // ── Publishing ────────────────────────────────────────────────────
357
336
 
358
- server.tool(
337
+ registerTool<any>(server,
359
338
  "validate_page",
360
339
  "Run validation checks on a page's current draft to determine if it is ready to publish. Returns a list of issues (errors and warnings) that must be resolved before publishing.",
361
340
  {
@@ -376,7 +355,7 @@ Common patterns:
376
355
  }
377
356
  );
378
357
 
379
- server.tool(
358
+ registerTool<any>(server,
380
359
  "publish_page",
381
360
  "Publish the current draft of a page, making it accessible at its runtime URL. Validates the draft first — if there are errors, publishing is rejected with details. Returns the publication record and the public runtime URL.",
382
361
  {
@@ -397,7 +376,7 @@ Common patterns:
397
376
  }
398
377
  );
399
378
 
400
- server.tool(
379
+ registerTool<any>(server,
401
380
  "unpublish_page",
402
381
  "Unpublish a page, making it no longer accessible at its runtime URL. The page definition is preserved and can be re-published later.",
403
382
  {
@@ -420,7 +399,7 @@ Common patterns:
420
399
 
421
400
  // ── Access Policy ─────────────────────────────────────────────────
422
401
 
423
- server.tool(
402
+ registerTool<any>(server,
424
403
  "set_page_access_policy",
425
404
  "Set the access policy for a page. Controls who can view the published page: 'public' (anyone), 'authenticated' (logged-in users), or 'role-gated' (users with specific roles).",
426
405
  {
@@ -453,7 +432,7 @@ Common patterns:
453
432
 
454
433
  // ── Theme ─────────────────────────────────────────────────────────
455
434
 
456
- server.tool(
435
+ registerTool<any>(server,
457
436
  "get_page_theme",
458
437
  "Get the workspace theme configuration used by published pages. Includes primary color, accent color, optional logo URL, and font family.",
459
438
  {},
@@ -472,7 +451,7 @@ Common patterns:
472
451
  }
473
452
  );
474
453
 
475
- server.tool(
454
+ registerTool<any>(server,
476
455
  "set_page_theme",
477
456
  "Set the workspace theme for published pages. Controls the visual branding of all published pages.",
478
457
  {
@@ -502,7 +481,7 @@ Common patterns:
502
481
 
503
482
  // ── Navigation ────────────────────────────────────────────────────
504
483
 
505
- server.tool(
484
+ registerTool<any>(server,
506
485
  "get_navigation",
507
486
  "Get the workspace navigation configuration. Controls the sidebar/nav shell that wraps published pages.",
508
487
  {},
@@ -521,7 +500,7 @@ Common patterns:
521
500
  }
522
501
  );
523
502
 
524
- server.tool(
503
+ registerTool<any>(server,
525
504
  "set_navigation",
526
505
  "Set the workspace navigation configuration. Defines the sidebar items, branding, and grouping for the page navigation shell.",
527
506
  {
@@ -546,7 +525,7 @@ Common patterns:
546
525
  }
547
526
  );
548
527
 
549
- server.tool(
528
+ registerTool<any>(server,
550
529
  "delete_navigation",
551
530
  "Delete the workspace navigation configuration. Pages revert to standalone rendering without a sidebar/nav shell.",
552
531
  {},
@@ -567,7 +546,7 @@ Common patterns:
567
546
 
568
547
  // ── Assembly (AI-assisted page generation) ────────────────────────
569
548
 
570
- server.tool(
549
+ registerTool<any>(server,
571
550
  "generate_starter_pages",
572
551
  "Generate page proposals from collection IDs. Uses guided assembly to create page definitions (list, detail, form, dashboard) tailored to the data schema. Returns proposals that can be reviewed and accepted.",
573
552
  {
@@ -597,7 +576,7 @@ Common patterns:
597
576
  }
598
577
  );
599
578
 
600
- server.tool(
579
+ registerTool<any>(server,
601
580
  "accept_page_proposal",
602
581
  "Accept a generated page proposal and create the page with its initial draft definition. Use after reviewing proposals from generate_starter_pages.",
603
582
  {
@@ -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, { AxiosInstance } 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
  */
@@ -82,7 +61,7 @@ function createRecordsClient(sdk: CentraliSDK, centraliUrl: string, workspaceId:
82
61
  }
83
62
 
84
63
  export function registerRecordTools(server: McpServer, sdk: CentraliSDK, centraliUrl: string, workspaceId: string) {
85
- server.tool(
64
+ registerTool<any>(server,
86
65
  "query_records",
87
66
  "Query records from a collection with optional filters, sorting, pagination, and date range filtering. Filters use 'data.' prefix for custom fields and bracket notation for operators (e.g., 'data.status': 'active', 'data.price[lte]': 100). Use dateWindow for date range queries.",
88
67
  {
@@ -168,7 +147,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
168
147
  }
169
148
  );
170
149
 
171
- server.tool(
150
+ registerTool<any>(server,
172
151
  "get_record",
173
152
  "Get a single record by its ID from a collection. Optionally expand reference fields.",
174
153
  {
@@ -202,7 +181,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
202
181
  }
203
182
  );
204
183
 
205
- server.tool(
184
+ registerTool<any>(server,
206
185
  "create_record",
207
186
  "Create a new record in a collection. Pass the record data as a JSON object with field names matching the collection's properties.",
208
187
  {
@@ -235,7 +214,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
235
214
  }
236
215
  );
237
216
 
238
- server.tool(
217
+ registerTool<any>(server,
239
218
  "update_record",
240
219
  "Update an existing record by ID. Only include the fields you want to change.",
241
220
  {
@@ -267,7 +246,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
267
246
  }
268
247
  );
269
248
 
270
- server.tool(
249
+ registerTool<any>(server,
271
250
  "delete_record",
272
251
  "Delete a record by ID. Performs a soft delete by default (can be restored). Set hard=true for permanent deletion.",
273
252
  {
@@ -307,7 +286,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
307
286
  }
308
287
  );
309
288
 
310
- server.tool(
289
+ registerTool<any>(server,
311
290
  "upsert_record",
312
291
  "Create or update a record atomically. Matches on the provided fields to find an existing record — updates it if found, creates it if not. Returns the record and whether it was 'created' or 'updated'.",
313
292
  {
@@ -345,7 +324,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
345
324
  }
346
325
  );
347
326
 
348
- server.tool(
327
+ registerTool<any>(server,
349
328
  "get_records_by_ids",
350
329
  "Fetch multiple records by their IDs in a single request. Returns an array of records.",
351
330
  {
@@ -369,7 +348,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
369
348
  }
370
349
  );
371
350
 
372
- server.tool(
351
+ registerTool<any>(server,
373
352
  "restore_record",
374
353
  "Restore a soft-deleted record by ID. Only works on records deleted without hard=true.",
375
354
  {
@@ -397,7 +376,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
397
376
 
398
377
  // ── Bulk Operations (1 aggregate event per operation) ───────────────
399
378
 
400
- server.tool(
379
+ registerTool<any>(server,
401
380
  "bulk_create_records",
402
381
  `Bulk create multiple records in a collection. All records are created in a single transaction. Publishes ONE aggregate 'records_bulk_created' event (not one per record). Use this when downstream triggers should process all records together as a batch. Max 1000 records per call. For individual events per record, use batch_create_records instead.`,
403
382
  {
@@ -422,7 +401,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
422
401
  }
423
402
  );
424
403
 
425
- server.tool(
404
+ registerTool<any>(server,
426
405
  "bulk_update_records",
427
406
  `Bulk update multiple records with the same data. All records are updated in a single transaction. Publishes ONE aggregate 'records_bulk_updated' event (not one per record). Use this when all records need the same change and downstream triggers should process them together. For different data per record or individual events, use batch_update_records instead.`,
428
407
  {
@@ -448,7 +427,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
448
427
  }
449
428
  );
450
429
 
451
- server.tool(
430
+ registerTool<any>(server,
452
431
  "bulk_delete_records",
453
432
  `Bulk delete multiple records. All records are deleted in a single transaction. Publishes ONE aggregate 'records_bulk_deleted' event (not one per record). Use this when downstream triggers should process all deletions together. For individual events per deletion, use batch_delete_records instead.`,
454
433
  {
@@ -485,7 +464,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
485
464
 
486
465
  // ── Batch Operations (1 event per record) ──────────────────────────
487
466
 
488
- server.tool(
467
+ registerTool<any>(server,
489
468
  "batch_create_records",
490
469
  `Create multiple records individually. Each record gets its own 'record_created' event. Use this when downstream triggers (functions, webhooks, orchestrations) should process each record separately. Supports partial failure — some records can succeed even if others fail. For a single aggregate event, use bulk_create_records instead.`,
491
470
  {
@@ -516,7 +495,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
516
495
  }
517
496
  );
518
497
 
519
- server.tool(
498
+ registerTool<any>(server,
520
499
  "batch_update_records",
521
500
  `Update multiple records individually with different data per record. Each record gets its own 'record_updated' event. Use this when each record needs different changes and downstream triggers should process each update separately. For the same change applied to all records with a single event, use bulk_update_records instead.`,
522
501
  {
@@ -548,7 +527,7 @@ export function registerRecordTools(server: McpServer, sdk: CentraliSDK, central
548
527
  }
549
528
  );
550
529
 
551
- server.tool(
530
+ registerTool<any>(server,
552
531
  "batch_delete_records",
553
532
  `Delete multiple records individually. Each record gets its own 'record_deleted' event. Use this when downstream triggers should process each deletion separately. For a single aggregate event, use bulk_delete_records instead.`,
554
533
  {
@@ -1,30 +1,15 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { CentraliSDK } from "@centrali-io/centrali-sdk";
3
3
  import { z } from "zod";
4
-
5
- function formatError(error: unknown, context: string): string {
6
- if (error && typeof error === 'object') {
7
- const e = error as Record<string, any>;
8
- if ('message' in e) {
9
- let msg = `Error ${context}`;
10
- if ('code' in e || 'status' in e) {
11
- msg += `: [${e.code ?? e.status ?? 'ERROR'}] ${e.message}`;
12
- } else {
13
- msg += `: ${e.message}`;
14
- }
15
- if (Array.isArray(e.fieldErrors) && e.fieldErrors.length > 0) {
16
- msg += '\nField errors:\n' + (e.fieldErrors as Array<{field: string; message: string}>)
17
- .map(f => ` ${f.field}: ${f.message}`)
18
- .join('\n');
19
- }
20
- return msg;
21
- }
22
- }
23
- return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
24
- }
4
+ import { registerTool, formatError } from "./_register.js";
25
5
 
26
6
  export function registerSearchTools(server: McpServer, sdk: CentraliSDK) {
27
- server.tool(
7
+ registerTool<{
8
+ query: string;
9
+ collections?: string | string[];
10
+ limit?: number;
11
+ }>(
12
+ server,
28
13
  "search_records",
29
14
  "Full-text search across records in the workspace. Powered by Meilisearch. Optionally filter by collection(s) and limit results.",
30
15
  {