@kadoa/mcp 0.3.1-rc.0 → 0.3.2

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/README.md CHANGED
@@ -6,6 +6,12 @@ Use [Kadoa](https://kadoa.com) from ChatGPT, Claude.ai, Claude Code, Cursor, and
6
6
 
7
7
  A hosted MCP server is available at `https://mcp.kadoa.com/mcp`. Connect from any MCP client — no local install, no API key config. You sign in with your Kadoa account via OAuth.
8
8
 
9
+ ### Claude Code
10
+
11
+ ```bash
12
+ claude mcp add kadoa --transport http https://mcp.kadoa.com/mcp
13
+ ```
14
+
9
15
  ### ChatGPT
10
16
 
11
17
  1. Go to **Settings → Connectors → Add MCP server**
@@ -144,6 +150,7 @@ Get your API key from [kadoa.com/settings](https://kadoa.com/settings).
144
150
  | `delete_workflow` | Delete a workflow |
145
151
  | `approve_workflow` | Approve and activate a workflow |
146
152
  | `update_workflow` | Update workflow configuration and schema |
153
+ | `whoami` | Show current user details, auth method, and team memberships |
147
154
  | `team_list` | List all teams you belong to and see which is active |
148
155
  | `team_switch` | Switch the active team by name or ID |
149
156
 
package/dist/index.js CHANGED
@@ -49273,26 +49273,87 @@ function registerTools(server, ctx) {
49273
49273
  "FOUR_WEEKS",
49274
49274
  "MONTHLY",
49275
49275
  "REAL_TIME"
49276
- ]).optional().describe("How often the workflow runs. Defaults to ONLY_ONCE. Use REAL_TIME for continuous monitoring.")
49276
+ ]).optional().describe("How often the workflow runs. Defaults to ONLY_ONCE. Use REAL_TIME for continuous monitoring."),
49277
+ notifications: exports_external.object({
49278
+ email: exports_external.boolean().optional().describe("Send email notifications to the account email when data changes"),
49279
+ webhook: exports_external.object({
49280
+ url: exports_external.string().url().describe("Webhook endpoint URL"),
49281
+ httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)")
49282
+ }).optional().describe("Send notifications via HTTP webhook"),
49283
+ slack: exports_external.object({
49284
+ webhookUrl: exports_external.string().url().describe("Slack incoming webhook URL")
49285
+ }).optional().describe("Send notifications to a Slack channel"),
49286
+ websocket: exports_external.boolean().optional().describe("Enable WebSocket notifications for programmatic real-time consumption")
49287
+ }).optional().describe("Notification channels to alert when data changes. At least one channel is required for REAL_TIME workflows.")
49277
49288
  },
49278
49289
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
49279
49290
  }, withErrorHandling("create_workflow", async (args) => {
49280
- const extraction = args.schema ? (builder) => {
49281
- const entity = builder.entity(args.entity || "Data");
49291
+ const n = args.notifications;
49292
+ const hasNotifications = n && (n.email || n.webhook || n.slack || n.websocket);
49293
+ if (args.interval === "REAL_TIME" && !hasNotifications) {
49294
+ return errorResult("Real-time workflows require at least one notification channel so you get alerted when data changes. " + "Add a notifications object with one or more channels: email, webhook, slack, or websocket.");
49295
+ }
49296
+ const extraction = args.schema ? (builder2) => {
49297
+ const entity = builder2.entity(args.entity || "Data");
49282
49298
  for (const field of args.schema) {
49283
49299
  entity.field(field.name, field.description || field.name, field.dataType || "STRING", { example: field.example });
49284
49300
  }
49285
49301
  return entity;
49286
49302
  } : undefined;
49287
- const workflow = await ctx.client.extract({
49303
+ let builder = ctx.client.extract({
49288
49304
  urls: args.urls,
49289
49305
  name: args.name || "Untitled Workflow",
49290
49306
  navigationMode: "agentic-navigation",
49291
49307
  userPrompt: args.prompt,
49292
49308
  extraction,
49293
49309
  interval: args.interval
49294
- }).create();
49295
- const message = args.interval === "REAL_TIME" ? "Workflow created successfully. This real-time workflow monitors continuously — no manual runs needed. Use fetch_data to retrieve the latest extracted results." : "Workflow created successfully. The AI agent will start extracting data automatically.";
49310
+ });
49311
+ if (hasNotifications) {
49312
+ const channels = {};
49313
+ if (n.email)
49314
+ channels.EMAIL = true;
49315
+ if (n.websocket)
49316
+ channels.WEBSOCKET = true;
49317
+ if (n.webhook) {
49318
+ channels.WEBHOOK = {
49319
+ name: "mcp-webhook",
49320
+ webhookUrl: n.webhook.url,
49321
+ httpMethod: n.webhook.httpMethod || "POST"
49322
+ };
49323
+ }
49324
+ if (n.slack) {
49325
+ channels.SLACK = {
49326
+ name: "mcp-slack",
49327
+ webhookUrl: n.slack.webhookUrl
49328
+ };
49329
+ }
49330
+ builder = builder.withNotifications({
49331
+ events: ["workflow_data_change"],
49332
+ channels
49333
+ });
49334
+ }
49335
+ const workflow = await builder.create();
49336
+ const enabledChannels = [];
49337
+ if (n?.email) {
49338
+ const user = await ctx.client.user.getCurrentUser();
49339
+ enabledChannels.push(`email (${user.email})`);
49340
+ }
49341
+ if (n?.slack)
49342
+ enabledChannels.push(`slack (${n.slack.webhookUrl})`);
49343
+ if (n?.webhook)
49344
+ enabledChannels.push(`webhook (${n.webhook.url})`);
49345
+ if (n?.websocket)
49346
+ enabledChannels.push("websocket");
49347
+ let message = "Workflow created successfully.";
49348
+ if (args.interval === "REAL_TIME") {
49349
+ message += " This real-time workflow monitors continuously — no manual runs needed.";
49350
+ } else {
49351
+ message += " The AI agent will start extracting data automatically.";
49352
+ }
49353
+ if (enabledChannels.length > 0) {
49354
+ message += ` Notifications on data changes via: ${enabledChannels.join(", ")}.`;
49355
+ }
49356
+ message += " Use fetch_data to retrieve the latest extracted results.";
49296
49357
  return jsonResult({
49297
49358
  success: true,
49298
49359
  workflowId: workflow.workflowId,
@@ -53959,7 +54020,7 @@ function renderTeamSelectionPage(teams, selectionToken) {
53959
54020
  function escapeHtml(str) {
53960
54021
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
53961
54022
  }
53962
- var clients, pendingAuths, pendingTeamSelections, authCodes, accessTokens, refreshTokens, TEAM_SELECTION_TTL, ACCESS_TOKEN_TTL = 3600, kadoaClientsStore;
54023
+ var clients, pendingAuths, pendingTeamSelections, authCodes, accessTokens, refreshTokens, TEAM_SELECTION_TTL, ACCESS_TOKEN_TTL, kadoaClientsStore;
53963
54024
  var init_auth2 = __esm(() => {
53964
54025
  clients = new Map;
53965
54026
  pendingAuths = new Map;
@@ -53968,6 +54029,7 @@ var init_auth2 = __esm(() => {
53968
54029
  accessTokens = new Map;
53969
54030
  refreshTokens = new Map;
53970
54031
  TEAM_SELECTION_TTL = 10 * 60 * 1000;
54032
+ ACCESS_TOKEN_TTL = 7 * 24 * 3600;
53971
54033
  kadoaClientsStore = {
53972
54034
  getClient(clientId) {
53973
54035
  return clients.get(clientId);
@@ -54184,7 +54246,7 @@ function createServer(auth) {
54184
54246
  client: createKadoaClient(auth)
54185
54247
  };
54186
54248
  }
54187
- const server = new McpServer({ name: "kadoa", version: "0.2.0" });
54249
+ const server = new McpServer({ name: "kadoa", version: "0.3.2" });
54188
54250
  registerTools(server, ctx);
54189
54251
  server.server.onerror = (error48) => console.error("[MCP Error]", error48);
54190
54252
  return server;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kadoa/mcp",
3
- "version": "0.3.1-rc.0",
3
+ "version": "0.3.2",
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",