@signaliz/sdk 1.0.3 → 1.0.5

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/cli.js CHANGED
@@ -174,13 +174,14 @@ var HttpClient = class {
174
174
  details: { responseText: text.slice(0, 500) }
175
175
  });
176
176
  }
177
- if (data.error) {
177
+ const responseError = isRecord(data) && isRecord(data.error) ? data.error : null;
178
+ if (responseError) {
178
179
  const err = new SignalizError({
179
- code: data.error.code?.toString() || data.error.data?.error_code || "MCP_ERROR",
180
- message: data.error.message || "MCP request failed",
181
- errorType: mapMcpErrorType(data.error),
182
- retryAfter: data.error.data?.retry_after,
183
- details: data.error.data
180
+ code: firstString(responseError.code, isRecord(responseError.data) ? responseError.data.error_code : void 0) || "MCP_ERROR",
181
+ message: firstString(responseError.message) || "MCP request failed",
182
+ errorType: mapMcpErrorType(responseError),
183
+ retryAfter: isRecord(responseError.data) && typeof responseError.data.retry_after === "number" ? responseError.data.retry_after : void 0,
184
+ details: isRecord(responseError.data) ? responseError.data : void 0
184
185
  });
185
186
  if (err.isRetryable && attempt < this.maxRetries) {
186
187
  lastError = err;
@@ -257,35 +258,63 @@ function normalizeMcpParams(method, params) {
257
258
  }
258
259
  };
259
260
  }
261
+ function isRecord(value) {
262
+ return typeof value === "object" && value !== null;
263
+ }
264
+ function firstString(...values) {
265
+ const value = values.find((item) => typeof item === "string" && item.length > 0);
266
+ return typeof value === "string" ? value : void 0;
267
+ }
268
+ function firstPayloadError(payload) {
269
+ const errors = payload.errors;
270
+ const first = Array.isArray(errors) ? errors[0] : void 0;
271
+ return isRecord(first) ? first : {};
272
+ }
260
273
  function unwrapMcpResponse(data) {
261
- if (data?.result?.structuredContent !== void 0) {
262
- return unwrapMcpPayload(data.result.structuredContent);
274
+ const result = isRecord(data) ? data.result : void 0;
275
+ if (isRecord(result) && result.structuredContent !== void 0) {
276
+ return unwrapMcpPayload(result.structuredContent);
263
277
  }
264
- const text = data?.result?.content?.[0]?.text;
278
+ const content = isRecord(result) ? result.content : void 0;
279
+ const firstContent = Array.isArray(content) ? content[0] : void 0;
280
+ const text = isRecord(firstContent) ? firstContent.text : void 0;
265
281
  if (typeof text === "string") {
266
282
  const parsed = safeJson(text);
267
283
  return unwrapMcpPayload(parsed ?? text);
268
284
  }
269
- return unwrapMcpPayload(data?.result);
285
+ return unwrapMcpPayload(result);
270
286
  }
271
287
  function unwrapMcpPayload(payload) {
272
- if (payload && typeof payload === "object") {
288
+ if (isRecord(payload)) {
273
289
  if (payload.ok === true && Object.prototype.hasOwnProperty.call(payload, "result")) {
274
- return payload.result;
290
+ return unwrapMcpPayload(payload.result);
291
+ }
292
+ if (payload.ok === false) {
293
+ const first = firstPayloadError(payload);
294
+ const code = firstString(first.code, payload.error_code, payload.code) || (payload.approval_required ? "APPROVAL_REQUIRED" : "MCP_ERROR");
295
+ throw new SignalizError({
296
+ code,
297
+ message: firstString(first.message, payload.message, payload.summary, payload.error) || "MCP request failed",
298
+ errorType: mapErrorTypeFromCode(code),
299
+ details: {
300
+ ...payload,
301
+ ...isRecord(first.details) ? first.details : {}
302
+ }
303
+ });
275
304
  }
276
305
  if (payload.success === true && Object.prototype.hasOwnProperty.call(payload, "data")) {
277
306
  return payload.data;
278
307
  }
279
308
  if (payload.success === false) {
280
- const first = Array.isArray(payload.errors) ? payload.errors[0] ?? {} : {};
281
- const code = first.code || payload.error_code || (payload.approval_required ? "APPROVAL_REQUIRED" : "MCP_ERROR");
309
+ const first = firstPayloadError(payload);
310
+ const code = firstString(first.code, payload.error_code) || (payload.approval_required ? "APPROVAL_REQUIRED" : "MCP_ERROR");
282
311
  throw new SignalizError({
283
312
  code,
284
- message: first.message || payload.message || payload.summary || "MCP request failed",
313
+ message: firstString(first.message, payload.message, payload.summary) || "MCP request failed",
285
314
  errorType: mapErrorTypeFromCode(code),
286
315
  details: {
287
316
  ...payload,
288
- ...first.details && typeof first.details === "object" ? first.details : {}
317
+ ...isRecord(first.details) ? first.details : {}
289
318
  }
290
319
  });
291
320
  }
@@ -293,8 +322,10 @@ function unwrapMcpPayload(payload) {
293
322
  return payload;
294
323
  }
295
324
  function mapMcpErrorType(error) {
296
- const code = String(error?.data?.error_code || error?.code || "");
297
- const message = String(error?.message || "").toLowerCase();
325
+ const errorRecord = isRecord(error) ? error : {};
326
+ const data = isRecord(errorRecord.data) ? errorRecord.data : {};
327
+ const code = String(data.error_code || errorRecord.code || "");
328
+ const message = String(errorRecord.message || "").toLowerCase();
298
329
  if (code === "429" || message.includes("rate limit")) return "rate_limited";
299
330
  if (code === "401" || code === "AUTH_001" || message.includes("auth")) return "auth_expired";
300
331
  if (code === "400" || code === "-32602" || message.includes("invalid")) return "validation";
@@ -777,15 +808,17 @@ var Campaigns = class {
777
808
  args.idempotency_key = options.idempotencyKey;
778
809
  }
779
810
  const data = await this.callMcp("build_campaign", args);
811
+ const isDryRun = request.dryRun === true || data.dry_run === true || data.status === "dry_run";
812
+ const message = data.message ?? data.summary ?? (isDryRun && data.planned_target_count !== void 0 && data.estimated_credits !== void 0 && data.estimated_duration_seconds !== void 0 ? `Dry-run plan: ${data.planned_target_count} fresh leads. ~${data.estimated_credits} credits, ~${data.estimated_duration_seconds}s.` : "");
780
813
  return {
781
814
  campaignBuildId: data.campaign_build_id ?? null,
782
815
  campaignId: data.campaign_id ?? null,
783
816
  campaignObject: data.campaign_object ?? null,
784
- status: data.dry_run ? "dry_run" : data.status ?? "queued",
785
- currentPhase: data.dry_run ? "plan" : data.current_phase ?? "acquisition",
817
+ status: isDryRun ? "dry_run" : data.status ?? "queued",
818
+ currentPhase: isDryRun ? "plan" : data.current_phase ?? "acquisition",
786
819
  nextPollAfterSeconds: data.next_poll_after_seconds ?? 10,
787
- message: data.message ?? data.summary ?? "",
788
- dryRun: data.dry_run === true,
820
+ message,
821
+ dryRun: isDryRun,
789
822
  requestedTargetCount: data.requested_target_count,
790
823
  plannedTargetCount: data.planned_target_count,
791
824
  estimatedCredits: data.estimated_credits,
@@ -899,8 +932,8 @@ function mapStatus(data) {
899
932
  recordsProcessed: data.records_processed ?? 0,
900
933
  recordsSucceeded: data.records_succeeded ?? 0,
901
934
  recordsFailed: data.records_failed ?? 0,
902
- warnings: data.warnings ?? [],
903
- errors: data.errors ?? [],
935
+ warnings: diagnosticMessages(data.warnings),
936
+ errors: diagnosticMessages(data.errors),
904
937
  artifactCount: data.artifact_count ?? 0,
905
938
  providerRoute: mapProviderRoute(data),
906
939
  nextAction: data.next_action ?? "",
@@ -935,6 +968,14 @@ function recordOrNull(value) {
935
968
  function stringArray(value) {
936
969
  return Array.isArray(value) ? value.map((item) => String(item || "").trim()).filter(Boolean) : [];
937
970
  }
971
+ function diagnosticMessages(value) {
972
+ if (!Array.isArray(value)) return [];
973
+ return value.map((item) => {
974
+ if (typeof item === "string") return item;
975
+ const record = recordOrNull(item);
976
+ return typeof record?.message === "string" ? record.message : null;
977
+ }).filter((item) => typeof item === "string" && item.length > 0);
978
+ }
938
979
  function booleanOrNull(value) {
939
980
  return typeof value === "boolean" ? value : null;
940
981
  }
@@ -2255,22 +2296,22 @@ function queryFieldFor(kind) {
2255
2296
  function statusCommandFor(kind, id) {
2256
2297
  switch (kind) {
2257
2298
  case "op":
2258
- return `signaliz status ${id}`;
2299
+ return `signaliz ops status ${id}`;
2259
2300
  case "trigger_run":
2260
2301
  case "dataplane_run":
2261
2302
  case "replay_run":
2262
- return `signaliz watch ${id}`;
2303
+ return `signaliz ops run-status ${id} --watch`;
2263
2304
  case "queue_job":
2264
- return `signaliz queue --job-id ${id}`;
2305
+ return `signaliz ops queue --job-id ${id}`;
2265
2306
  case "routine":
2266
- return `signaliz routine ${id}`;
2307
+ return `signaliz ops routine ${id}`;
2267
2308
  default:
2268
2309
  return void 0;
2269
2310
  }
2270
2311
  }
2271
2312
  function replayCommandFor(kind, id) {
2272
2313
  if (kind !== "execution_event") return void 0;
2273
- return `signaliz replay ${id}`;
2314
+ return `signaliz ops replay ${id}`;
2274
2315
  }
2275
2316
 
2276
2317
  // src/resources/ops.ts
@@ -2918,6 +2959,10 @@ function normalizeOpsProofResult(data) {
2918
2959
  failed30d: numberValue(summary.failed_30d ?? summary.failed30d),
2919
2960
  external_delivered_30d: numberValue(summary.external_delivered_30d ?? summary.externalDelivered30d),
2920
2961
  externalDelivered30d: numberValue(summary.external_delivered_30d ?? summary.externalDelivered30d),
2962
+ nango_proofs_30d: numberValue(summary.nango_proofs_30d ?? summary.nangoProofs30d),
2963
+ nangoProofs30d: numberValue(summary.nango_proofs_30d ?? summary.nangoProofs30d),
2964
+ nango_failures_30d: numberValue(summary.nango_failures_30d ?? summary.nangoFailures30d),
2965
+ nangoFailures30d: numberValue(summary.nango_failures_30d ?? summary.nangoFailures30d),
2921
2966
  airbyte_configured: numberValue(summary.airbyte_configured ?? summary.airbyteConfigured),
2922
2967
  airbyteConfigured: numberValue(summary.airbyte_configured ?? summary.airbyteConfigured),
2923
2968
  airbyte_proofs_30d: numberValue(summary.airbyte_proofs_30d ?? summary.airbyteProofs30d),
@@ -3332,9 +3377,10 @@ function buildOpsDebugOptions(params) {
3332
3377
  }
3333
3378
  function buildCreateRoutineBody(params) {
3334
3379
  const { outputSinks, wakeOnEvents, ...rest } = params;
3380
+ const sinks = rest.output_sinks ?? outputSinks;
3335
3381
  return {
3336
3382
  ...rest,
3337
- output_sinks: rest.output_sinks ?? outputSinks,
3383
+ output_sinks: Array.isArray(sinks) ? sinks.map(normalizeOpsSinkRequest) : sinks,
3338
3384
  wake_on_events: rest.wake_on_events ?? wakeOnEvents
3339
3385
  };
3340
3386
  }
@@ -3368,6 +3414,97 @@ function buildCreateOutputSinkBody(params) {
3368
3414
  webhook_url: rest.webhook_url ?? webhookUrl
3369
3415
  };
3370
3416
  }
3417
+ function normalizeOpsSinkRequest(sink) {
3418
+ const {
3419
+ sinkId,
3420
+ connectionId,
3421
+ connectorId,
3422
+ connectorName,
3423
+ deliveryMode,
3424
+ providerConfigKey,
3425
+ integrationId,
3426
+ nangoConnectionId,
3427
+ actionName,
3428
+ nangoAction,
3429
+ proxyPath,
3430
+ nangoProxyPath,
3431
+ fieldMap,
3432
+ requiredFields,
3433
+ writeConfirmed,
3434
+ agentWriteConfirmed,
3435
+ config,
3436
+ ...rest
3437
+ } = sink;
3438
+ const normalizedConfig = normalizeOpsSinkConfigRequest(config);
3439
+ const connection_id = rest.connection_id ?? connectionId;
3440
+ const connector_id = rest.connector_id ?? connectorId;
3441
+ const delivery_mode = rest.delivery_mode ?? deliveryMode;
3442
+ const provider_config_key = rest.provider_config_key ?? providerConfigKey;
3443
+ const integration_id = rest.integration_id ?? integrationId;
3444
+ const nango_connection_id = rest.nango_connection_id ?? nangoConnectionId;
3445
+ const action_name = rest.action_name ?? actionName;
3446
+ const nango_action = rest.nango_action ?? nangoAction;
3447
+ const proxy_path = rest.proxy_path ?? proxyPath;
3448
+ const nango_proxy_path = rest.nango_proxy_path ?? nangoProxyPath;
3449
+ const field_map = rest.field_map ?? fieldMap;
3450
+ const required_fields = rest.required_fields ?? requiredFields;
3451
+ const write_confirmed = rest.write_confirmed ?? writeConfirmed;
3452
+ const agent_write_confirmed = rest.agent_write_confirmed ?? agentWriteConfirmed;
3453
+ if (connection_id !== void 0 && normalizedConfig.connection_id === void 0) normalizedConfig.connection_id = connection_id;
3454
+ if (connector_id !== void 0 && normalizedConfig.connector_id === void 0) normalizedConfig.connector_id = connector_id;
3455
+ if (delivery_mode !== void 0 && normalizedConfig.delivery_mode === void 0) normalizedConfig.delivery_mode = delivery_mode;
3456
+ if (provider_config_key !== void 0 && normalizedConfig.provider_config_key === void 0) normalizedConfig.provider_config_key = provider_config_key;
3457
+ if (integration_id !== void 0 && normalizedConfig.integration_id === void 0) normalizedConfig.integration_id = integration_id;
3458
+ if (nango_connection_id !== void 0 && normalizedConfig.nango_connection_id === void 0) normalizedConfig.nango_connection_id = nango_connection_id;
3459
+ if (action_name !== void 0 && normalizedConfig.action_name === void 0) normalizedConfig.action_name = action_name;
3460
+ if (nango_action !== void 0 && normalizedConfig.nango_action === void 0) normalizedConfig.nango_action = nango_action;
3461
+ if (proxy_path !== void 0 && normalizedConfig.proxy_path === void 0) normalizedConfig.proxy_path = proxy_path;
3462
+ if (nango_proxy_path !== void 0 && normalizedConfig.nango_proxy_path === void 0) normalizedConfig.nango_proxy_path = nango_proxy_path;
3463
+ if (field_map !== void 0 && normalizedConfig.field_map === void 0) normalizedConfig.field_map = field_map;
3464
+ if (required_fields !== void 0 && normalizedConfig.required_fields === void 0) normalizedConfig.required_fields = required_fields;
3465
+ if (write_confirmed !== void 0 && normalizedConfig.write_confirmed === void 0) normalizedConfig.write_confirmed = write_confirmed;
3466
+ if (agent_write_confirmed !== void 0 && normalizedConfig.agent_write_confirmed === void 0) normalizedConfig.agent_write_confirmed = agent_write_confirmed;
3467
+ if (sink.type === "nango" && normalizedConfig.integration_platform === void 0) normalizedConfig.integration_platform = "nango";
3468
+ return {
3469
+ ...rest,
3470
+ sink_id: rest.sink_id ?? sinkId,
3471
+ connection_id,
3472
+ connector_id,
3473
+ connector_name: rest.connector_name ?? connectorName,
3474
+ delivery_mode,
3475
+ provider_config_key,
3476
+ integration_id,
3477
+ nango_connection_id,
3478
+ action_name,
3479
+ nango_action,
3480
+ proxy_path,
3481
+ nango_proxy_path,
3482
+ field_map,
3483
+ required_fields,
3484
+ write_confirmed,
3485
+ agent_write_confirmed,
3486
+ config: normalizedConfig
3487
+ };
3488
+ }
3489
+ function normalizeOpsSinkConfigRequest(config) {
3490
+ const out = { ...config ?? {} };
3491
+ if (out.connection_id === void 0 && out.connectionId !== void 0) out.connection_id = out.connectionId;
3492
+ if (out.connector_id === void 0 && out.connectorId !== void 0) out.connector_id = out.connectorId;
3493
+ if (out.connector_name === void 0 && out.connectorName !== void 0) out.connector_name = out.connectorName;
3494
+ if (out.delivery_mode === void 0 && out.deliveryMode !== void 0) out.delivery_mode = out.deliveryMode;
3495
+ if (out.provider_config_key === void 0 && out.providerConfigKey !== void 0) out.provider_config_key = out.providerConfigKey;
3496
+ if (out.integration_id === void 0 && out.integrationId !== void 0) out.integration_id = out.integrationId;
3497
+ if (out.nango_connection_id === void 0 && out.nangoConnectionId !== void 0) out.nango_connection_id = out.nangoConnectionId;
3498
+ if (out.action_name === void 0 && out.actionName !== void 0) out.action_name = out.actionName;
3499
+ if (out.nango_action === void 0 && out.nangoAction !== void 0) out.nango_action = out.nangoAction;
3500
+ if (out.proxy_path === void 0 && out.proxyPath !== void 0) out.proxy_path = out.proxyPath;
3501
+ if (out.nango_proxy_path === void 0 && out.nangoProxyPath !== void 0) out.nango_proxy_path = out.nangoProxyPath;
3502
+ if (out.field_map === void 0 && out.fieldMap !== void 0) out.field_map = out.fieldMap;
3503
+ if (out.required_fields === void 0 && out.requiredFields !== void 0) out.required_fields = out.requiredFields;
3504
+ if (out.write_confirmed === void 0 && out.writeConfirmed !== void 0) out.write_confirmed = out.writeConfirmed;
3505
+ if (out.agent_write_confirmed === void 0 && out.agentWriteConfirmed !== void 0) out.agent_write_confirmed = out.agentWriteConfirmed;
3506
+ return out;
3507
+ }
3371
3508
  function buildApproveBody(params) {
3372
3509
  const { tokenId, tokenIds, reviewerNotes, ...rest } = params;
3373
3510
  return {
@@ -3516,6 +3653,57 @@ var GtmKernel = class {
3516
3653
  limit: options.limit
3517
3654
  });
3518
3655
  }
3656
+ /** Discover existing provider campaigns, starting with live/Kernel-linked Instantly campaigns, before audit or import preview. */
3657
+ async discoverExistingCampaigns(options = {}) {
3658
+ return this.callMcp("gtm_existing_campaign_discover", {
3659
+ provider: options.provider,
3660
+ integration_id: options.integrationId,
3661
+ search: options.search,
3662
+ limit: options.limit,
3663
+ include_kernel_linked: options.includeKernelLinked,
3664
+ include_provider_live: options.includeProviderLive
3665
+ });
3666
+ }
3667
+ /** Run a read-only existing campaign audit with completeness, recommendations, safe next MCP JSON, and approval boundaries. */
3668
+ async auditExistingCampaign(options) {
3669
+ return this.callMcp("gtm_existing_campaign_audit", {
3670
+ campaign_id: options.campaignId,
3671
+ provider: options.provider,
3672
+ provider_campaign_id: options.providerCampaignId,
3673
+ campaign_name: options.campaignName,
3674
+ days: options.days,
3675
+ include_route_preview: options.includeRoutePreview,
3676
+ include_memory: options.includeMemory,
3677
+ include_brain: options.includeBrain
3678
+ });
3679
+ }
3680
+ /** Discover the first matching existing provider campaign, then run the same read-only audit against that match. */
3681
+ async auditExistingCampaignBySearch(options) {
3682
+ const discovery = await this.discoverExistingCampaigns({
3683
+ provider: options.provider,
3684
+ integrationId: options.integrationId,
3685
+ search: options.search,
3686
+ limit: 1,
3687
+ includeKernelLinked: options.includeKernelLinked,
3688
+ includeProviderLive: options.includeProviderLive
3689
+ });
3690
+ const match = discovery.campaigns?.[0];
3691
+ const campaignId = match?.linked_kernel_campaign_id || void 0;
3692
+ const providerCampaignId = match?.provider_campaign_id || void 0;
3693
+ if (!campaignId && !providerCampaignId) {
3694
+ throw new Error(`No existing ${options.provider || discovery.provider || "provider"} campaign matched "${options.search}"`);
3695
+ }
3696
+ return this.auditExistingCampaign({
3697
+ provider: options.provider || discovery.provider || match?.provider,
3698
+ campaignId,
3699
+ providerCampaignId,
3700
+ campaignName: match?.name || match?.linked_kernel_campaign_name || void 0,
3701
+ days: options.days,
3702
+ includeRoutePreview: options.includeRoutePreview,
3703
+ includeMemory: options.includeMemory,
3704
+ includeBrain: options.includeBrain
3705
+ });
3706
+ }
3519
3707
  /** Create a first-class GTM campaign object in the current workspace. */
3520
3708
  async createCampaign(input) {
3521
3709
  return this.callMcp("gtm_campaign_create", campaignCreateArgs(input));
@@ -3721,6 +3909,47 @@ var GtmKernel = class {
3721
3909
  brain_cycle_min_interval_minutes: input.brainCycleMinIntervalMinutes
3722
3910
  });
3723
3911
  }
3912
+ /** Preview anonymized Instantly workspace sources registered for Kernel import. */
3913
+ async previewKernelImport(input = {}) {
3914
+ return this.callMcp("gtm_kernel_import_preview", {
3915
+ source_ids: input.sourceIds,
3916
+ include_leads: input.includeLeads,
3917
+ include_replies: input.includeReplies,
3918
+ include_private_copy: input.includePrivateCopy,
3919
+ max_pages: input.maxPages,
3920
+ limit: input.limit
3921
+ });
3922
+ }
3923
+ /** Queue the read-only Instantly-to-GTM Kernel import. Live writes require writeApproved. */
3924
+ async runKernelImport(input = {}) {
3925
+ return this.callMcp("gtm_kernel_import_run", {
3926
+ source_ids: input.sourceIds,
3927
+ dry_run: input.dryRun,
3928
+ write_approved: input.writeApproved,
3929
+ include_leads: input.includeLeads,
3930
+ include_replies: input.includeReplies,
3931
+ include_private_copy: input.includePrivateCopy,
3932
+ private_copy_approved: input.privateCopyApproved,
3933
+ promote_global_patterns: input.promoteGlobalPatterns,
3934
+ min_global_privacy_k: input.minGlobalPrivacyK,
3935
+ max_pages: input.maxPages,
3936
+ limit: input.limit
3937
+ });
3938
+ }
3939
+ /** Queue Brain distillation over imported Instantly memory with abstracted-only outputs. */
3940
+ async runBrainDistillation(input = {}) {
3941
+ return this.callMcp("gtm_brain_distill_run", {
3942
+ source_ids: input.sourceIds,
3943
+ write_mode: input.writeMode,
3944
+ write_approved: input.writeApproved,
3945
+ brain_cycle_phases: input.brainCyclePhases,
3946
+ days: input.days,
3947
+ network_days: input.networkDays,
3948
+ min_sample_size: input.minSampleSize,
3949
+ min_workspace_count: input.minWorkspaceCount,
3950
+ min_privacy_k: input.minPrivacyK
3951
+ });
3952
+ }
3724
3953
  /** Prepare a provider-agnostic feedback webhook URL for Smartlead, HeyReach, Airbyte, or custom sender events. */
3725
3954
  async prepareFeedbackWebhook(input) {
3726
3955
  return this.callMcp("gtm_feedback_webhook_prepare", {
@@ -4148,6 +4377,43 @@ var GtmKernel = class {
4148
4377
  context: input.context
4149
4378
  });
4150
4379
  }
4380
+ /** List Nango-backed action tools for a workspace connection without executing them. */
4381
+ async listNangoTools(options = {}) {
4382
+ return this.callMcp("nango_mcp_tools_list", {
4383
+ workspace_connection_id: options.workspaceConnectionId,
4384
+ connection_id: options.connectionId,
4385
+ provider_config_key: options.providerConfigKey,
4386
+ integration_id: options.integrationId,
4387
+ nango_connection_id: options.nangoConnectionId,
4388
+ format: options.format,
4389
+ include_raw: options.includeRaw
4390
+ });
4391
+ }
4392
+ /** Dry-run or execute a Nango-backed action tool through the approval-aware MCP bridge. */
4393
+ async callNangoTool(input) {
4394
+ return this.callMcp("nango_mcp_tool_call", {
4395
+ workspace_connection_id: input.workspaceConnectionId,
4396
+ connection_id: input.connectionId,
4397
+ provider_config_key: input.providerConfigKey,
4398
+ integration_id: input.integrationId,
4399
+ nango_connection_id: input.nangoConnectionId,
4400
+ action_name: input.actionName,
4401
+ tool_name: input.toolName,
4402
+ input: input.input,
4403
+ async: input.async,
4404
+ max_retries: input.maxRetries,
4405
+ dry_run: input.dryRun,
4406
+ confirm: input.confirm,
4407
+ confirm_write: input.confirmWrite
4408
+ });
4409
+ }
4410
+ /** Poll an async Nango action result by action id or status URL. */
4411
+ async getNangoActionResult(input) {
4412
+ return this.callMcp("nango_mcp_action_result_get", {
4413
+ action_id: input.actionId,
4414
+ status_url: input.statusUrl
4415
+ });
4416
+ }
4151
4417
  /** Deliver approved campaign-layer records to a webhook recipe, starting with Clay-style webhooks. */
4152
4418
  async deliverWebhook(input) {
4153
4419
  return this.callMcp("gtm_webhook_deliver", {
@@ -4282,6 +4548,82 @@ function compact2(value) {
4282
4548
  }
4283
4549
 
4284
4550
  // src/index.ts
4551
+ function inferMcpToolCategory(toolName) {
4552
+ if (typeof toolName !== "string" || !toolName) return void 0;
4553
+ if (toolName.startsWith("ops_") || toolName === "get_ops_readiness" || toolName === "get_gtm_ops_readiness" || toolName.startsWith("gtm_") || [
4554
+ "list_routines",
4555
+ "create_routine",
4556
+ "update_routine",
4557
+ "run_routine_now",
4558
+ "get_routine",
4559
+ "get_routine_ticks",
4560
+ "get_tick_items",
4561
+ "get_last_tick_items",
4562
+ "chain_routines",
4563
+ "get_chain_status",
4564
+ "launch_campaign",
4565
+ "quickstart_gtm_book",
4566
+ "list_campaigns",
4567
+ "campaign_performance",
4568
+ "tune_campaign",
4569
+ "emit_event",
4570
+ "approvals_list",
4571
+ "list_output_sinks",
4572
+ "create_output_sink",
4573
+ "update_output_sink",
4574
+ "delete_output_sink",
4575
+ "attach_sink_to_routine"
4576
+ ].includes(toolName)) {
4577
+ return "ops";
4578
+ }
4579
+ if ([
4580
+ "find_emails_with_verification",
4581
+ "verify_email",
4582
+ "enrich_company_signals",
4583
+ "company_intelligence",
4584
+ "find_contacts_with_email",
4585
+ "execute_primitive"
4586
+ ].includes(toolName)) {
4587
+ return "enrichment";
4588
+ }
4589
+ if (toolName.includes("icp")) return "icp";
4590
+ if (toolName.startsWith("ai_clean_")) return "data_cleaning";
4591
+ if (toolName.includes("system") || toolName.includes("workflow")) return "automation";
4592
+ if (toolName.includes("agent") || toolName.includes("platform_health") || toolName === "discover_capabilities") return "observability";
4593
+ return void 0;
4594
+ }
4595
+ function mapMcpToolInfo(t) {
4596
+ const annotations = asRecord3(t.annotations);
4597
+ const execution = asRecord3(t.execution);
4598
+ const schemas = asRecord3(t.schemas);
4599
+ const name = typeof t.name === "string" ? t.name : typeof t.id === "string" ? t.id : "";
4600
+ return {
4601
+ name,
4602
+ description: String(t.description ?? t.short_description ?? "").slice(0, 120),
4603
+ category: typeof t.category === "string" ? t.category : typeof annotations?.category === "string" ? annotations.category : inferMcpToolCategory(name),
4604
+ costCredits: typeof (execution?.cost_credits ?? annotations?.cost_credits) === "number" ? execution?.cost_credits ?? annotations?.cost_credits : void 0,
4605
+ contractVersion: typeof t.contract_version === "string" ? t.contract_version : typeof (annotations?.contract_version ?? annotations?.contract?.contract_version) === "string" ? annotations?.contract_version ?? annotations?.contract?.contract_version : void 0,
4606
+ permissionLevel: typeof (execution?.permission_level ?? annotations?.permission_level ?? annotations?.contract?.permission_level) === "string" ? execution?.permission_level ?? annotations?.permission_level ?? annotations?.contract?.permission_level : void 0,
4607
+ authScopes: asStringArray(execution?.auth_scopes ?? annotations?.auth_scopes ?? annotations?.contract?.auth_scopes),
4608
+ idempotent: typeof (execution?.idempotent ?? annotations?.idempotentHint ?? annotations?.idempotent ?? annotations?.contract?.idempotent) === "boolean" ? execution?.idempotent ?? annotations?.idempotentHint ?? annotations?.idempotent ?? annotations?.contract?.idempotent : void 0,
4609
+ destructive: typeof (execution?.destructive ?? annotations?.destructiveHint ?? annotations?.destructive ?? annotations?.contract?.destructive) === "boolean" ? execution?.destructive ?? annotations?.destructiveHint ?? annotations?.destructive ?? annotations?.contract?.destructive : void 0,
4610
+ retryable: typeof (execution?.retryable ?? annotations?.retryable ?? annotations?.contract?.retryable) === "boolean" ? execution?.retryable ?? annotations?.retryable ?? annotations?.contract?.retryable : void 0,
4611
+ rateLimitKey: typeof (execution?.rate_limit_key ?? annotations?.rate_limit_key ?? annotations?.contract?.rate_limit_key) === "string" ? execution?.rate_limit_key ?? annotations?.rate_limit_key ?? annotations?.contract?.rate_limit_key : void 0,
4612
+ observability: asRecord3(annotations?.observability ?? annotations?.contract?.observability),
4613
+ inputSchema: asObjectSchema(schemas?.input ?? t.inputSchema ?? t.input_schema ?? annotations?.contract?.input_schema),
4614
+ outputSchema: asObjectSchema(schemas?.output ?? t.outputSchema ?? t.output_schema ?? annotations?.contract?.output_schema),
4615
+ annotations
4616
+ };
4617
+ }
4618
+ function asRecord3(value) {
4619
+ return value && typeof value === "object" ? value : void 0;
4620
+ }
4621
+ function asStringArray(value) {
4622
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : void 0;
4623
+ }
4624
+ function asObjectSchema(value) {
4625
+ return asRecord3(value);
4626
+ }
4285
4627
  var Signaliz = class {
4286
4628
  constructor(config) {
4287
4629
  this.client = new HttpClient(config);
@@ -4337,25 +4679,18 @@ var Signaliz = class {
4337
4679
  }
4338
4680
  /** List all available MCP tools */
4339
4681
  async listTools() {
4682
+ try {
4683
+ const manifest = await this.client.mcp("tools/call", {
4684
+ name: "get_tool_manifest",
4685
+ arguments: { include_schemas: true }
4686
+ });
4687
+ const tools2 = manifest?.tools ?? manifest ?? [];
4688
+ if (Array.isArray(tools2)) return tools2.map(mapMcpToolInfo);
4689
+ } catch (_err) {
4690
+ }
4340
4691
  const data = await this.client.mcp("tools/list", {});
4341
4692
  const tools = data?.tools ?? data ?? [];
4342
- return tools.map((t) => ({
4343
- name: t.name,
4344
- description: (t.description ?? "").slice(0, 120),
4345
- category: t.annotations?.category,
4346
- costCredits: t.annotations?.cost_credits,
4347
- contractVersion: t.annotations?.contract_version ?? t.annotations?.contract?.contract_version,
4348
- permissionLevel: t.annotations?.permission_level ?? t.annotations?.contract?.permission_level,
4349
- authScopes: t.annotations?.auth_scopes ?? t.annotations?.contract?.auth_scopes,
4350
- idempotent: t.annotations?.idempotentHint ?? t.annotations?.idempotent ?? t.annotations?.contract?.idempotent,
4351
- destructive: t.annotations?.destructiveHint ?? t.annotations?.destructive ?? t.annotations?.contract?.destructive,
4352
- retryable: t.annotations?.retryable ?? t.annotations?.contract?.retryable,
4353
- rateLimitKey: t.annotations?.rate_limit_key ?? t.annotations?.contract?.rate_limit_key,
4354
- observability: t.annotations?.observability ?? t.annotations?.contract?.observability,
4355
- inputSchema: t.inputSchema ?? t.input_schema ?? t.annotations?.contract?.input_schema,
4356
- outputSchema: t.outputSchema ?? t.output_schema ?? t.annotations?.contract?.output_schema,
4357
- annotations: t.annotations
4358
- }));
4693
+ return tools.map(mapMcpToolInfo);
4359
4694
  }
4360
4695
  /** Discover tools by natural language query */
4361
4696
  async discover(query, category) {
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Signaliz
4
- } from "./chunk-L6XUFJJO.mjs";
4
+ } from "./chunk-GF2T2X3W.mjs";
5
5
 
6
6
  // src/cli.ts
7
7
  var apiKey = process.env.SIGNALIZ_API_KEY;