@kadoa/mcp 0.3.5-rc.7 → 0.3.6-rc.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.
Files changed (2) hide show
  1. package/dist/index.js +99 -85
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -49261,24 +49261,6 @@ function classifyError(error48) {
49261
49261
  return "Unknown error";
49262
49262
  }
49263
49263
  function registerTools(server, ctx) {
49264
- async function elicit(message, schema, required2) {
49265
- try {
49266
- const result = await server.server.elicitInput({
49267
- message,
49268
- requestedSchema: {
49269
- type: "object",
49270
- properties: schema,
49271
- ...required2 ? { required: required2 } : {}
49272
- }
49273
- });
49274
- if (result.action === "accept" && result.content) {
49275
- return result.content;
49276
- }
49277
- return null;
49278
- } catch {
49279
- return null;
49280
- }
49281
- }
49282
49264
  function withErrorHandling(name, handler) {
49283
49265
  return async (...args) => {
49284
49266
  try {
@@ -49322,16 +49304,28 @@ function registerTools(server, ctx) {
49322
49304
  entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
49323
49305
  schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape))).optional().describe("Extraction schema fields. If omitted, the AI agent auto-detects the schema.")
49324
49306
  };
49307
+ const webhookAuthShape = exports_external.object({
49308
+ type: exports_external.enum(["bearer", "basic", "header"]).describe("Authentication type"),
49309
+ token: exports_external.string().optional().describe("Bearer token (required for 'bearer' type)"),
49310
+ username: exports_external.string().optional().describe("Username (required for 'basic' type)"),
49311
+ password: exports_external.string().optional().describe("Password (required for 'basic' type)"),
49312
+ headers: exports_external.object({}).passthrough().optional().describe("Custom headers as key-value pairs (required for 'header' type)")
49313
+ }).optional().describe("Authentication configuration for the webhook endpoint");
49325
49314
  const notificationsInputShape = {
49326
49315
  notifications: exports_external.object({
49327
- email: exports_external.boolean().optional().describe("Send email notifications to the account email when data changes"),
49316
+ email: exports_external.object({
49317
+ recipients: exports_external.array(exports_external.string().email()).optional().describe("Email addresses to notify. Omit to use account default email.")
49318
+ }).optional().describe("Send email notifications. Pass {} for account default email, or {recipients: [...]} for custom addresses."),
49328
49319
  webhook: exports_external.object({
49329
49320
  url: exports_external.string().url().describe("Webhook endpoint URL"),
49330
- httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)")
49321
+ httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)"),
49322
+ auth: webhookAuthShape
49331
49323
  }).optional().describe("Send notifications via HTTP webhook"),
49332
49324
  slack: exports_external.object({
49333
- webhookUrl: exports_external.string().url().describe("Slack incoming webhook URL")
49334
- }).optional().describe("Send notifications to a Slack channel"),
49325
+ webhookUrl: exports_external.string().url().optional().describe("Slack incoming webhook URL (legacy)"),
49326
+ slackChannelId: exports_external.string().optional().describe("Slack channel ID from OAuth integration (e.g. C01ABCDEF)"),
49327
+ slackChannelName: exports_external.string().optional().describe("Slack channel name (e.g. #alerts)")
49328
+ }).optional().describe("Send notifications to a Slack channel. Use slackChannelId/slackChannelName for OAuth integration, or webhookUrl for legacy incoming webhooks."),
49335
49329
  websocket: exports_external.boolean().optional().describe("Enable WebSocket notifications for programmatic real-time consumption")
49336
49330
  }).optional().describe("Notification channels to alert when data changes.")
49337
49331
  };
@@ -49352,22 +49346,34 @@ function registerTools(server, ctx) {
49352
49346
  }
49353
49347
  function buildNotificationChannels(n) {
49354
49348
  const channels = {};
49355
- if (n.email)
49356
- channels.EMAIL = true;
49349
+ if (n.email) {
49350
+ if (typeof n.email === "object" && n.email.recipients?.length) {
49351
+ channels.EMAIL = { name: "mcp-email", recipients: n.email.recipients };
49352
+ } else {
49353
+ channels.EMAIL = true;
49354
+ }
49355
+ }
49357
49356
  if (n.websocket)
49358
49357
  channels.WEBSOCKET = true;
49359
49358
  if (n.webhook) {
49360
- channels.WEBHOOK = {
49359
+ const webhookChannel = {
49361
49360
  name: "mcp-webhook",
49362
49361
  webhookUrl: n.webhook.url,
49363
49362
  httpMethod: n.webhook.httpMethod || "POST"
49364
49363
  };
49364
+ if (n.webhook.auth)
49365
+ webhookChannel.auth = n.webhook.auth;
49366
+ channels.WEBHOOK = webhookChannel;
49365
49367
  }
49366
49368
  if (n.slack) {
49367
- channels.SLACK = {
49368
- name: "mcp-slack",
49369
- webhookUrl: n.slack.webhookUrl
49370
- };
49369
+ const slackChannel = { name: "mcp-slack" };
49370
+ if (n.slack.webhookUrl)
49371
+ slackChannel.webhookUrl = n.slack.webhookUrl;
49372
+ if (n.slack.slackChannelId)
49373
+ slackChannel.slackChannelId = n.slack.slackChannelId;
49374
+ if (n.slack.slackChannelName)
49375
+ slackChannel.slackChannelName = n.slack.slackChannelName;
49376
+ channels.SLACK = slackChannel;
49371
49377
  }
49372
49378
  return channels;
49373
49379
  }
@@ -49376,11 +49382,17 @@ function registerTools(server, ctx) {
49376
49382
  return [];
49377
49383
  const channels = [];
49378
49384
  if (n.email) {
49379
- const user = await ctx.client.user.getCurrentUser();
49380
- channels.push(`email (${user.email})`);
49385
+ if (typeof n.email === "object" && n.email.recipients?.length) {
49386
+ channels.push(`email (${n.email.recipients.join(", ")})`);
49387
+ } else {
49388
+ const user = await ctx.client.user.getCurrentUser();
49389
+ channels.push(`email (${user.email})`);
49390
+ }
49391
+ }
49392
+ if (n.slack) {
49393
+ const slackDesc = n.slack.slackChannelName || n.slack.slackChannelId || n.slack.webhookUrl || "default";
49394
+ channels.push(`slack (${slackDesc})`);
49381
49395
  }
49382
- if (n.slack)
49383
- channels.push(`slack (${n.slack.webhookUrl})`);
49384
49396
  if (n.webhook)
49385
49397
  channels.push(`webhook (${n.webhook.url})`);
49386
49398
  if (n.websocket)
@@ -49608,20 +49620,13 @@ function registerTools(server, ctx) {
49608
49620
  workflowStatus = workflow.displayState ?? workflow.state ?? "unknown";
49609
49621
  } catch {}
49610
49622
  if (!args.confirmed) {
49611
- const confirmation = await elicit(`Are you sure you want to permanently delete "${workflowName}" (${workflowStatus})? This cannot be undone.`, { confirm: { type: "boolean", description: "Confirm deletion" } }, ["confirm"]);
49612
- if (confirmation !== null) {
49613
- if (!confirmation.confirm) {
49614
- return jsonResult({ success: false, message: "Deletion cancelled by user." });
49615
- }
49616
- } else {
49617
- return jsonResult({
49618
- pending: true,
49619
- workflowId: args.workflowId,
49620
- workflowName,
49621
- status: workflowStatus,
49622
- message: `⚠️ You are about to permanently delete "${workflowName}" (${workflowStatus}). This cannot be undone. Ask the user to confirm, then call delete_workflow again with confirmed=true.`
49623
- });
49624
- }
49623
+ return jsonResult({
49624
+ pending: true,
49625
+ workflowId: args.workflowId,
49626
+ workflowName,
49627
+ status: workflowStatus,
49628
+ message: `⚠️ You are about to permanently delete "${workflowName}" (${workflowStatus}). This cannot be undone. Ask the user to confirm, then call delete_workflow again with confirmed=true.`
49629
+ });
49625
49630
  }
49626
49631
  await ctx.client.workflow.delete(args.workflowId);
49627
49632
  return jsonResult({
@@ -49722,15 +49727,24 @@ function registerTools(server, ctx) {
49722
49727
  });
49723
49728
  }));
49724
49729
  server.registerTool("create_notification_channel", {
49725
- description: "Create a notification channel (email, webhook, or slack). The channel can then be linked to notification settings for specific events.",
49730
+ description: "Create a notification channel (email, webhook, slack, or websocket). The channel can then be linked to notification settings for specific events. " + "For SLACK: use slackChannelId + slackChannelName for OAuth integration, or webhookUrl for legacy incoming webhooks. " + "For WEBHOOK: auth is optional and supports bearer, basic, or header authentication.",
49726
49731
  inputSchema: {
49727
- channelType: exports_external.enum(["EMAIL", "WEBHOOK", "SLACK"]).describe("Type of notification channel"),
49732
+ channelType: exports_external.enum(["EMAIL", "WEBHOOK", "SLACK", "WEBSOCKET"]).describe("Type of notification channel"),
49728
49733
  name: exports_external.string().optional().describe("Name for the channel (defaults to 'default')"),
49729
49734
  config: exports_external.object({
49730
49735
  recipients: exports_external.array(exports_external.string()).optional().describe("Email recipients (required for EMAIL channels)"),
49731
- webhookUrl: exports_external.string().optional().describe("Webhook/Slack endpoint URL (required for WEBHOOK and SLACK channels)"),
49732
- httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method for WEBHOOK channels (defaults to POST)")
49733
- }).optional().describe("Channel-specific configuration. For EMAIL: provide recipients. For WEBHOOK: provide webhookUrl. For SLACK: provide webhookUrl.")
49736
+ webhookUrl: exports_external.string().optional().describe("Webhook/Slack endpoint URL (required for WEBHOOK, optional for SLACK)"),
49737
+ httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method for WEBHOOK channels (defaults to POST)"),
49738
+ slackChannelId: exports_external.string().optional().describe("Slack channel ID from OAuth integration (for SLACK channels, e.g. C01ABCDEF)"),
49739
+ slackChannelName: exports_external.string().optional().describe("Slack channel name (for SLACK channels, e.g. #alerts)"),
49740
+ auth: exports_external.object({
49741
+ type: exports_external.enum(["bearer", "basic", "header"]).describe("Authentication type"),
49742
+ token: exports_external.string().optional().describe("Bearer token (for 'bearer' type)"),
49743
+ username: exports_external.string().optional().describe("Username (for 'basic' type)"),
49744
+ password: exports_external.string().optional().describe("Password (for 'basic' type)"),
49745
+ headers: exports_external.object({}).passthrough().optional().describe("Custom headers as key-value pairs (for 'header' type)")
49746
+ }).optional().describe("Authentication for WEBHOOK channels")
49747
+ }).optional().describe("Channel-specific configuration. " + "EMAIL: provide recipients. " + "WEBHOOK: provide webhookUrl, httpMethod, and optionally auth. " + "SLACK: provide slackChannelId + slackChannelName (OAuth) or webhookUrl (legacy). " + "WEBSOCKET: no config needed.")
49734
49748
  },
49735
49749
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
49736
49750
  }, withErrorHandling("create_notification_channel", async (args) => {
@@ -49758,18 +49772,11 @@ function registerTools(server, ctx) {
49758
49772
  annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true }
49759
49773
  }, withErrorHandling("delete_notification_channel", async (args) => {
49760
49774
  if (!args.confirmed) {
49761
- const confirmation = await elicit(`Are you sure you want to delete notification channel "${args.channelId}"?`, { confirm: { type: "boolean", description: "Confirm deletion" } }, ["confirm"]);
49762
- if (confirmation !== null) {
49763
- if (!confirmation.confirm) {
49764
- return jsonResult({ success: false, message: "Deletion cancelled by user." });
49765
- }
49766
- } else {
49767
- return jsonResult({
49768
- pending: true,
49769
- channelId: args.channelId,
49770
- message: `⚠️ About to delete notification channel "${args.channelId}". Ask the user to confirm, then call again with confirmed=true.`
49771
- });
49772
- }
49775
+ return jsonResult({
49776
+ pending: true,
49777
+ channelId: args.channelId,
49778
+ message: `⚠️ About to delete notification channel "${args.channelId}". Ask the user to confirm, then call again with confirmed=true.`
49779
+ });
49773
49780
  }
49774
49781
  await ctx.client.notification.channels.deleteChannel(args.channelId);
49775
49782
  return jsonResult({
@@ -49787,6 +49794,10 @@ function registerTools(server, ctx) {
49787
49794
  "workflow_failed",
49788
49795
  "workflow_sample_finished",
49789
49796
  "workflow_data_change",
49797
+ "workflow_validation_anomaly_change",
49798
+ "workflow_export_completed",
49799
+ "workflow_health_degraded",
49800
+ "workflow_recovered",
49790
49801
  "system_maintenance",
49791
49802
  "service_degradation",
49792
49803
  "credits_low",
@@ -49817,18 +49828,21 @@ function registerTools(server, ctx) {
49817
49828
  description: "Set up notifications for a workflow or workspace. Creates channels and settings in one step. " + "Specify which events to listen for and which channels to deliver to (email, webhook, slack, websocket).",
49818
49829
  inputSchema: {
49819
49830
  workflowId: exports_external.string().optional().describe("Workflow ID to configure notifications for. Omit for workspace-level notifications."),
49820
- events: exports_external.array(exports_external.string()).describe('Event types to notify on. Pass ["all"] for all events, or pick from: ' + "workflow_started, workflow_finished, workflow_failed, workflow_sample_finished, " + "workflow_data_change, system_maintenance, service_degradation, credits_low, free_trial_ending"),
49831
+ events: exports_external.array(exports_external.string()).describe('Event types to notify on. Pass ["all"] for all events, or pick from: ' + "workflow_started, workflow_finished, workflow_failed, workflow_sample_finished, " + "workflow_data_change, workflow_validation_anomaly_change, workflow_export_completed, " + "workflow_health_degraded, workflow_recovered, " + "system_maintenance, service_degradation, credits_low, free_trial_ending"),
49821
49832
  channels: exports_external.object({
49822
49833
  email: exports_external.object({
49823
49834
  recipients: exports_external.array(exports_external.string().email()).optional().describe("Email addresses to notify. Omit to use the account default email.")
49824
49835
  }).optional().describe("Send email notifications. Pass {} for default email or {recipients: [...]} for custom addresses."),
49825
49836
  webhook: exports_external.object({
49826
49837
  url: exports_external.string().url().describe("Webhook endpoint URL"),
49827
- httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)")
49838
+ httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)"),
49839
+ auth: webhookAuthShape
49828
49840
  }).optional().describe("Send via HTTP webhook"),
49829
49841
  slack: exports_external.object({
49830
- webhookUrl: exports_external.string().url().describe("Slack incoming webhook URL")
49831
- }).optional().describe("Send to Slack channel"),
49842
+ webhookUrl: exports_external.string().url().optional().describe("Slack incoming webhook URL (legacy)"),
49843
+ slackChannelId: exports_external.string().optional().describe("Slack channel ID from OAuth integration (e.g. C01ABCDEF)"),
49844
+ slackChannelName: exports_external.string().optional().describe("Slack channel name (e.g. #alerts)")
49845
+ }).optional().describe("Send to Slack channel. Use slackChannelId/slackChannelName for OAuth integration, or webhookUrl for legacy incoming webhooks."),
49832
49846
  websocket: exports_external.boolean().optional().describe("Enable WebSocket notifications")
49833
49847
  }).describe("At least one channel must be specified")
49834
49848
  },
@@ -49847,17 +49861,24 @@ function registerTools(server, ctx) {
49847
49861
  if (ch.websocket)
49848
49862
  channelSetup.WEBSOCKET = true;
49849
49863
  if (ch.webhook) {
49850
- channelSetup.WEBHOOK = {
49864
+ const webhookChannel = {
49851
49865
  name: "mcp-webhook",
49852
49866
  webhookUrl: ch.webhook.url,
49853
49867
  httpMethod: ch.webhook.httpMethod || "POST"
49854
49868
  };
49869
+ if (ch.webhook.auth)
49870
+ webhookChannel.auth = ch.webhook.auth;
49871
+ channelSetup.WEBHOOK = webhookChannel;
49855
49872
  }
49856
49873
  if (ch.slack) {
49857
- channelSetup.SLACK = {
49858
- name: "mcp-slack",
49859
- webhookUrl: ch.slack.webhookUrl
49860
- };
49874
+ const slackChannel = { name: "mcp-slack" };
49875
+ if (ch.slack.webhookUrl)
49876
+ slackChannel.webhookUrl = ch.slack.webhookUrl;
49877
+ if (ch.slack.slackChannelId)
49878
+ slackChannel.slackChannelId = ch.slack.slackChannelId;
49879
+ if (ch.slack.slackChannelName)
49880
+ slackChannel.slackChannelName = ch.slack.slackChannelName;
49881
+ channelSetup.SLACK = slackChannel;
49861
49882
  }
49862
49883
  if (Object.keys(channelSetup).length === 0) {
49863
49884
  return errorResult("At least one notification channel must be specified (email, webhook, slack, or websocket).");
@@ -49889,18 +49910,11 @@ function registerTools(server, ctx) {
49889
49910
  annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true }
49890
49911
  }, withErrorHandling("delete_notification_setting", async (args) => {
49891
49912
  if (!args.confirmed) {
49892
- const confirmation = await elicit(`Are you sure you want to delete notification setting "${args.settingsId}"?`, { confirm: { type: "boolean", description: "Confirm deletion" } }, ["confirm"]);
49893
- if (confirmation !== null) {
49894
- if (!confirmation.confirm) {
49895
- return jsonResult({ success: false, message: "Deletion cancelled by user." });
49896
- }
49897
- } else {
49898
- return jsonResult({
49899
- pending: true,
49900
- settingsId: args.settingsId,
49901
- message: `⚠️ About to delete notification setting "${args.settingsId}". Ask the user to confirm, then call again with confirmed=true.`
49902
- });
49903
- }
49913
+ return jsonResult({
49914
+ pending: true,
49915
+ settingsId: args.settingsId,
49916
+ message: `⚠️ About to delete notification setting "${args.settingsId}". Ask the user to confirm, then call again with confirmed=true.`
49917
+ });
49904
49918
  }
49905
49919
  await ctx.client.notification.settings.deleteSettings(args.settingsId);
49906
49920
  return jsonResult({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kadoa/mcp",
3
- "version": "0.3.5-rc.7",
3
+ "version": "0.3.6-rc.0",
4
4
  "description": "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",