@kadoa/mcp 0.3.7-rc.1 → 0.3.7-rc.3

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 +46 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -49154,6 +49154,15 @@ async function refreshSupabaseJwt(ctx) {
49154
49154
  ctx.supabaseJwt = data.access_token;
49155
49155
  ctx.supabaseRefreshToken = data.refresh_token;
49156
49156
  ctx.client.setBearerToken(data.access_token);
49157
+ try {
49158
+ await ctx.persist?.({
49159
+ supabaseJwt: ctx.supabaseJwt,
49160
+ supabaseRefreshToken: ctx.supabaseRefreshToken,
49161
+ teamId: ctx.teamId
49162
+ });
49163
+ } catch (e) {
49164
+ console.error("[JWT_REFRESH] WARN: persist failed, tokens updated in-memory only:", e);
49165
+ }
49157
49166
  console.error(`[JWT_REFRESH] OK: token refreshed (team=${ctx.teamId ?? "unknown"}, newRefreshToken=${data.refresh_token.slice(0, 12)}...)`);
49158
49167
  return data.access_token;
49159
49168
  } catch (error48) {
@@ -49990,11 +49999,11 @@ function registerTools(server, ctx) {
49990
49999
  return errorResult(`Team not found: "${identifier}". Available teams: ${teams.map((t) => t.name).join(", ")}`);
49991
50000
  }
49992
50001
  await ctx.client.setActiveTeam(match.id);
50002
+ ctx.teamId = match.id;
49993
50003
  const newJwt = await refreshSupabaseJwt(ctx);
49994
50004
  if (!newJwt) {
49995
50005
  return errorResult("Failed to refresh session after team switch");
49996
50006
  }
49997
- ctx.teamId = match.id;
49998
50007
  const config2 = loadConfig2();
49999
50008
  config2.teamId = match.id;
50000
50009
  config2.teamName = match.name;
@@ -54060,7 +54069,11 @@ async function refreshSupabaseToken(supabaseRefreshToken, context) {
54060
54069
  function jwtClaims(jwt2) {
54061
54070
  try {
54062
54071
  const payload = JSON.parse(Buffer.from(jwt2.split(".")[1], "base64url").toString());
54063
- return { email: payload.email, sub: payload.sub };
54072
+ return {
54073
+ email: payload.email,
54074
+ sub: payload.sub,
54075
+ activeTeamId: payload.app_metadata?.active_team_id
54076
+ };
54064
54077
  } catch {
54065
54078
  return {};
54066
54079
  }
@@ -54367,20 +54380,22 @@ class KadoaOAuthProvider {
54367
54380
  } else {
54368
54381
  console.error(`[AUTH] REFRESH_WARN: using stale Supabase JWT as fallback (${context})`);
54369
54382
  }
54383
+ const freshClaims = jwtClaims(supabaseJwt);
54384
+ const teamId = freshClaims.activeTeamId ?? entry.teamId;
54370
54385
  const newAccessToken = randomToken();
54371
54386
  const newRefreshToken = randomToken();
54372
54387
  const expiresAt = Date.now() + ACCESS_TOKEN_TTL * 1000;
54373
54388
  await this.store.set("access_tokens", newAccessToken, {
54374
54389
  supabaseJwt,
54375
54390
  supabaseRefreshToken,
54376
- teamId: entry.teamId,
54391
+ teamId,
54377
54392
  clientId: entry.clientId,
54378
54393
  expiresAt
54379
54394
  }, ACCESS_TOKEN_TTL);
54380
54395
  await this.store.set("refresh_tokens", newRefreshToken, {
54381
54396
  supabaseJwt,
54382
54397
  supabaseRefreshToken,
54383
- teamId: entry.teamId,
54398
+ teamId,
54384
54399
  clientId: entry.clientId
54385
54400
  }, 2592000);
54386
54401
  return {
@@ -55075,17 +55090,18 @@ function resolveAuth(req) {
55075
55090
  jwt: extra.supabaseJwt,
55076
55091
  refreshToken: extra.supabaseRefreshToken ?? "",
55077
55092
  teamId: extra.teamId ?? "",
55078
- userId
55093
+ userId,
55094
+ mcpToken: req.auth.token
55079
55095
  };
55080
55096
  }
55081
55097
  console.error(`[AUTH_RESOLVE] FAIL: no apiKey or supabaseJwt in extra (keys: ${Object.keys(extra).join(", ")})`);
55082
55098
  return;
55083
55099
  }
55084
- async function startHttpServer() {
55100
+ async function startHttpServer(options) {
55085
55101
  const port = parseInt(process.env.PORT || "3000", 10);
55086
55102
  const app = createMcpExpressApp({ host: "0.0.0.0" });
55087
55103
  app.set("trust proxy", 1);
55088
- const store = new RedisTokenStore;
55104
+ const store = options?.store ?? new RedisTokenStore;
55089
55105
  const provider = new KadoaOAuthProvider(store);
55090
55106
  const serverUrl = process.env.MCP_SERVER_URL || `http://localhost:${port}`;
55091
55107
  app.use(mcpAuthRouter({
@@ -55137,7 +55153,27 @@ async function startHttpServer() {
55137
55153
  const server = auth.kind === "jwt" ? createServer({
55138
55154
  jwt: auth.jwt,
55139
55155
  refreshToken: auth.refreshToken,
55140
- teamId: auth.teamId
55156
+ teamId: auth.teamId,
55157
+ persist: async (state) => {
55158
+ const entry = await store.get("access_tokens", auth.mcpToken);
55159
+ if (!entry) {
55160
+ console.error(`[PERSIST] WARN: access token gone from store (token=${auth.mcpToken.slice(0, 12)}...)`);
55161
+ return;
55162
+ }
55163
+ const remainingMs = entry.expiresAt - Date.now();
55164
+ if (remainingMs <= 0) {
55165
+ console.error(`[PERSIST] WARN: access token already expired, skipping persist`);
55166
+ return;
55167
+ }
55168
+ const ttlSeconds = Math.ceil(remainingMs / 1000);
55169
+ await store.set("access_tokens", auth.mcpToken, {
55170
+ ...entry,
55171
+ supabaseJwt: state.supabaseJwt ?? entry.supabaseJwt,
55172
+ supabaseRefreshToken: state.supabaseRefreshToken ?? entry.supabaseRefreshToken,
55173
+ teamId: state.teamId ?? entry.teamId
55174
+ }, ttlSeconds);
55175
+ console.error(`[PERSIST] OK: updated access token in store (token=${auth.mcpToken.slice(0, 12)}..., team=${state.teamId ?? "unchanged"}, ttl=${ttlSeconds}s)`);
55176
+ }
55141
55177
  }) : createServer({ apiKey: auth.apiKey });
55142
55178
  await server.connect(transport);
55143
55179
  await transport.handleRequest(req, res, req.body);
@@ -55197,7 +55233,8 @@ function createServer(auth) {
55197
55233
  client: createKadoaClient({ jwt: auth.jwt }),
55198
55234
  supabaseJwt: auth.jwt,
55199
55235
  supabaseRefreshToken: auth.refreshToken,
55200
- teamId: auth.teamId
55236
+ teamId: auth.teamId,
55237
+ persist: auth.persist
55201
55238
  };
55202
55239
  } else if (typeof auth === "object" && auth !== null && "apiKey" in auth) {
55203
55240
  ctx = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kadoa/mcp",
3
- "version": "0.3.7-rc.1",
3
+ "version": "0.3.7-rc.3",
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",