@centrali-io/centrali-mcp 5.2.0 → 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.registerDescribeTools = registerDescribeTools;
13
+ const _register_js_1 = require("./_register.js");
13
14
  /**
14
15
  * Introspection tools that teach AI assistants the valid shapes, schemas,
15
16
  * and domain concepts for every Centrali API. These tools return static
@@ -20,7 +21,7 @@ exports.registerDescribeTools = registerDescribeTools;
20
21
  */
21
22
  function registerDescribeTools(server) {
22
23
  // ── Master describe tool ────────────────────────────────────────────
23
- server.tool("describe_centrali", "Get an overview of all Centrali platform capabilities and API domains. Call this first to understand what Centrali can do and which describe_* tool to call for deeper schema details.", {}, () => __awaiter(this, void 0, void 0, function* () {
24
+ (0, _register_js_1.registerTool)(server, "describe_centrali", "Get an overview of all Centrali platform capabilities and API domains. Call this first to understand what Centrali can do and which describe_* tool to call for deeper schema details.", {}, () => __awaiter(this, void 0, void 0, function* () {
24
25
  return ({
25
26
  content: [
26
27
  {
@@ -178,6 +179,22 @@ function registerDescribeTools(server) {
178
179
  "refresh_auth_provider_jwks",
179
180
  ],
180
181
  },
182
+ webhooks: {
183
+ summary: "Outbound webhook subscriptions for record events. Centrali POSTs a signed JSON payload to your URL on record_created, record_updated, record_deleted, and records_bulk_created. Each dispatch is signed with HMAC-SHA256 under the subscription's whsec_ secret and every attempt is recorded in the delivery log for inspection and replay.",
184
+ describeWith: "describe_webhooks",
185
+ tools: [
186
+ "list_webhook_subscriptions",
187
+ "get_webhook_subscription",
188
+ "create_webhook_subscription",
189
+ "update_webhook_subscription",
190
+ "delete_webhook_subscription",
191
+ "rotate_webhook_subscription_secret",
192
+ "list_webhook_deliveries",
193
+ "get_webhook_delivery",
194
+ "retry_webhook_delivery",
195
+ "cancel_webhook_delivery",
196
+ ],
197
+ },
181
198
  service_accounts: {
182
199
  summary: "Machine identities for backend-to-backend API access. Create service accounts with client_credentials OAuth2 flow, manage roles and groups for fine-grained permissions, and introspect access with permission scanning.",
183
200
  describeWith: "describe_service_accounts",
@@ -270,6 +287,7 @@ function registerDescribeTools(server) {
270
287
  "Anomaly insights": { sdk: true, mcp: true, console: true },
271
288
  "Search": { sdk: true, mcp: true, console: true },
272
289
  "Function runs (execution history)": { sdk: true, mcp: true, console: true },
290
+ "Outbound webhooks": { sdk: true, mcp: true, console: true, note: "SDK namespace (client.webhookSubscriptions) and MCP tools wrap the REST surface including delivery replay" },
273
291
  "Service accounts & IAM": { sdk: false, mcp: true, console: true, note: "MCP tools for full SA lifecycle, roles, groups, and permission introspection" },
274
292
  "File uploads": { sdk: true, mcp: false, console: true, note: "SDK-only — use client.uploadFile() in app code" },
275
293
  },
@@ -489,7 +507,7 @@ function registerDescribeTools(server) {
489
507
  });
490
508
  }));
491
509
  // ── Collections ────────────────────────────────────────────────────
492
- server.tool("describe_collections", "Get the schema reference for Centrali collections. Explains field types, property shapes, constraints, and how to define data models.", {}, () => __awaiter(this, void 0, void 0, function* () {
510
+ (0, _register_js_1.registerTool)(server, "describe_collections", "Get the schema reference for Centrali collections. Explains field types, property shapes, constraints, and how to define data models.", {}, () => __awaiter(this, void 0, void 0, function* () {
493
511
  return ({
494
512
  content: [
495
513
  {
@@ -567,7 +585,7 @@ function registerDescribeTools(server) {
567
585
  });
568
586
  }));
569
587
  // ── Records ────────────────────────────────────────────────────────
570
- server.tool("describe_records", "Get the schema reference for Centrali record operations. Explains filter syntax, sort syntax, pagination, expand, and the data. prefix convention.", {}, () => __awaiter(this, void 0, void 0, function* () {
588
+ (0, _register_js_1.registerTool)(server, "describe_records", "Get the schema reference for Centrali record operations. Explains filter syntax, sort syntax, pagination, expand, and the data. prefix convention.", {}, () => __awaiter(this, void 0, void 0, function* () {
571
589
  return ({
572
590
  content: [
573
591
  {
@@ -669,7 +687,7 @@ function registerDescribeTools(server) {
669
687
  });
670
688
  }));
671
689
  // ── Search ─────────────────────────────────────────────────────────
672
- server.tool("describe_search", "Get the schema reference for Centrali full-text search. Explains search behavior, filtering, and result format.", {}, () => __awaiter(this, void 0, void 0, function* () {
690
+ (0, _register_js_1.registerTool)(server, "describe_search", "Get the schema reference for Centrali full-text search. Explains search behavior, filtering, and result format.", {}, () => __awaiter(this, void 0, void 0, function* () {
673
691
  return ({
674
692
  content: [
675
693
  {
@@ -699,7 +717,7 @@ function registerDescribeTools(server) {
699
717
  });
700
718
  }));
701
719
  // ── Compute ────────────────────────────────────────────────────────
702
- server.tool("describe_compute", "Get the schema reference for Centrali compute functions and triggers. Explains function types, trigger execution modes, and invocation patterns.", {}, () => __awaiter(this, void 0, void 0, function* () {
720
+ (0, _register_js_1.registerTool)(server, "describe_compute", "Get the schema reference for Centrali compute functions and triggers. Explains function types, trigger execution modes, and invocation patterns.", {}, () => __awaiter(this, void 0, void 0, function* () {
703
721
  return ({
704
722
  content: [
705
723
  {
@@ -905,10 +923,12 @@ function registerDescribeTools(server) {
905
923
  utilities: "api.uuid, api.formatDate, api.chunk, api.merge, api.math, api.evaluate, api.renderTemplate, api.log, api.logError, api.toCSV, api.toJSON",
906
924
  },
907
925
  secrets: {
908
- description: "Compute functions have NO built-in environment variables or secrets field.",
909
- recommended: "Wrap the function in an orchestration and use encrypted params on the compute step. Encrypted params are stored with AES-256-GCM at rest, decrypted at execution time, and arrive in triggerParams.",
910
- alternative: "Pass secrets in the trigger invocation payload via executionParams. This works but means the calling app is the courier for the secret.",
911
- encrypted_params_flow: "Create orchestration add compute step with encryptedParams: { API_KEY: { value: 'secret', encrypt: true } } at execution, API_KEY arrives decrypted in triggerParams.API_KEY",
926
+ description: "Set encrypted params directly on any trigger's triggerMetadata.params. Shape at create/update: { paramName: { value: 'plaintext', encrypt: true } }. Stored AES-256-GCM at rest, decrypted at execution time, arrive in triggerParams[paramName] as plaintext.",
927
+ works_on: "event-driven, scheduled, http-trigger, endpoint, and on-demand triggers plus orchestration compute steps (same mechanism, scoped to a step via encryptedParams).",
928
+ example_event_driven: "create_trigger({ executionType: 'event-driven', triggerMetadata: { eventType: 'record_created', recordSlug: 'stripe-events', params: { SLACK_WEBHOOK_URL: { value: 'https://hooks.slack.com/...', encrypt: true } } } }) — function accesses triggerParams.SLACK_WEBHOOK_URL as plaintext.",
929
+ update_semantics: "To rotate a value: send { KEY: { value: 'new-plaintext', encrypt: true } }. To preserve an existing encrypted value without rotating: send { KEY: { value: '********', encrypted: true, keyVersion: N } } (use get_trigger to see the stored shape).",
930
+ alternative: "Pass secrets in the invocation payload via executionParams — only when the caller is already holding the secret and you don't want to store it on the trigger.",
931
+ orchestration_note: "Orchestration compute steps use encryptedParams with the same { value, encrypt: true } shape — equivalent mechanism, just scoped to a single step.",
912
932
  },
913
933
  async_execution: {
914
934
  description: "Trigger invocation is ASYNCHRONOUS. invoke_trigger returns a job ID, not the execution result. There are two ways to get the result.",
@@ -946,7 +966,7 @@ function registerDescribeTools(server) {
946
966
  "Use get_function_run or list_function_runs to check execution results after invoking a trigger",
947
967
  "Use api.crypto.signJwt() for GitHub App, Google Cloud, or Azure AD authentication flows",
948
968
  "Before creating functions that call external APIs, add the target domains with add_allowed_domain",
949
- "For secrets (API keys, credentials), use orchestration encrypted params — see the 'secrets' section above",
969
+ "For secrets (API keys, credentials), set encrypted params on the trigger (triggerMetadata.params with { value, encrypt: true }) — see the 'secrets' section above",
950
970
  ],
951
971
  }, null, 2),
952
972
  },
@@ -954,7 +974,7 @@ function registerDescribeTools(server) {
954
974
  });
955
975
  }));
956
976
  // ── Smart Queries ──────────────────────────────────────────────────
957
- server.tool("describe_smart_queries", "Get the schema reference for Centrali smart queries. Explains parameterized queries, variable substitution, and execution.", {}, () => __awaiter(this, void 0, void 0, function* () {
977
+ (0, _register_js_1.registerTool)(server, "describe_smart_queries", "Get the schema reference for Centrali smart queries. Explains parameterized queries, variable substitution, and execution.", {}, () => __awaiter(this, void 0, void 0, function* () {
958
978
  return ({
959
979
  content: [
960
980
  {
@@ -1028,7 +1048,7 @@ function registerDescribeTools(server) {
1028
1048
  });
1029
1049
  }));
1030
1050
  // ── Orchestrations ─────────────────────────────────────────────────
1031
- server.tool("describe_orchestrations", "Get the schema reference for Centrali orchestrations. Explains multi-step workflows, runs, steps, and execution model.", {}, () => __awaiter(this, void 0, void 0, function* () {
1051
+ (0, _register_js_1.registerTool)(server, "describe_orchestrations", "Get the schema reference for Centrali orchestrations. Explains multi-step workflows, runs, steps, and execution model.", {}, () => __awaiter(this, void 0, void 0, function* () {
1032
1052
  return ({
1033
1053
  content: [
1034
1054
  {
@@ -1197,8 +1217,141 @@ function registerDescribeTools(server) {
1197
1217
  ],
1198
1218
  });
1199
1219
  }));
1220
+ // ── Webhooks ───────────────────────────────────────────────────────
1221
+ (0, _register_js_1.registerTool)(server, "describe_webhooks", "Get the schema reference for Centrali outbound webhooks. Explains subscription shape, supported event types, signature verification, retry behavior, and delivery-status lifecycle.", {}, () => __awaiter(this, void 0, void 0, function* () {
1222
+ return ({
1223
+ content: [
1224
+ {
1225
+ type: "text",
1226
+ text: JSON.stringify({
1227
+ domain: "Webhook Subscriptions",
1228
+ description: "Centrali emits record lifecycle events to external URLs. A subscription binds an HTTPS URL to one or more event types (optionally scoped to a subset of collections). Every dispatch is signed with HMAC-SHA256 and recorded in the delivery log — successes, retries, and terminal failures are all preserved.",
1229
+ subscription_shape: {
1230
+ id: "UUID",
1231
+ name: "string",
1232
+ url: "string — HTTPS URL that receives the POSTed payload",
1233
+ events: "RecordEventType[] — subscribed events",
1234
+ recordSlugs: "string[] — restrict to these collections. An empty array (or null on a read from an older row) means the subscription receives events for all collections. On update_webhook_subscription, pass [] to clear the restriction; omit the field to leave scope unchanged.",
1235
+ active: "boolean — when false, dispatches are skipped",
1236
+ secret: "string | undefined — `whsec_<base64url>` signing secret. Returned ONLY on create_webhook_subscription and rotate_webhook_subscription_secret; omitted on list/get.",
1237
+ createdAt: "ISO 8601 datetime",
1238
+ updatedAt: "ISO 8601 datetime",
1239
+ },
1240
+ event_types: {
1241
+ record_created: "A new record was inserted",
1242
+ record_updated: "An existing record was modified",
1243
+ record_deleted: "A record was deleted (soft or hard)",
1244
+ records_bulk_created: "Multiple records were inserted in a batch",
1245
+ },
1246
+ outbound_payload_shape: {
1247
+ description: "Body shape Centrali POSTs to the subscribed URL. JSON-serialized; the raw bytes of this body are what gets HMAC-signed into X-Signature.",
1248
+ event: "string — one of 'record_created' | 'record_updated' | 'record_deleted' | 'records_bulk_created'",
1249
+ workspaceSlug: "string — the workspace that produced the event",
1250
+ recordSlug: "string | undefined — the collection slug (absent on some bulk events)",
1251
+ recordId: "string — the affected record's UUID (or the batch marker for bulk events)",
1252
+ data: "object | undefined — the record snapshot for created/updated events (absent on deletes)",
1253
+ timestamp: "string | undefined — ISO 8601 time the event was emitted",
1254
+ createdBy: "string | undefined — actor user ID; populated on 'record_created'",
1255
+ updatedBy: "string | undefined — actor user ID; populated on 'record_updated'",
1256
+ deletedBy: "string | undefined — actor user ID; populated on 'record_deleted'",
1257
+ note: "Actor fields are per-event: a create delivery carries createdBy, an update carries updatedBy, a delete carries deletedBy. They are the source of truth for 'who did this' — don't infer it from `data`.",
1258
+ },
1259
+ signature: {
1260
+ header: "X-Signature",
1261
+ algorithm: "HMAC-SHA256",
1262
+ secret_format: "`whsec_<base64url>` — strip the `whsec_` prefix and base64url-decode the remainder to get the raw HMAC key bytes.",
1263
+ signed_value: "The raw JSON request body (the outbound_payload_shape above, as bytes). Verify before parsing.",
1264
+ output_encoding: "base64 (standard, not base64url)",
1265
+ verify_example: [
1266
+ "// Node.js verification",
1267
+ "const key = Buffer.from(secret.replace(/^whsec_/, ''), 'base64url');",
1268
+ "const expected = crypto.createHmac('sha256', key).update(rawBody).digest('base64');",
1269
+ "// then timing-safe compare expected to req.headers['x-signature']",
1270
+ ].join("\n"),
1271
+ },
1272
+ delivery_shape: {
1273
+ id: "UUID",
1274
+ webhookSubscriptionId: "UUID — parent subscription",
1275
+ event: "string — the event name that triggered the dispatch",
1276
+ status: "'success' | 'failed' | 'retrying'",
1277
+ attemptCount: "number — number of HTTP attempts made against the target",
1278
+ httpStatus: "number | null — the response status on the last attempt",
1279
+ lastError: "string | null — last error message; 'Cancelled by user' for cancelled retries",
1280
+ lastAttemptAt: "ISO 8601 datetime",
1281
+ nextAttemptAt: "ISO 8601 datetime | null — scheduled time of the next retry (null when terminal)",
1282
+ requestPayload: "object — only present on get_webhook_delivery (list_webhook_deliveries trims it for efficiency)",
1283
+ responseBody: "string | null — first 1000 chars of the target response; only present on get_webhook_delivery",
1284
+ replayedFrom: "UUID | null — delivery ID this row was replayed from; null for originals",
1285
+ createdAt: "ISO 8601 datetime",
1286
+ updatedAt: "ISO 8601 datetime",
1287
+ },
1288
+ retry_behavior: {
1289
+ description: "Failed deliveries retry with fixed backoffs. After exhausting all attempts the row terminates as 'failed'. Circuit-open rejections count as spent attempts.",
1290
+ max_attempts: 5,
1291
+ terminal_statuses: ["success", "failed"],
1292
+ replay: "retry_webhook_delivery inserts a new delivery row and preserves the original payload and signature. The retry counter restarts for the replay.",
1293
+ cancel: "cancel_webhook_delivery only works on 'retrying' rows. It flips the row to 'failed' with lastError='Cancelled by user' and clears nextAttemptAt.",
1294
+ },
1295
+ crud_tools: {
1296
+ create_webhook_subscription: {
1297
+ description: "Create a subscription. The signing secret is ONLY returned on this call — surface it to the user once.",
1298
+ required_params: ["name", "url", "events"],
1299
+ optional_params: ["recordSlugs", "active"],
1300
+ example: {
1301
+ name: "Orders webhook",
1302
+ url: "https://api.example.com/hooks/centrali",
1303
+ events: ["record_created", "record_updated"],
1304
+ recordSlugs: ["orders"],
1305
+ },
1306
+ },
1307
+ update_webhook_subscription: {
1308
+ description: "Update editable fields. The signing secret is server-managed — use rotate instead.",
1309
+ required_params: ["subscriptionId"],
1310
+ optional_params: ["name", "url", "events", "recordSlugs", "active"],
1311
+ },
1312
+ rotate_webhook_subscription_secret: {
1313
+ description: "Regenerate the signing secret. Immediate cutover — surface the new secret to the user; it is not returned on reads.",
1314
+ required_params: ["subscriptionId"],
1315
+ },
1316
+ delete_webhook_subscription: {
1317
+ description: "Delete a subscription. Historical delivery rows are retained for audit.",
1318
+ required_params: ["subscriptionId"],
1319
+ },
1320
+ list_webhook_deliveries: {
1321
+ description: "List deliveries for a subscription. Rows omit the request payload and response body — fetch them via get_webhook_delivery when needed.",
1322
+ required_params: ["subscriptionId"],
1323
+ optional_params: ["status", "since", "until", "limit", "offset"],
1324
+ },
1325
+ get_webhook_delivery: {
1326
+ description: "Get a single delivery including the full request payload and response body.",
1327
+ required_params: ["subscriptionId", "deliveryId"],
1328
+ },
1329
+ retry_webhook_delivery: {
1330
+ description: "Replay a delivery. Works on any non-retrying row (use cancel first if the row is still retrying).",
1331
+ required_params: ["deliveryId"],
1332
+ note: "deliveryId is the global delivery ID — it does NOT need to be nested under a subscription because the backend route is /webhook-subscriptions/deliveries/{id}/retry.",
1333
+ },
1334
+ cancel_webhook_delivery: {
1335
+ description: "Cancel a delivery that is currently retrying. Returns 409 if the row is not retrying or is mid-dispatch.",
1336
+ required_params: ["deliveryId"],
1337
+ },
1338
+ },
1339
+ tips: [
1340
+ "Store the `whsec_` secret the moment create_webhook_subscription or rotate_webhook_subscription_secret returns it — it is not retrievable afterwards.",
1341
+ "Use recordSlugs to keep webhook traffic scoped to the collections that matter — cuts noise and reduces retry pressure.",
1342
+ "The signed value is the raw request body, not a canonical JSON; verify signatures before parsing.",
1343
+ "get_webhook_delivery is the only tool that returns requestPayload and responseBody — list_webhook_deliveries trims them to keep responses manageable.",
1344
+ "Use since/until on list_webhook_deliveries to scope a forensic pass to a time window.",
1345
+ "retry_webhook_delivery preserves the original signature — pair it with a fixed bug on the receiver's side instead of regenerating payloads.",
1346
+ "cancel_webhook_delivery only works while the row is 'retrying'. If the dispatcher has already claimed the row the call returns 409; wait a second and try again.",
1347
+ ],
1348
+ }, null, 2),
1349
+ },
1350
+ ],
1351
+ });
1352
+ }));
1200
1353
  // ── Insights ───────────────────────────────────────────────────────
1201
- server.tool("describe_insights", "Get the schema reference for Centrali anomaly insights. Explains anomaly detection, severity levels, and the acknowledge/dismiss workflow.", {}, () => __awaiter(this, void 0, void 0, function* () {
1354
+ (0, _register_js_1.registerTool)(server, "describe_insights", "Get the schema reference for Centrali anomaly insights. Explains anomaly detection, severity levels, and the acknowledge/dismiss workflow.", {}, () => __awaiter(this, void 0, void 0, function* () {
1202
1355
  return ({
1203
1356
  content: [
1204
1357
  {
@@ -1241,7 +1394,7 @@ function registerDescribeTools(server) {
1241
1394
  });
1242
1395
  }));
1243
1396
  // ── Validation ─────────────────────────────────────────────────────
1244
- server.tool("describe_validation", "Get the schema reference for Centrali data quality validation. Explains scan types, suggestion lifecycle, and how to review/apply fixes.", {}, () => __awaiter(this, void 0, void 0, function* () {
1397
+ (0, _register_js_1.registerTool)(server, "describe_validation", "Get the schema reference for Centrali data quality validation. Explains scan types, suggestion lifecycle, and how to review/apply fixes.", {}, () => __awaiter(this, void 0, void 0, function* () {
1245
1398
  return ({
1246
1399
  content: [
1247
1400
  {
@@ -1288,7 +1441,7 @@ function registerDescribeTools(server) {
1288
1441
  });
1289
1442
  }));
1290
1443
  // ── Pages ──────────────────────────────────────────────────────────
1291
- server.tool("describe_pages", "Get the schema reference for Centrali pages. Explains page types, the definition structure, sections, blocks, and the publish lifecycle.", {}, () => __awaiter(this, void 0, void 0, function* () {
1444
+ (0, _register_js_1.registerTool)(server, "describe_pages", "Get the schema reference for Centrali pages. Explains page types, the definition structure, sections, blocks, and the publish lifecycle.", {}, () => __awaiter(this, void 0, void 0, function* () {
1292
1445
  return ({
1293
1446
  content: [
1294
1447
  {
@@ -1388,7 +1541,7 @@ function registerDescribeTools(server) {
1388
1541
  });
1389
1542
  }));
1390
1543
  // ── Page Definition Schema ─────────────────────────────────────────
1391
- server.tool("describe_page_definition", "Get the full schema for a page definition — the JSON structure passed to save_page_draft. Explains sections, blocks, data sources, and how they compose together.", {}, () => __awaiter(this, void 0, void 0, function* () {
1544
+ (0, _register_js_1.registerTool)(server, "describe_page_definition", "Get the full schema for a page definition — the JSON structure passed to save_page_draft. Explains sections, blocks, data sources, and how they compose together.", {}, () => __awaiter(this, void 0, void 0, function* () {
1392
1545
  return ({
1393
1546
  content: [
1394
1547
  {
@@ -1594,7 +1747,7 @@ function registerDescribeTools(server) {
1594
1747
  });
1595
1748
  }));
1596
1749
  // ── Page Block Types ───────────────────────────────────────────────
1597
- server.tool("describe_page_blocks", "Get all available page block types and their configuration shapes. Each block type has specific data source requirements and presentation options.", {}, () => __awaiter(this, void 0, void 0, function* () {
1750
+ (0, _register_js_1.registerTool)(server, "describe_page_blocks", "Get all available page block types and their configuration shapes. Each block type has specific data source requirements and presentation options.", {}, () => __awaiter(this, void 0, void 0, function* () {
1598
1751
  return ({
1599
1752
  content: [
1600
1753
  {
@@ -1876,7 +2029,7 @@ function registerDescribeTools(server) {
1876
2029
  });
1877
2030
  }));
1878
2031
  // ── Page Actions ───────────────────────────────────────────────────
1879
- server.tool("describe_page_actions", "Get all available page action types and their configuration shapes. Actions define interactive behaviors on blocks (button clicks, row clicks, form submissions).", {}, () => __awaiter(this, void 0, void 0, function* () {
2032
+ (0, _register_js_1.registerTool)(server, "describe_page_actions", "Get all available page action types and their configuration shapes. Actions define interactive behaviors on blocks (button clicks, row clicks, form submissions).", {}, () => __awaiter(this, void 0, void 0, function* () {
1880
2033
  return ({
1881
2034
  content: [
1882
2035
  {
@@ -1988,7 +2141,7 @@ function registerDescribeTools(server) {
1988
2141
  });
1989
2142
  }));
1990
2143
  // ── Navigation ─────────────────────────────────────────────────────
1991
- server.tool("describe_navigation", "Get the full schema for the workspace navigation configuration. Explains how to construct the sidebar/nav shell that wraps published pages — item types, grouping, branding, and limits.", {}, () => __awaiter(this, void 0, void 0, function* () {
2144
+ (0, _register_js_1.registerTool)(server, "describe_navigation", "Get the full schema for the workspace navigation configuration. Explains how to construct the sidebar/nav shell that wraps published pages — item types, grouping, branding, and limits.", {}, () => __awaiter(this, void 0, void 0, function* () {
1992
2145
  return ({
1993
2146
  content: [
1994
2147
  {
@@ -2104,7 +2257,7 @@ function registerDescribeTools(server) {
2104
2257
  });
2105
2258
  }));
2106
2259
  // ── Auth Providers (BYOT) ──────────────────────────────────────────
2107
- server.tool("describe_auth_providers", "Get the full reference for configuring external auth providers (BYOT — Bring Your Own Token). Explains how to connect Clerk, Auth0, Okta, or any OIDC provider so your app's users authenticate with their existing IdP while Centrali handles authorization.", {}, () => __awaiter(this, void 0, void 0, function* () {
2260
+ (0, _register_js_1.registerTool)(server, "describe_auth_providers", "Get the full reference for configuring external auth providers (BYOT — Bring Your Own Token). Explains how to connect Clerk, Auth0, Okta, or any OIDC provider so your app's users authenticate with their existing IdP while Centrali handles authorization.", {}, () => __awaiter(this, void 0, void 0, function* () {
2108
2261
  return ({
2109
2262
  content: [
2110
2263
  {
@@ -2223,7 +2376,7 @@ function registerDescribeTools(server) {
2223
2376
  });
2224
2377
  }));
2225
2378
  // ── Service Accounts & IAM ──────────────────────────────────────
2226
- server.tool("describe_service_accounts", "Get the full reference for managing service accounts, roles, groups, and permissions. Explains the complete IAM setup flow from creating a service account to granting fine-grained access.", {}, () => __awaiter(this, void 0, void 0, function* () {
2379
+ (0, _register_js_1.registerTool)(server, "describe_service_accounts", "Get the full reference for managing service accounts, roles, groups, and permissions. Explains the complete IAM setup flow from creating a service account to granting fine-grained access.", {}, () => __awaiter(this, void 0, void 0, function* () {
2227
2380
  return ({
2228
2381
  content: [
2229
2382
  {
@@ -11,32 +11,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.registerInsightTools = registerInsightTools;
13
13
  const zod_1 = require("zod");
14
- function formatError(error, context) {
15
- var _a, _b;
16
- if (error && typeof error === "object") {
17
- const e = error;
18
- if ("message" in e) {
19
- let msg = `Error ${context}`;
20
- if ("code" in e || "status" in e) {
21
- msg += `: [${(_b = (_a = e.code) !== null && _a !== void 0 ? _a : e.status) !== null && _b !== void 0 ? _b : "ERROR"}] ${e.message}`;
22
- }
23
- else {
24
- msg += `: ${e.message}`;
25
- }
26
- if (Array.isArray(e.fieldErrors) && e.fieldErrors.length > 0) {
27
- msg +=
28
- "\nField errors:\n" +
29
- e.fieldErrors
30
- .map((f) => ` ${f.field}: ${f.message}`)
31
- .join("\n");
32
- }
33
- return msg;
34
- }
35
- }
36
- return `Error ${context}: ${error instanceof Error ? error.message : String(error)}`;
37
- }
14
+ const _register_js_1 = require("./_register.js");
38
15
  function registerInsightTools(server, sdk) {
39
- server.tool("list_insights", "List anomaly insights detected by Centrali's AI analysis. Insights flag unusual patterns in your data such as spikes, drops, or outliers.", {
16
+ (0, _register_js_1.registerTool)(server, "list_insights", "List anomaly insights detected by Centrali's AI analysis. Insights flag unusual patterns in your data such as spikes, drops, or outliers.", {
40
17
  recordSlug: zod_1.z
41
18
  .string()
42
19
  .optional()
@@ -65,12 +42,12 @@ function registerInsightTools(server, sdk) {
65
42
  }
66
43
  catch (error) {
67
44
  return {
68
- content: [{ type: "text", text: formatError(error, "listing insights") }],
45
+ content: [{ type: "text", text: (0, _register_js_1.formatError)(error, "listing insights") }],
69
46
  isError: true,
70
47
  };
71
48
  }
72
49
  }));
73
- server.tool("get_insight", "Get full details of a single anomaly insight by ID.", {
50
+ (0, _register_js_1.registerTool)(server, "get_insight", "Get full details of a single anomaly insight by ID.", {
74
51
  insightId: zod_1.z.string().describe("The insight ID (UUID)"),
75
52
  }, (_a) => __awaiter(this, [_a], void 0, function* ({ insightId }) {
76
53
  try {
@@ -82,13 +59,13 @@ function registerInsightTools(server, sdk) {
82
59
  catch (error) {
83
60
  return {
84
61
  content: [
85
- { type: "text", text: formatError(error, `getting insight '${insightId}'`) },
62
+ { type: "text", text: (0, _register_js_1.formatError)(error, `getting insight '${insightId}'`) },
86
63
  ],
87
64
  isError: true,
88
65
  };
89
66
  }
90
67
  }));
91
- server.tool("acknowledge_insight", "Mark an anomaly insight as acknowledged (reviewed/handled). The insight remains visible but is flagged as addressed.", {
68
+ (0, _register_js_1.registerTool)(server, "acknowledge_insight", "Mark an anomaly insight as acknowledged (reviewed/handled). The insight remains visible but is flagged as addressed.", {
92
69
  insightId: zod_1.z.string().describe("The insight ID (UUID) to acknowledge"),
93
70
  }, (_a) => __awaiter(this, [_a], void 0, function* ({ insightId }) {
94
71
  try {
@@ -102,14 +79,14 @@ function registerInsightTools(server, sdk) {
102
79
  content: [
103
80
  {
104
81
  type: "text",
105
- text: formatError(error, `acknowledging insight '${insightId}'`),
82
+ text: (0, _register_js_1.formatError)(error, `acknowledging insight '${insightId}'`),
106
83
  },
107
84
  ],
108
85
  isError: true,
109
86
  };
110
87
  }
111
88
  }));
112
- server.tool("dismiss_insight", "Dismiss an anomaly insight, marking it as a false positive or not relevant.", {
89
+ (0, _register_js_1.registerTool)(server, "dismiss_insight", "Dismiss an anomaly insight, marking it as a false positive or not relevant.", {
113
90
  insightId: zod_1.z.string().describe("The insight ID (UUID) to dismiss"),
114
91
  }, (_a) => __awaiter(this, [_a], void 0, function* ({ insightId }) {
115
92
  try {
@@ -121,13 +98,13 @@ function registerInsightTools(server, sdk) {
121
98
  catch (error) {
122
99
  return {
123
100
  content: [
124
- { type: "text", text: formatError(error, `dismissing insight '${insightId}'`) },
101
+ { type: "text", text: (0, _register_js_1.formatError)(error, `dismissing insight '${insightId}'`) },
125
102
  ],
126
103
  isError: true,
127
104
  };
128
105
  }
129
106
  }));
130
- server.tool("get_insights_summary", "Get a summary of anomaly insights in the workspace — counts by status and severity. Optionally filter by collection.", {
107
+ (0, _register_js_1.registerTool)(server, "get_insights_summary", "Get a summary of anomaly insights in the workspace — counts by status and severity. Optionally filter by collection.", {
131
108
  recordSlug: zod_1.z
132
109
  .string()
133
110
  .optional()
@@ -142,13 +119,13 @@ function registerInsightTools(server, sdk) {
142
119
  catch (error) {
143
120
  return {
144
121
  content: [
145
- { type: "text", text: formatError(error, "getting insights summary") },
122
+ { type: "text", text: (0, _register_js_1.formatError)(error, "getting insights summary") },
146
123
  ],
147
124
  isError: true,
148
125
  };
149
126
  }
150
127
  }));
151
- server.tool("trigger_anomaly_analysis", "Trigger AI-powered anomaly analysis for a collection. Starts a background analysis to detect unusual patterns. Check list_insights after the scan completes.", {
128
+ (0, _register_js_1.registerTool)(server, "trigger_anomaly_analysis", "Trigger AI-powered anomaly analysis for a collection. Starts a background analysis to detect unusual patterns. Check list_insights after the scan completes.", {
152
129
  recordSlug: zod_1.z.string().describe("The collection's record slug to analyze"),
153
130
  }, (_a) => __awaiter(this, [_a], void 0, function* ({ recordSlug }) {
154
131
  try {
@@ -162,7 +139,7 @@ function registerInsightTools(server, sdk) {
162
139
  content: [
163
140
  {
164
141
  type: "text",
165
- text: formatError(error, `triggering anomaly analysis for '${recordSlug}'`),
142
+ text: (0, _register_js_1.formatError)(error, `triggering anomaly analysis for '${recordSlug}'`),
166
143
  },
167
144
  ],
168
145
  isError: true,