@kadoa/mcp 0.3.10-rc.1 → 0.3.10-rc.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.
Files changed (2) hide show
  1. package/dist/index.js +169 -79
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -49167,13 +49167,37 @@ function createKadoaClient(auth) {
49167
49167
  });
49168
49168
  return client;
49169
49169
  }
49170
- var ctxRefreshMutex;
49170
+ var refreshRawMutex, ctxRefreshMutex;
49171
49171
  var init_client = __esm(() => {
49172
49172
  init_dist2();
49173
+ refreshRawMutex = new Map;
49173
49174
  ctxRefreshMutex = new WeakMap;
49174
49175
  });
49175
49176
 
49176
49177
  // src/client.ts
49178
+ var exports_client = {};
49179
+ __export(exports_client, {
49180
+ refreshSupabaseJwtRaw: () => refreshSupabaseJwtRaw,
49181
+ refreshSupabaseJwt: () => refreshSupabaseJwt,
49182
+ isJwtExpired: () => isJwtExpired,
49183
+ getValidJwt: () => getValidJwt,
49184
+ decodeJwtClaims: () => decodeJwtClaims,
49185
+ createKadoaClient: () => createKadoaClient2,
49186
+ SessionExpiredError: () => SessionExpiredError,
49187
+ KadoaSdkException: () => KadoaSdkException,
49188
+ KadoaClient: () => KadoaClient
49189
+ });
49190
+ function createKadoaClient2(auth) {
49191
+ const client = new KadoaClient({ bearerToken: auth.jwt });
49192
+ client.axiosInstance.interceptors.request.use((config2) => {
49193
+ config2.headers["x-kadoa-source"] = "mcp";
49194
+ if (auth.teamId) {
49195
+ config2.headers["x-team-id"] = auth.teamId;
49196
+ }
49197
+ return config2;
49198
+ });
49199
+ return client;
49200
+ }
49177
49201
  function decodeJwtClaims(jwt2) {
49178
49202
  try {
49179
49203
  const payload = JSON.parse(Buffer.from(jwt2.split(".")[1], "base64url").toString());
@@ -49195,36 +49219,57 @@ function isJwtExpired(jwt2) {
49195
49219
  return true;
49196
49220
  }
49197
49221
  }
49198
- async function refreshSupabaseJwt(ctx) {
49199
- if (!ctx.supabaseRefreshToken) {
49200
- console.error("[JWT_REFRESH] No refresh token available, cannot refresh");
49201
- return;
49222
+ async function refreshSupabaseJwtRaw(supabaseRefreshToken) {
49223
+ const inflight = refreshRawMutex2.get(supabaseRefreshToken);
49224
+ if (inflight) {
49225
+ console.error(`[JWT_REFRESH] DEDUP: reusing in-flight raw refresh`);
49226
+ return inflight;
49202
49227
  }
49228
+ const promise3 = _doRefreshRaw(supabaseRefreshToken).finally(() => {
49229
+ refreshRawMutex2.delete(supabaseRefreshToken);
49230
+ });
49231
+ refreshRawMutex2.set(supabaseRefreshToken, promise3);
49232
+ return promise3;
49233
+ }
49234
+ async function _doRefreshRaw(supabaseRefreshToken) {
49203
49235
  const supabaseUrl = process.env.SUPABASE_URL;
49204
49236
  if (!supabaseUrl) {
49205
49237
  console.error("[JWT_REFRESH] SUPABASE_URL not set, cannot refresh");
49238
+ return null;
49239
+ }
49240
+ const res = await fetch(`${supabaseUrl}/auth/v1/token?grant_type=refresh_token`, {
49241
+ method: "POST",
49242
+ headers: {
49243
+ "Content-Type": "application/json",
49244
+ apikey: process.env.SUPABASE_ANON_KEY
49245
+ },
49246
+ body: JSON.stringify({ refresh_token: supabaseRefreshToken })
49247
+ });
49248
+ if (res.ok) {
49249
+ const data = await res.json();
49250
+ return { jwt: data.access_token, refreshToken: data.refresh_token };
49251
+ }
49252
+ const body = await res.text().catch(() => "");
49253
+ console.error(`[JWT_REFRESH] FAIL: Supabase returned ${res.status} (refreshToken=${supabaseRefreshToken.slice(0, 12)}...): ${body}`);
49254
+ if (body.includes("session_expired") || body.includes("refresh_token_not_found") || body.includes("refresh_token_already_used")) {
49255
+ throw new SessionExpiredError("Your Kadoa session has expired due to inactivity. Please reconnect to re-authenticate.");
49256
+ }
49257
+ return null;
49258
+ }
49259
+ async function refreshSupabaseJwt(ctx) {
49260
+ if (!ctx.supabaseRefreshToken) {
49261
+ console.error("[JWT_REFRESH] No refresh token available, cannot refresh");
49206
49262
  return;
49207
49263
  }
49208
49264
  try {
49209
49265
  const refreshToken = ctx.supabaseRefreshToken;
49210
49266
  console.error(`[JWT_REFRESH] Refreshing Supabase JWT (refreshToken=${refreshToken.slice(0, 12)}..., team=${ctx.teamId ?? "unknown"})`);
49211
- const res = await fetch(`${supabaseUrl}/auth/v1/token?grant_type=refresh_token`, {
49212
- method: "POST",
49213
- headers: {
49214
- "Content-Type": "application/json",
49215
- apikey: process.env.SUPABASE_ANON_KEY
49216
- },
49217
- body: JSON.stringify({ refresh_token: refreshToken })
49218
- });
49219
- if (!res.ok) {
49220
- const body = await res.text().catch(() => "");
49221
- console.error(`[JWT_REFRESH] FAIL: Supabase returned ${res.status} (refreshToken=${refreshToken.slice(0, 12)}...): ${body}`);
49267
+ const result = await refreshSupabaseJwtRaw(refreshToken);
49268
+ if (!result)
49222
49269
  return;
49223
- }
49224
- const data = await res.json();
49225
- ctx.supabaseJwt = data.access_token;
49226
- ctx.supabaseRefreshToken = data.refresh_token;
49227
- ctx.client.setBearerToken(data.access_token);
49270
+ ctx.supabaseJwt = result.jwt;
49271
+ ctx.supabaseRefreshToken = result.refreshToken;
49272
+ ctx.client.setBearerToken(result.jwt);
49228
49273
  try {
49229
49274
  await ctx.persist?.({
49230
49275
  supabaseJwt: ctx.supabaseJwt,
@@ -49234,9 +49279,11 @@ async function refreshSupabaseJwt(ctx) {
49234
49279
  } catch (e) {
49235
49280
  console.error("[JWT_REFRESH] WARN: persist failed, tokens updated in-memory only:", e);
49236
49281
  }
49237
- console.error(`[JWT_REFRESH] OK: token refreshed (team=${ctx.teamId ?? "unknown"}, newRefreshToken=${data.refresh_token.slice(0, 12)}...)`);
49238
- return data.access_token;
49282
+ console.error(`[JWT_REFRESH] OK: token refreshed (team=${ctx.teamId ?? "unknown"}, newRefreshToken=${result.refreshToken.slice(0, 12)}...)`);
49283
+ return result.jwt;
49239
49284
  } catch (error48) {
49285
+ if (error48 instanceof SessionExpiredError)
49286
+ throw error48;
49240
49287
  console.error("[JWT_REFRESH] FAIL: threw", error48);
49241
49288
  return;
49242
49289
  }
@@ -49257,9 +49304,16 @@ async function getValidJwt(ctx) {
49257
49304
  ctxRefreshMutex2.set(ctx, promise3);
49258
49305
  return promise3;
49259
49306
  }
49260
- var ctxRefreshMutex2;
49307
+ var SessionExpiredError, refreshRawMutex2, ctxRefreshMutex2;
49261
49308
  var init_client2 = __esm(() => {
49262
49309
  init_dist2();
49310
+ SessionExpiredError = class SessionExpiredError extends Error {
49311
+ constructor(message) {
49312
+ super(message ?? "Supabase session expired. Please re-authenticate.");
49313
+ this.name = "SessionExpiredError";
49314
+ }
49315
+ };
49316
+ refreshRawMutex2 = new Map;
49263
49317
  ctxRefreshMutex2 = new WeakMap;
49264
49318
  });
49265
49319
 
@@ -49380,6 +49434,10 @@ function registerTools(server, ctx) {
49380
49434
  }
49381
49435
  return await handler(...args);
49382
49436
  } catch (error48) {
49437
+ if (error48 instanceof SessionExpiredError) {
49438
+ console.error(`[Tool Error] ${name}: session expired, user must re-authenticate`);
49439
+ return errorResult("Your session has expired. Please reconnect the MCP server to re-authenticate.");
49440
+ }
49383
49441
  let message = classifyError(error48);
49384
49442
  if (KadoaHttpException.isInstance(error48) && error48.httpStatus === 403) {
49385
49443
  try {
@@ -49529,7 +49587,10 @@ function registerTools(server, ctx) {
49529
49587
  inputSchema: strictSchema({
49530
49588
  ...extractionInputShape,
49531
49589
  ...urlInputShape,
49532
- interval: exports_external.enum([
49590
+ description: exports_external.string().max(500).optional().describe("Description of what this workflow does (max 500 characters)"),
49591
+ tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
49592
+ limit: exports_external.number().optional().describe("Maximum number of records to extract per run. Useful for limiting scope or cost control."),
49593
+ updateInterval: exports_external.enum([
49533
49594
  "ONLY_ONCE",
49534
49595
  "EVERY_10_MINUTES",
49535
49596
  "HALF_HOURLY",
@@ -49545,8 +49606,10 @@ function registerTools(server, ctx) {
49545
49606
  "BIWEEKLY",
49546
49607
  "TRIWEEKLY",
49547
49608
  "FOUR_WEEKS",
49548
- "MONTHLY"
49549
- ]).optional().describe("How often the workflow runs. Defaults to ONLY_ONCE."),
49609
+ "MONTHLY",
49610
+ "CUSTOM"
49611
+ ]).optional().describe("How often the workflow runs. Defaults to ONLY_ONCE. Use CUSTOM with the 'schedules' field for cron-based scheduling."),
49612
+ schedules: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Cron expressions for CUSTOM updateInterval (e.g. '0 8 * * 2' for Tuesdays at 8am UTC). Requires updateInterval='CUSTOM'."),
49550
49613
  ...notificationsInputShape
49551
49614
  }),
49552
49615
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
@@ -49555,13 +49618,18 @@ function registerTools(server, ctx) {
49555
49618
  if (!urls) {
49556
49619
  return errorResult("At least one URL is required. Provide 'urls' (array) or 'url' (string).");
49557
49620
  }
49621
+ if (args.updateInterval === "CUSTOM" && (!args.schedules || args.schedules.length === 0)) {
49622
+ return errorResult("updateInterval='CUSTOM' requires at least one cron expression in the 'schedules' field (e.g. '0 8 * * 2' for Tuesdays at 8am UTC).");
49623
+ }
49558
49624
  let builder = ctx.client.extract({
49559
49625
  urls,
49560
49626
  name: args.name || "Untitled Workflow",
49561
49627
  navigationMode: "agentic-navigation",
49562
49628
  userPrompt: args.prompt,
49563
49629
  extraction: buildExtraction(args),
49564
- interval: args.interval
49630
+ interval: args.updateInterval,
49631
+ description: args.description,
49632
+ schedules: args.schedules
49565
49633
  });
49566
49634
  const n = args.notifications;
49567
49635
  const hasNotifications = n && (n.email || n.webhook || n.slack || n.websocket);
@@ -49572,6 +49640,15 @@ function registerTools(server, ctx) {
49572
49640
  });
49573
49641
  }
49574
49642
  const workflow = await builder.create();
49643
+ const needsUpdate = args.limit !== undefined || args.tags && args.tags.length > 0;
49644
+ if (needsUpdate) {
49645
+ const updates = {};
49646
+ if (args.limit !== undefined)
49647
+ updates.limit = args.limit;
49648
+ if (args.tags && args.tags.length > 0)
49649
+ updates.tags = args.tags;
49650
+ await ctx.client.workflow.update(workflow.workflowId, updates);
49651
+ }
49575
49652
  const enabledChannels = await describeNotifications(n);
49576
49653
  let message = "Workflow created successfully. The AI agent will start extracting data automatically.";
49577
49654
  if (enabledChannels.length > 0) {
@@ -49592,6 +49669,8 @@ function registerTools(server, ctx) {
49592
49669
  inputSchema: strictSchema({
49593
49670
  ...extractionInputShape,
49594
49671
  ...urlInputShape,
49672
+ description: exports_external.string().max(500).optional().describe("Description of what this monitor watches (max 500 characters)"),
49673
+ tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing monitors"),
49595
49674
  ...notificationsInputShape
49596
49675
  }),
49597
49676
  annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
@@ -49610,13 +49689,17 @@ function registerTools(server, ctx) {
49610
49689
  name: args.name || "Untitled Monitor",
49611
49690
  userPrompt: args.prompt,
49612
49691
  extraction: buildExtraction(args),
49613
- interval: "REAL_TIME"
49692
+ interval: "REAL_TIME",
49693
+ description: args.description
49614
49694
  });
49615
49695
  builder = builder.withNotifications({
49616
49696
  events: ["workflow_data_change"],
49617
49697
  channels: buildNotificationChannels(n)
49618
49698
  });
49619
49699
  const workflow = await builder.create();
49700
+ if (args.tags && args.tags.length > 0) {
49701
+ await ctx.client.workflow.update(workflow.workflowId, { tags: args.tags });
49702
+ }
49620
49703
  const enabledChannels = await describeNotifications(n);
49621
49704
  let message = "Real-time monitor created successfully. It will continuously watch for changes — no manual runs needed.";
49622
49705
  if (enabledChannels.length > 0) {
@@ -49785,7 +49868,7 @@ function registerTools(server, ctx) {
49785
49868
  urls: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).optional().describe("New target URLs for the workflow (array of strings). Also accepts a single URL string."),
49786
49869
  entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
49787
49870
  schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape))).optional().describe("New extraction schema fields"),
49788
- description: exports_external.string().optional().describe("Workflow description"),
49871
+ description: exports_external.string().max(500).optional().describe("Workflow description (max 500 characters)"),
49789
49872
  tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
49790
49873
  userPrompt: exports_external.string().optional().describe("Navigation prompt for agentic-navigation mode (10-5000 characters)"),
49791
49874
  updateInterval: exports_external.enum([
@@ -49824,6 +49907,9 @@ function registerTools(server, ctx) {
49824
49907
  return errorResult("Cannot change a real-time workflow's interval to a scheduled interval. " + "Real-time workflows are architecturally different and cannot be converted to regular workflows. " + "Delete this workflow and create a new one with the desired interval using create_workflow.");
49825
49908
  }
49826
49909
  }
49910
+ if (updates.updateInterval === "CUSTOM" && (!updates.schedules || updates.schedules.length === 0)) {
49911
+ return errorResult("updateInterval='CUSTOM' requires at least one cron expression in the 'schedules' field (e.g. '0 8 * * 2' for Tuesdays at 8am UTC).");
49912
+ }
49827
49913
  const result = await ctx.client.workflow.update(workflowId, updates);
49828
49914
  return jsonResult({
49829
49915
  success: true,
@@ -50097,7 +50183,7 @@ function registerTools(server, ctx) {
50097
50183
  });
50098
50184
  }));
50099
50185
  }
50100
- var SchemaFieldShape, DASHBOARD_BASE_URL = "https://app.kadoa.com";
50186
+ var SchemaFieldShape, DASHBOARD_BASE_URL = "https://www.kadoa.com";
50101
50187
  var init_tools = __esm(() => {
50102
50188
  init_zod();
50103
50189
  init_dist2();
@@ -54108,45 +54194,6 @@ function generatePKCE() {
54108
54194
  const challenge = createHash2("sha256").update(verifier).digest("base64url");
54109
54195
  return { verifier, challenge };
54110
54196
  }
54111
- async function refreshSupabaseToken(supabaseRefreshToken, context) {
54112
- const inflight = supabaseRefreshMutex.get(supabaseRefreshToken);
54113
- if (inflight) {
54114
- console.error(`[AUTH] REFRESH_DEDUP: reusing in-flight refresh (${context})`);
54115
- return inflight;
54116
- }
54117
- const promise3 = (async () => {
54118
- const supabaseUrl = process.env.SUPABASE_URL;
54119
- if (!supabaseUrl || !supabaseRefreshToken)
54120
- return null;
54121
- try {
54122
- const res = await fetch(`${supabaseUrl}/auth/v1/token?grant_type=refresh_token`, {
54123
- method: "POST",
54124
- headers: {
54125
- "Content-Type": "application/json",
54126
- apikey: process.env.SUPABASE_ANON_KEY
54127
- },
54128
- body: JSON.stringify({ refresh_token: supabaseRefreshToken })
54129
- });
54130
- if (res.ok) {
54131
- const data = await res.json();
54132
- const newClaims = jwtClaims(data.access_token);
54133
- console.log(`[AUTH] REFRESH_OK: Supabase JWT refreshed (${context}, newEmail=${newClaims.email})`);
54134
- return { jwt: data.access_token, refreshToken: data.refresh_token };
54135
- }
54136
- const body = await res.text().catch(() => "");
54137
- console.error(`[AUTH] REFRESH_FAIL: Supabase returned ${res.status} (${context}): ${body.slice(0, 200)}`);
54138
- return null;
54139
- } catch (err) {
54140
- console.error(`[AUTH] REFRESH_FAIL: Supabase refresh threw (${context}):`, err);
54141
- return null;
54142
- }
54143
- })();
54144
- supabaseRefreshMutex.set(supabaseRefreshToken, promise3);
54145
- promise3.finally(() => {
54146
- supabaseRefreshMutex.delete(supabaseRefreshToken);
54147
- });
54148
- return promise3;
54149
- }
54150
54197
  function jwtClaims(jwt2) {
54151
54198
  try {
54152
54199
  const payload = JSON.parse(Buffer.from(jwt2.split(".")[1], "base64url").toString());
@@ -54454,12 +54501,22 @@ class KadoaOAuthProvider {
54454
54501
  let { supabaseJwt, supabaseRefreshToken } = entry;
54455
54502
  const claims = jwtClaims(entry.supabaseJwt);
54456
54503
  const context = `email=${claims.email}, team=${entry.teamId}`;
54457
- const refreshed = await refreshSupabaseToken(supabaseRefreshToken, context);
54458
- if (refreshed) {
54459
- supabaseJwt = refreshed.jwt;
54460
- supabaseRefreshToken = refreshed.refreshToken;
54461
- } else {
54462
- console.error(`[AUTH] REFRESH_WARN: using stale Supabase JWT as fallback (${context})`);
54504
+ try {
54505
+ const { refreshSupabaseJwtRaw: refreshSupabaseJwtRaw2, SessionExpiredError: SessionExpiredError2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
54506
+ const refreshed = await refreshSupabaseJwtRaw2(supabaseRefreshToken);
54507
+ if (refreshed) {
54508
+ supabaseJwt = refreshed.jwt;
54509
+ supabaseRefreshToken = refreshed.refreshToken;
54510
+ console.error(`[AUTH] REFRESH_OK: Supabase JWT refreshed (${context})`);
54511
+ } else {
54512
+ console.error(`[AUTH] REFRESH_WARN: using stale Supabase JWT as fallback (${context})`);
54513
+ }
54514
+ } catch (error48) {
54515
+ if (error48 instanceof Error && error48.name === "SessionExpiredError") {
54516
+ console.error(`[AUTH] REFRESH_DEAD: session permanently expired (${context}): ${error48.message}`);
54517
+ throw new InvalidTokenError("Supabase session expired. Please re-authenticate.");
54518
+ }
54519
+ console.error(`[AUTH] REFRESH_WARN: unexpected error, using stale JWT (${context}):`, error48);
54463
54520
  }
54464
54521
  const freshClaims = jwtClaims(supabaseJwt);
54465
54522
  const teamId = freshClaims.activeTeamId ?? entry.teamId;
@@ -54586,7 +54643,7 @@ class KadoaOAuthProvider {
54586
54643
  codeChallenge: pending.params.codeChallenge,
54587
54644
  clientId: pending.client.client_id,
54588
54645
  redirectUri: pending.params.redirectUri,
54589
- expiresAt: Date.now() + 10 * 60 * 1000
54646
+ expiresAt: Date.now() + 600000
54590
54647
  }, 600);
54591
54648
  const redirectUrl = new URL(pending.params.redirectUri);
54592
54649
  redirectUrl.searchParams.set("code", mcpCode);
@@ -55015,12 +55072,11 @@ function renderLoginPage(state, error48) {
55015
55072
  function escapeHtml(str) {
55016
55073
  return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
55017
55074
  }
55018
- var TEAM_SELECTION_TTL, ACCESS_TOKEN_TTL, supabaseRefreshMutex;
55075
+ var TEAM_SELECTION_TTL, ACCESS_TOKEN_TTL;
55019
55076
  var init_auth2 = __esm(() => {
55020
55077
  init_errors4();
55021
55078
  TEAM_SELECTION_TTL = 10 * 60 * 1000;
55022
55079
  ACCESS_TOKEN_TTL = 7 * 24 * 3600;
55023
- supabaseRefreshMutex = new Map;
55024
55080
  });
55025
55081
 
55026
55082
  // src/redis-store.ts
@@ -55213,6 +55269,39 @@ async function startHttpServer(options) {
55213
55269
  return;
55214
55270
  }
55215
55271
  const identity = `jwt:${auth.userId.slice(0, 8)}...:team=${auth.teamId.slice(0, 8)}...`;
55272
+ if (isJwtExpired(auth.jwt)) {
55273
+ try {
55274
+ const refreshed = await refreshSupabaseJwtRaw(auth.refreshToken);
55275
+ if (refreshed) {
55276
+ auth.jwt = refreshed.jwt;
55277
+ auth.refreshToken = refreshed.refreshToken;
55278
+ const entry = await store.get("access_tokens", auth.mcpToken);
55279
+ if (entry) {
55280
+ const remainingMs = entry.expiresAt - Date.now();
55281
+ if (remainingMs > 0) {
55282
+ await store.set("access_tokens", auth.mcpToken, {
55283
+ ...entry,
55284
+ supabaseJwt: refreshed.jwt,
55285
+ supabaseRefreshToken: refreshed.refreshToken
55286
+ }, Math.ceil(remainingMs / 1000));
55287
+ console.error(`[PROACTIVE_REFRESH] OK: JWT refreshed on ${method} (${identity})`);
55288
+ }
55289
+ }
55290
+ }
55291
+ } catch (error48) {
55292
+ if (error48 instanceof SessionExpiredError) {
55293
+ console.error(`[PROACTIVE_REFRESH] Session dead on ${method} (${identity}): ${error48.message}`);
55294
+ await store.del("access_tokens", auth.mcpToken);
55295
+ res.status(401).json({
55296
+ jsonrpc: "2.0",
55297
+ error: { code: -32001, message: error48.message },
55298
+ id: req.body?.id ?? null
55299
+ });
55300
+ return;
55301
+ }
55302
+ console.error(`[PROACTIVE_REFRESH] WARN: refresh failed on ${method}, continuing with stale JWT`, error48);
55303
+ }
55304
+ }
55216
55305
  try {
55217
55306
  console.error(`[MCP] POST method=${method} auth=${identity}`);
55218
55307
  const transport = new StreamableHTTPServerTransport({
@@ -55290,6 +55379,7 @@ var init_http2 = __esm(async () => {
55290
55379
  init_bearerAuth();
55291
55380
  init_auth2();
55292
55381
  init_redis_store();
55382
+ init_client2();
55293
55383
  await init_src();
55294
55384
  });
55295
55385
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kadoa/mcp",
3
- "version": "0.3.10-rc.1",
3
+ "version": "0.3.10-rc.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",
@@ -24,7 +24,7 @@
24
24
  "prepublishOnly": "bun run check-types && bun run test:unit && bun run build"
25
25
  },
26
26
  "dependencies": {
27
- "@kadoa/node-sdk": "^0.24.2",
27
+ "@kadoa/node-sdk": "^0.23.0",
28
28
  "@modelcontextprotocol/sdk": "^1.26.0",
29
29
  "express": "^5.2.1",
30
30
  "ioredis": "^5.6.1",