@signaliz/sdk 1.0.3 → 1.0.4

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/index.js CHANGED
@@ -210,13 +210,14 @@ var HttpClient = class {
210
210
  details: { responseText: text.slice(0, 500) }
211
211
  });
212
212
  }
213
- if (data.error) {
213
+ const responseError = isRecord(data) && isRecord(data.error) ? data.error : null;
214
+ if (responseError) {
214
215
  const err = new SignalizError({
215
- code: data.error.code?.toString() || data.error.data?.error_code || "MCP_ERROR",
216
- message: data.error.message || "MCP request failed",
217
- errorType: mapMcpErrorType(data.error),
218
- retryAfter: data.error.data?.retry_after,
219
- details: data.error.data
216
+ code: firstString(responseError.code, isRecord(responseError.data) ? responseError.data.error_code : void 0) || "MCP_ERROR",
217
+ message: firstString(responseError.message) || "MCP request failed",
218
+ errorType: mapMcpErrorType(responseError),
219
+ retryAfter: isRecord(responseError.data) && typeof responseError.data.retry_after === "number" ? responseError.data.retry_after : void 0,
220
+ details: isRecord(responseError.data) ? responseError.data : void 0
220
221
  });
221
222
  if (err.isRetryable && attempt < this.maxRetries) {
222
223
  lastError = err;
@@ -293,35 +294,63 @@ function normalizeMcpParams(method, params) {
293
294
  }
294
295
  };
295
296
  }
297
+ function isRecord(value) {
298
+ return typeof value === "object" && value !== null;
299
+ }
300
+ function firstString(...values) {
301
+ const value = values.find((item) => typeof item === "string" && item.length > 0);
302
+ return typeof value === "string" ? value : void 0;
303
+ }
304
+ function firstPayloadError(payload) {
305
+ const errors = payload.errors;
306
+ const first = Array.isArray(errors) ? errors[0] : void 0;
307
+ return isRecord(first) ? first : {};
308
+ }
296
309
  function unwrapMcpResponse(data) {
297
- if (data?.result?.structuredContent !== void 0) {
298
- return unwrapMcpPayload(data.result.structuredContent);
310
+ const result = isRecord(data) ? data.result : void 0;
311
+ if (isRecord(result) && result.structuredContent !== void 0) {
312
+ return unwrapMcpPayload(result.structuredContent);
299
313
  }
300
- const text = data?.result?.content?.[0]?.text;
314
+ const content = isRecord(result) ? result.content : void 0;
315
+ const firstContent = Array.isArray(content) ? content[0] : void 0;
316
+ const text = isRecord(firstContent) ? firstContent.text : void 0;
301
317
  if (typeof text === "string") {
302
318
  const parsed = safeJson(text);
303
319
  return unwrapMcpPayload(parsed ?? text);
304
320
  }
305
- return unwrapMcpPayload(data?.result);
321
+ return unwrapMcpPayload(result);
306
322
  }
307
323
  function unwrapMcpPayload(payload) {
308
- if (payload && typeof payload === "object") {
324
+ if (isRecord(payload)) {
309
325
  if (payload.ok === true && Object.prototype.hasOwnProperty.call(payload, "result")) {
310
326
  return payload.result;
311
327
  }
328
+ if (payload.ok === false) {
329
+ const first = firstPayloadError(payload);
330
+ const code = firstString(first.code, payload.error_code, payload.code) || (payload.approval_required ? "APPROVAL_REQUIRED" : "MCP_ERROR");
331
+ throw new SignalizError({
332
+ code,
333
+ message: firstString(first.message, payload.message, payload.summary, payload.error) || "MCP request failed",
334
+ errorType: mapErrorTypeFromCode(code),
335
+ details: {
336
+ ...payload,
337
+ ...isRecord(first.details) ? first.details : {}
338
+ }
339
+ });
340
+ }
312
341
  if (payload.success === true && Object.prototype.hasOwnProperty.call(payload, "data")) {
313
342
  return payload.data;
314
343
  }
315
344
  if (payload.success === false) {
316
- const first = Array.isArray(payload.errors) ? payload.errors[0] ?? {} : {};
317
- const code = first.code || payload.error_code || (payload.approval_required ? "APPROVAL_REQUIRED" : "MCP_ERROR");
345
+ const first = firstPayloadError(payload);
346
+ const code = firstString(first.code, payload.error_code) || (payload.approval_required ? "APPROVAL_REQUIRED" : "MCP_ERROR");
318
347
  throw new SignalizError({
319
348
  code,
320
- message: first.message || payload.message || payload.summary || "MCP request failed",
349
+ message: firstString(first.message, payload.message, payload.summary) || "MCP request failed",
321
350
  errorType: mapErrorTypeFromCode(code),
322
351
  details: {
323
352
  ...payload,
324
- ...first.details && typeof first.details === "object" ? first.details : {}
353
+ ...isRecord(first.details) ? first.details : {}
325
354
  }
326
355
  });
327
356
  }
@@ -329,8 +358,10 @@ function unwrapMcpPayload(payload) {
329
358
  return payload;
330
359
  }
331
360
  function mapMcpErrorType(error) {
332
- const code = String(error?.data?.error_code || error?.code || "");
333
- const message = String(error?.message || "").toLowerCase();
361
+ const errorRecord = isRecord(error) ? error : {};
362
+ const data = isRecord(errorRecord.data) ? errorRecord.data : {};
363
+ const code = String(data.error_code || errorRecord.code || "");
364
+ const message = String(errorRecord.message || "").toLowerCase();
334
365
  if (code === "429" || message.includes("rate limit")) return "rate_limited";
335
366
  if (code === "401" || code === "AUTH_001" || message.includes("auth")) return "auth_expired";
336
367
  if (code === "400" || code === "-32602" || message.includes("invalid")) return "validation";
@@ -2961,6 +2992,10 @@ function normalizeOpsProofResult(data) {
2961
2992
  failed30d: numberValue(summary.failed_30d ?? summary.failed30d),
2962
2993
  external_delivered_30d: numberValue(summary.external_delivered_30d ?? summary.externalDelivered30d),
2963
2994
  externalDelivered30d: numberValue(summary.external_delivered_30d ?? summary.externalDelivered30d),
2995
+ nango_proofs_30d: numberValue(summary.nango_proofs_30d ?? summary.nangoProofs30d),
2996
+ nangoProofs30d: numberValue(summary.nango_proofs_30d ?? summary.nangoProofs30d),
2997
+ nango_failures_30d: numberValue(summary.nango_failures_30d ?? summary.nangoFailures30d),
2998
+ nangoFailures30d: numberValue(summary.nango_failures_30d ?? summary.nangoFailures30d),
2964
2999
  airbyte_configured: numberValue(summary.airbyte_configured ?? summary.airbyteConfigured),
2965
3000
  airbyteConfigured: numberValue(summary.airbyte_configured ?? summary.airbyteConfigured),
2966
3001
  airbyte_proofs_30d: numberValue(summary.airbyte_proofs_30d ?? summary.airbyteProofs30d),
@@ -3375,9 +3410,10 @@ function buildOpsDebugOptions(params) {
3375
3410
  }
3376
3411
  function buildCreateRoutineBody(params) {
3377
3412
  const { outputSinks, wakeOnEvents, ...rest } = params;
3413
+ const sinks = rest.output_sinks ?? outputSinks;
3378
3414
  return {
3379
3415
  ...rest,
3380
- output_sinks: rest.output_sinks ?? outputSinks,
3416
+ output_sinks: Array.isArray(sinks) ? sinks.map(normalizeOpsSinkRequest) : sinks,
3381
3417
  wake_on_events: rest.wake_on_events ?? wakeOnEvents
3382
3418
  };
3383
3419
  }
@@ -3411,6 +3447,97 @@ function buildCreateOutputSinkBody(params) {
3411
3447
  webhook_url: rest.webhook_url ?? webhookUrl
3412
3448
  };
3413
3449
  }
3450
+ function normalizeOpsSinkRequest(sink) {
3451
+ const {
3452
+ sinkId,
3453
+ connectionId,
3454
+ connectorId,
3455
+ connectorName,
3456
+ deliveryMode,
3457
+ providerConfigKey,
3458
+ integrationId,
3459
+ nangoConnectionId,
3460
+ actionName,
3461
+ nangoAction,
3462
+ proxyPath,
3463
+ nangoProxyPath,
3464
+ fieldMap,
3465
+ requiredFields,
3466
+ writeConfirmed,
3467
+ agentWriteConfirmed,
3468
+ config,
3469
+ ...rest
3470
+ } = sink;
3471
+ const normalizedConfig = normalizeOpsSinkConfigRequest(config);
3472
+ const connection_id = rest.connection_id ?? connectionId;
3473
+ const connector_id = rest.connector_id ?? connectorId;
3474
+ const delivery_mode = rest.delivery_mode ?? deliveryMode;
3475
+ const provider_config_key = rest.provider_config_key ?? providerConfigKey;
3476
+ const integration_id = rest.integration_id ?? integrationId;
3477
+ const nango_connection_id = rest.nango_connection_id ?? nangoConnectionId;
3478
+ const action_name = rest.action_name ?? actionName;
3479
+ const nango_action = rest.nango_action ?? nangoAction;
3480
+ const proxy_path = rest.proxy_path ?? proxyPath;
3481
+ const nango_proxy_path = rest.nango_proxy_path ?? nangoProxyPath;
3482
+ const field_map = rest.field_map ?? fieldMap;
3483
+ const required_fields = rest.required_fields ?? requiredFields;
3484
+ const write_confirmed = rest.write_confirmed ?? writeConfirmed;
3485
+ const agent_write_confirmed = rest.agent_write_confirmed ?? agentWriteConfirmed;
3486
+ if (connection_id !== void 0 && normalizedConfig.connection_id === void 0) normalizedConfig.connection_id = connection_id;
3487
+ if (connector_id !== void 0 && normalizedConfig.connector_id === void 0) normalizedConfig.connector_id = connector_id;
3488
+ if (delivery_mode !== void 0 && normalizedConfig.delivery_mode === void 0) normalizedConfig.delivery_mode = delivery_mode;
3489
+ if (provider_config_key !== void 0 && normalizedConfig.provider_config_key === void 0) normalizedConfig.provider_config_key = provider_config_key;
3490
+ if (integration_id !== void 0 && normalizedConfig.integration_id === void 0) normalizedConfig.integration_id = integration_id;
3491
+ if (nango_connection_id !== void 0 && normalizedConfig.nango_connection_id === void 0) normalizedConfig.nango_connection_id = nango_connection_id;
3492
+ if (action_name !== void 0 && normalizedConfig.action_name === void 0) normalizedConfig.action_name = action_name;
3493
+ if (nango_action !== void 0 && normalizedConfig.nango_action === void 0) normalizedConfig.nango_action = nango_action;
3494
+ if (proxy_path !== void 0 && normalizedConfig.proxy_path === void 0) normalizedConfig.proxy_path = proxy_path;
3495
+ if (nango_proxy_path !== void 0 && normalizedConfig.nango_proxy_path === void 0) normalizedConfig.nango_proxy_path = nango_proxy_path;
3496
+ if (field_map !== void 0 && normalizedConfig.field_map === void 0) normalizedConfig.field_map = field_map;
3497
+ if (required_fields !== void 0 && normalizedConfig.required_fields === void 0) normalizedConfig.required_fields = required_fields;
3498
+ if (write_confirmed !== void 0 && normalizedConfig.write_confirmed === void 0) normalizedConfig.write_confirmed = write_confirmed;
3499
+ if (agent_write_confirmed !== void 0 && normalizedConfig.agent_write_confirmed === void 0) normalizedConfig.agent_write_confirmed = agent_write_confirmed;
3500
+ if (sink.type === "nango" && normalizedConfig.integration_platform === void 0) normalizedConfig.integration_platform = "nango";
3501
+ return {
3502
+ ...rest,
3503
+ sink_id: rest.sink_id ?? sinkId,
3504
+ connection_id,
3505
+ connector_id,
3506
+ connector_name: rest.connector_name ?? connectorName,
3507
+ delivery_mode,
3508
+ provider_config_key,
3509
+ integration_id,
3510
+ nango_connection_id,
3511
+ action_name,
3512
+ nango_action,
3513
+ proxy_path,
3514
+ nango_proxy_path,
3515
+ field_map,
3516
+ required_fields,
3517
+ write_confirmed,
3518
+ agent_write_confirmed,
3519
+ config: normalizedConfig
3520
+ };
3521
+ }
3522
+ function normalizeOpsSinkConfigRequest(config) {
3523
+ const out = { ...config ?? {} };
3524
+ if (out.connection_id === void 0 && out.connectionId !== void 0) out.connection_id = out.connectionId;
3525
+ if (out.connector_id === void 0 && out.connectorId !== void 0) out.connector_id = out.connectorId;
3526
+ if (out.connector_name === void 0 && out.connectorName !== void 0) out.connector_name = out.connectorName;
3527
+ if (out.delivery_mode === void 0 && out.deliveryMode !== void 0) out.delivery_mode = out.deliveryMode;
3528
+ if (out.provider_config_key === void 0 && out.providerConfigKey !== void 0) out.provider_config_key = out.providerConfigKey;
3529
+ if (out.integration_id === void 0 && out.integrationId !== void 0) out.integration_id = out.integrationId;
3530
+ if (out.nango_connection_id === void 0 && out.nangoConnectionId !== void 0) out.nango_connection_id = out.nangoConnectionId;
3531
+ if (out.action_name === void 0 && out.actionName !== void 0) out.action_name = out.actionName;
3532
+ if (out.nango_action === void 0 && out.nangoAction !== void 0) out.nango_action = out.nangoAction;
3533
+ if (out.proxy_path === void 0 && out.proxyPath !== void 0) out.proxy_path = out.proxyPath;
3534
+ if (out.nango_proxy_path === void 0 && out.nangoProxyPath !== void 0) out.nango_proxy_path = out.nangoProxyPath;
3535
+ if (out.field_map === void 0 && out.fieldMap !== void 0) out.field_map = out.fieldMap;
3536
+ if (out.required_fields === void 0 && out.requiredFields !== void 0) out.required_fields = out.requiredFields;
3537
+ if (out.write_confirmed === void 0 && out.writeConfirmed !== void 0) out.write_confirmed = out.writeConfirmed;
3538
+ if (out.agent_write_confirmed === void 0 && out.agentWriteConfirmed !== void 0) out.agent_write_confirmed = out.agentWriteConfirmed;
3539
+ return out;
3540
+ }
3414
3541
  function buildApproveBody(params) {
3415
3542
  const { tokenId, tokenIds, reviewerNotes, ...rest } = params;
3416
3543
  return {
@@ -3559,6 +3686,57 @@ var GtmKernel = class {
3559
3686
  limit: options.limit
3560
3687
  });
3561
3688
  }
3689
+ /** Discover existing provider campaigns, starting with live/Kernel-linked Instantly campaigns, before audit or import preview. */
3690
+ async discoverExistingCampaigns(options = {}) {
3691
+ return this.callMcp("gtm_existing_campaign_discover", {
3692
+ provider: options.provider,
3693
+ integration_id: options.integrationId,
3694
+ search: options.search,
3695
+ limit: options.limit,
3696
+ include_kernel_linked: options.includeKernelLinked,
3697
+ include_provider_live: options.includeProviderLive
3698
+ });
3699
+ }
3700
+ /** Run a read-only existing campaign audit with completeness, recommendations, safe next MCP JSON, and approval boundaries. */
3701
+ async auditExistingCampaign(options) {
3702
+ return this.callMcp("gtm_existing_campaign_audit", {
3703
+ campaign_id: options.campaignId,
3704
+ provider: options.provider,
3705
+ provider_campaign_id: options.providerCampaignId,
3706
+ campaign_name: options.campaignName,
3707
+ days: options.days,
3708
+ include_route_preview: options.includeRoutePreview,
3709
+ include_memory: options.includeMemory,
3710
+ include_brain: options.includeBrain
3711
+ });
3712
+ }
3713
+ /** Discover the first matching existing provider campaign, then run the same read-only audit against that match. */
3714
+ async auditExistingCampaignBySearch(options) {
3715
+ const discovery = await this.discoverExistingCampaigns({
3716
+ provider: options.provider,
3717
+ integrationId: options.integrationId,
3718
+ search: options.search,
3719
+ limit: 1,
3720
+ includeKernelLinked: options.includeKernelLinked,
3721
+ includeProviderLive: options.includeProviderLive
3722
+ });
3723
+ const match = discovery.campaigns?.[0];
3724
+ const campaignId = match?.linked_kernel_campaign_id || void 0;
3725
+ const providerCampaignId = match?.provider_campaign_id || void 0;
3726
+ if (!campaignId && !providerCampaignId) {
3727
+ throw new Error(`No existing ${options.provider || discovery.provider || "provider"} campaign matched "${options.search}"`);
3728
+ }
3729
+ return this.auditExistingCampaign({
3730
+ provider: options.provider || discovery.provider || match?.provider,
3731
+ campaignId,
3732
+ providerCampaignId,
3733
+ campaignName: match?.name || match?.linked_kernel_campaign_name || void 0,
3734
+ days: options.days,
3735
+ includeRoutePreview: options.includeRoutePreview,
3736
+ includeMemory: options.includeMemory,
3737
+ includeBrain: options.includeBrain
3738
+ });
3739
+ }
3562
3740
  /** Create a first-class GTM campaign object in the current workspace. */
3563
3741
  async createCampaign(input) {
3564
3742
  return this.callMcp("gtm_campaign_create", campaignCreateArgs(input));
@@ -3764,6 +3942,47 @@ var GtmKernel = class {
3764
3942
  brain_cycle_min_interval_minutes: input.brainCycleMinIntervalMinutes
3765
3943
  });
3766
3944
  }
3945
+ /** Preview anonymized Instantly workspace sources registered for Kernel import. */
3946
+ async previewKernelImport(input = {}) {
3947
+ return this.callMcp("gtm_kernel_import_preview", {
3948
+ source_ids: input.sourceIds,
3949
+ include_leads: input.includeLeads,
3950
+ include_replies: input.includeReplies,
3951
+ include_private_copy: input.includePrivateCopy,
3952
+ max_pages: input.maxPages,
3953
+ limit: input.limit
3954
+ });
3955
+ }
3956
+ /** Queue the read-only Instantly-to-GTM Kernel import. Live writes require writeApproved. */
3957
+ async runKernelImport(input = {}) {
3958
+ return this.callMcp("gtm_kernel_import_run", {
3959
+ source_ids: input.sourceIds,
3960
+ dry_run: input.dryRun,
3961
+ write_approved: input.writeApproved,
3962
+ include_leads: input.includeLeads,
3963
+ include_replies: input.includeReplies,
3964
+ include_private_copy: input.includePrivateCopy,
3965
+ private_copy_approved: input.privateCopyApproved,
3966
+ promote_global_patterns: input.promoteGlobalPatterns,
3967
+ min_global_privacy_k: input.minGlobalPrivacyK,
3968
+ max_pages: input.maxPages,
3969
+ limit: input.limit
3970
+ });
3971
+ }
3972
+ /** Queue Brain distillation over imported Instantly memory with abstracted-only outputs. */
3973
+ async runBrainDistillation(input = {}) {
3974
+ return this.callMcp("gtm_brain_distill_run", {
3975
+ source_ids: input.sourceIds,
3976
+ write_mode: input.writeMode,
3977
+ write_approved: input.writeApproved,
3978
+ brain_cycle_phases: input.brainCyclePhases,
3979
+ days: input.days,
3980
+ network_days: input.networkDays,
3981
+ min_sample_size: input.minSampleSize,
3982
+ min_workspace_count: input.minWorkspaceCount,
3983
+ min_privacy_k: input.minPrivacyK
3984
+ });
3985
+ }
3767
3986
  /** Prepare a provider-agnostic feedback webhook URL for Smartlead, HeyReach, Airbyte, or custom sender events. */
3768
3987
  async prepareFeedbackWebhook(input) {
3769
3988
  return this.callMcp("gtm_feedback_webhook_prepare", {
@@ -4191,6 +4410,43 @@ var GtmKernel = class {
4191
4410
  context: input.context
4192
4411
  });
4193
4412
  }
4413
+ /** List Nango-backed action tools for a workspace connection without executing them. */
4414
+ async listNangoTools(options = {}) {
4415
+ return this.callMcp("nango_mcp_tools_list", {
4416
+ workspace_connection_id: options.workspaceConnectionId,
4417
+ connection_id: options.connectionId,
4418
+ provider_config_key: options.providerConfigKey,
4419
+ integration_id: options.integrationId,
4420
+ nango_connection_id: options.nangoConnectionId,
4421
+ format: options.format,
4422
+ include_raw: options.includeRaw
4423
+ });
4424
+ }
4425
+ /** Dry-run or execute a Nango-backed action tool through the approval-aware MCP bridge. */
4426
+ async callNangoTool(input) {
4427
+ return this.callMcp("nango_mcp_tool_call", {
4428
+ workspace_connection_id: input.workspaceConnectionId,
4429
+ connection_id: input.connectionId,
4430
+ provider_config_key: input.providerConfigKey,
4431
+ integration_id: input.integrationId,
4432
+ nango_connection_id: input.nangoConnectionId,
4433
+ action_name: input.actionName,
4434
+ tool_name: input.toolName,
4435
+ input: input.input,
4436
+ async: input.async,
4437
+ max_retries: input.maxRetries,
4438
+ dry_run: input.dryRun,
4439
+ confirm: input.confirm,
4440
+ confirm_write: input.confirmWrite
4441
+ });
4442
+ }
4443
+ /** Poll an async Nango action result by action id or status URL. */
4444
+ async getNangoActionResult(input) {
4445
+ return this.callMcp("nango_mcp_action_result_get", {
4446
+ action_id: input.actionId,
4447
+ status_url: input.statusUrl
4448
+ });
4449
+ }
4194
4450
  /** Deliver approved campaign-layer records to a webhook recipe, starting with Clay-style webhooks. */
4195
4451
  async deliverWebhook(input) {
4196
4452
  return this.callMcp("gtm_webhook_deliver", {
@@ -4325,6 +4581,59 @@ function compact2(value) {
4325
4581
  }
4326
4582
 
4327
4583
  // src/index.ts
4584
+ function inferMcpToolCategory(toolName) {
4585
+ if (typeof toolName !== "string" || !toolName) return void 0;
4586
+ if (toolName.startsWith("ops_") || toolName === "get_ops_readiness" || toolName === "get_gtm_ops_readiness" || toolName.startsWith("gtm_") || [
4587
+ "list_routines",
4588
+ "create_routine",
4589
+ "update_routine",
4590
+ "run_routine_now",
4591
+ "get_routine",
4592
+ "get_routine_ticks",
4593
+ "get_tick_items",
4594
+ "get_last_tick_items",
4595
+ "chain_routines",
4596
+ "get_chain_status",
4597
+ "launch_campaign",
4598
+ "quickstart_gtm_book",
4599
+ "list_campaigns",
4600
+ "campaign_performance",
4601
+ "tune_campaign",
4602
+ "emit_event",
4603
+ "approvals_list",
4604
+ "list_output_sinks",
4605
+ "create_output_sink",
4606
+ "update_output_sink",
4607
+ "delete_output_sink",
4608
+ "attach_sink_to_routine"
4609
+ ].includes(toolName)) {
4610
+ return "ops";
4611
+ }
4612
+ if ([
4613
+ "find_emails_with_verification",
4614
+ "verify_email",
4615
+ "enrich_company_signals",
4616
+ "company_intelligence",
4617
+ "find_contacts_with_email",
4618
+ "execute_primitive"
4619
+ ].includes(toolName)) {
4620
+ return "enrichment";
4621
+ }
4622
+ if (toolName.includes("icp")) return "icp";
4623
+ if (toolName.startsWith("ai_clean_")) return "data_cleaning";
4624
+ if (toolName.includes("system") || toolName.includes("workflow")) return "automation";
4625
+ if (toolName.includes("agent") || toolName.includes("platform_health") || toolName === "discover_capabilities") return "observability";
4626
+ return void 0;
4627
+ }
4628
+ function asRecord3(value) {
4629
+ return value && typeof value === "object" ? value : void 0;
4630
+ }
4631
+ function asStringArray(value) {
4632
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : void 0;
4633
+ }
4634
+ function asObjectSchema(value) {
4635
+ return asRecord3(value);
4636
+ }
4328
4637
  var Signaliz = class {
4329
4638
  constructor(config) {
4330
4639
  this.client = new HttpClient(config);
@@ -4383,21 +4692,21 @@ var Signaliz = class {
4383
4692
  const data = await this.client.mcp("tools/list", {});
4384
4693
  const tools = data?.tools ?? data ?? [];
4385
4694
  return tools.map((t) => ({
4386
- name: t.name,
4387
- description: (t.description ?? "").slice(0, 120),
4388
- category: t.annotations?.category,
4389
- costCredits: t.annotations?.cost_credits,
4390
- contractVersion: t.annotations?.contract_version ?? t.annotations?.contract?.contract_version,
4391
- permissionLevel: t.annotations?.permission_level ?? t.annotations?.contract?.permission_level,
4392
- authScopes: t.annotations?.auth_scopes ?? t.annotations?.contract?.auth_scopes,
4393
- idempotent: t.annotations?.idempotentHint ?? t.annotations?.idempotent ?? t.annotations?.contract?.idempotent,
4394
- destructive: t.annotations?.destructiveHint ?? t.annotations?.destructive ?? t.annotations?.contract?.destructive,
4395
- retryable: t.annotations?.retryable ?? t.annotations?.contract?.retryable,
4396
- rateLimitKey: t.annotations?.rate_limit_key ?? t.annotations?.contract?.rate_limit_key,
4397
- observability: t.annotations?.observability ?? t.annotations?.contract?.observability,
4398
- inputSchema: t.inputSchema ?? t.input_schema ?? t.annotations?.contract?.input_schema,
4399
- outputSchema: t.outputSchema ?? t.output_schema ?? t.annotations?.contract?.output_schema,
4400
- annotations: t.annotations
4695
+ name: typeof t.name === "string" ? t.name : "",
4696
+ description: String(t.description ?? "").slice(0, 120),
4697
+ category: typeof t.annotations?.category === "string" ? t.annotations.category : inferMcpToolCategory(t.name),
4698
+ costCredits: typeof t.annotations?.cost_credits === "number" ? t.annotations.cost_credits : void 0,
4699
+ contractVersion: typeof (t.annotations?.contract_version ?? t.annotations?.contract?.contract_version) === "string" ? t.annotations?.contract_version ?? t.annotations?.contract?.contract_version : void 0,
4700
+ permissionLevel: typeof (t.annotations?.permission_level ?? t.annotations?.contract?.permission_level) === "string" ? t.annotations?.permission_level ?? t.annotations?.contract?.permission_level : void 0,
4701
+ authScopes: asStringArray(t.annotations?.auth_scopes ?? t.annotations?.contract?.auth_scopes),
4702
+ idempotent: typeof (t.annotations?.idempotentHint ?? t.annotations?.idempotent ?? t.annotations?.contract?.idempotent) === "boolean" ? t.annotations?.idempotentHint ?? t.annotations?.idempotent ?? t.annotations?.contract?.idempotent : void 0,
4703
+ destructive: typeof (t.annotations?.destructiveHint ?? t.annotations?.destructive ?? t.annotations?.contract?.destructive) === "boolean" ? t.annotations?.destructiveHint ?? t.annotations?.destructive ?? t.annotations?.contract?.destructive : void 0,
4704
+ retryable: typeof (t.annotations?.retryable ?? t.annotations?.contract?.retryable) === "boolean" ? t.annotations?.retryable ?? t.annotations?.contract?.retryable : void 0,
4705
+ rateLimitKey: typeof (t.annotations?.rate_limit_key ?? t.annotations?.contract?.rate_limit_key) === "string" ? t.annotations?.rate_limit_key ?? t.annotations?.contract?.rate_limit_key : void 0,
4706
+ observability: asRecord3(t.annotations?.observability ?? t.annotations?.contract?.observability),
4707
+ inputSchema: asObjectSchema(t.inputSchema ?? t.input_schema ?? t.annotations?.contract?.input_schema),
4708
+ outputSchema: asObjectSchema(t.outputSchema ?? t.output_schema ?? t.annotations?.contract?.output_schema),
4709
+ annotations: asRecord3(t.annotations)
4401
4710
  }));
4402
4711
  }
4403
4712
  /** Discover tools by natural language query */
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ import {
13
13
  createCampaignBuilderApproval,
14
14
  getMissingCampaignBuilderApprovals,
15
15
  normalizeExecutionReference
16
- } from "./chunk-L6XUFJJO.mjs";
16
+ } from "./chunk-EVZZQTWE.mjs";
17
17
  export {
18
18
  Ai,
19
19
  CampaignBuilderAgent,