integrate-sdk 0.7.48 → 0.7.49

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 (34) hide show
  1. package/dist/adapters/auto-routes.d.ts.map +1 -1
  2. package/dist/adapters/auto-routes.js +380 -24
  3. package/dist/adapters/base-handler.d.ts +50 -6
  4. package/dist/adapters/base-handler.d.ts.map +1 -1
  5. package/dist/adapters/base-handler.js +368 -18
  6. package/dist/adapters/context-cookie.d.ts +85 -0
  7. package/dist/adapters/context-cookie.d.ts.map +1 -0
  8. package/dist/adapters/context-cookie.js +152 -0
  9. package/dist/adapters/index.js +399 -37
  10. package/dist/adapters/nextjs.d.ts.map +1 -1
  11. package/dist/adapters/nextjs.js +387 -31
  12. package/dist/adapters/node.d.ts.map +1 -1
  13. package/dist/adapters/node.js +380 -24
  14. package/dist/adapters/session-detector.d.ts +37 -0
  15. package/dist/adapters/session-detector.d.ts.map +1 -0
  16. package/dist/adapters/session-detector.js +157 -0
  17. package/dist/adapters/solid-start.js +387 -31
  18. package/dist/adapters/svelte-kit.js +387 -31
  19. package/dist/index.js +392 -30
  20. package/dist/oauth.js +380 -24
  21. package/dist/server.js +401 -33
  22. package/dist/src/adapters/auto-routes.d.ts.map +1 -1
  23. package/dist/src/adapters/base-handler.d.ts +50 -6
  24. package/dist/src/adapters/base-handler.d.ts.map +1 -1
  25. package/dist/src/adapters/context-cookie.d.ts +85 -0
  26. package/dist/src/adapters/context-cookie.d.ts.map +1 -0
  27. package/dist/src/adapters/nextjs.d.ts.map +1 -1
  28. package/dist/src/adapters/node.d.ts.map +1 -1
  29. package/dist/src/adapters/session-detector.d.ts +37 -0
  30. package/dist/src/adapters/session-detector.d.ts.map +1 -0
  31. package/dist/src/config/types.d.ts +24 -0
  32. package/dist/src/config/types.d.ts.map +1 -1
  33. package/dist/src/server.d.ts.map +1 -1
  34. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"auto-routes.d.ts","sourceRoot":"","sources":["../../../src/adapters/auto-routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQ1E;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,kBAAkB,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;;GAiBG;AAkBH;;;GAGG;AACH,wBAAsB,IAAI,CACxB,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACvC,OAAO,CAAC,GAAG,CAAC,CAgDd;AAED;;;GAGG;AACH,wBAAsB,GAAG,CACvB,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACvC,OAAO,CAAC,GAAG,CAAC,CAoCd"}
1
+ {"version":3,"file":"auto-routes.d.ts","sourceRoot":"","sources":["../../../src/adapters/auto-routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAQ1E;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CAErE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,kBAAkB,GAAG,IAAI,CAEhE;AAED;;;;;;;;;;;;;;;;;GAiBG;AAkBH;;;GAGG;AACH,wBAAsB,IAAI,CACxB,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACvC,OAAO,CAAC,GAAG,CAAC,CA8Dd;AAED;;;GAGG;AACH,wBAAsB,GAAG,CACvB,GAAG,EAAE,GAAG,EACR,OAAO,CAAC,EAAE;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACvC,OAAO,CAAC,GAAG,CAAC,CAoCd"}
@@ -10,6 +10,280 @@ var __export = (target, all) => {
10
10
  };
11
11
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
12
 
13
+ // session-detector.ts
14
+ var exports_session_detector = {};
15
+ __export(exports_session_detector, {
16
+ tryDecodeJWT: () => tryDecodeJWT,
17
+ detectSessionContext: () => detectSessionContext
18
+ });
19
+ function tryDecodeJWT(token) {
20
+ try {
21
+ const parts = token.split(".");
22
+ if (parts.length !== 3) {
23
+ return;
24
+ }
25
+ const payloadPart = parts[1];
26
+ if (!payloadPart) {
27
+ return;
28
+ }
29
+ const base64 = payloadPart.replace(/-/g, "+").replace(/_/g, "/");
30
+ const jsonPayload = decodeURIComponent(atob(base64).split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join(""));
31
+ return JSON.parse(jsonPayload);
32
+ } catch (error) {
33
+ return;
34
+ }
35
+ }
36
+ function getCookies(request) {
37
+ const cookies = new Map;
38
+ const cookieHeader = request.headers.get("cookie");
39
+ if (!cookieHeader) {
40
+ return cookies;
41
+ }
42
+ const pairs = cookieHeader.split(";");
43
+ for (const pair of pairs) {
44
+ const [name, ...valueParts] = pair.split("=");
45
+ if (name && valueParts.length > 0) {
46
+ const trimmedName = name.trim();
47
+ const value = valueParts.join("=").trim();
48
+ cookies.set(trimmedName, value);
49
+ }
50
+ }
51
+ return cookies;
52
+ }
53
+ function tryBetterAuth(cookies) {
54
+ const sessionToken = cookies.get("better-auth.session_token");
55
+ if (!sessionToken) {
56
+ return;
57
+ }
58
+ const payload = tryDecodeJWT(sessionToken);
59
+ if (!payload) {
60
+ return;
61
+ }
62
+ const userId = payload.sub || payload.userId || payload.user_id || payload.id;
63
+ if (!userId) {
64
+ return;
65
+ }
66
+ return {
67
+ userId,
68
+ sessionId: payload.jti || payload.sessionId
69
+ };
70
+ }
71
+ function tryNextAuth(cookies) {
72
+ const sessionToken = cookies.get("__Secure-next-auth.session-token") || cookies.get("next-auth.session-token");
73
+ if (!sessionToken) {
74
+ return;
75
+ }
76
+ if (sessionToken.includes(".")) {
77
+ const payload = tryDecodeJWT(sessionToken);
78
+ if (payload) {
79
+ return {
80
+ userId: payload.sub || payload.userId || payload.user_id || payload.id,
81
+ sessionId: payload.jti
82
+ };
83
+ }
84
+ }
85
+ return;
86
+ }
87
+ function tryClerk(cookies) {
88
+ const sessionToken = cookies.get("__session");
89
+ if (!sessionToken) {
90
+ return;
91
+ }
92
+ const payload = tryDecodeJWT(sessionToken);
93
+ if (!payload) {
94
+ return;
95
+ }
96
+ return {
97
+ userId: payload.sub || payload.userId,
98
+ organizationId: payload.org_id || payload.organizationId,
99
+ sessionId: payload.sid || payload.sessionId
100
+ };
101
+ }
102
+ function tryLucia(cookies) {
103
+ const sessionToken = cookies.get("lucia_session");
104
+ if (!sessionToken) {
105
+ return;
106
+ }
107
+ return {
108
+ sessionId: sessionToken
109
+ };
110
+ }
111
+ function tryGenericSession(cookies) {
112
+ const sessionToken = cookies.get("auth_session") || cookies.get("session");
113
+ if (!sessionToken) {
114
+ return;
115
+ }
116
+ if (sessionToken.includes(".")) {
117
+ const payload = tryDecodeJWT(sessionToken);
118
+ if (payload) {
119
+ return {
120
+ userId: payload.sub || payload.userId || payload.user_id || payload.id,
121
+ sessionId: payload.jti || payload.sessionId || payload.sid
122
+ };
123
+ }
124
+ }
125
+ return {
126
+ sessionId: sessionToken
127
+ };
128
+ }
129
+ async function detectSessionContext(request) {
130
+ const cookies = getCookies(request);
131
+ let context;
132
+ context = tryBetterAuth(cookies);
133
+ if (context?.userId) {
134
+ return context;
135
+ }
136
+ context = tryNextAuth(cookies);
137
+ if (context?.userId) {
138
+ return context;
139
+ }
140
+ context = tryClerk(cookies);
141
+ if (context?.userId) {
142
+ return context;
143
+ }
144
+ context = tryLucia(cookies);
145
+ if (context?.userId) {
146
+ return context;
147
+ }
148
+ context = tryGenericSession(cookies);
149
+ if (context?.userId) {
150
+ return context;
151
+ }
152
+ return;
153
+ }
154
+
155
+ // context-cookie.ts
156
+ var exports_context_cookie = {};
157
+ __export(exports_context_cookie, {
158
+ readContextCookie: () => readContextCookie,
159
+ getSetCookieHeader: () => getSetCookieHeader,
160
+ getContextCookieFromRequest: () => getContextCookieFromRequest,
161
+ getClearCookieHeader: () => getClearCookieHeader,
162
+ createContextCookie: () => createContextCookie,
163
+ CONTEXT_COOKIE_NAME: () => CONTEXT_COOKIE_NAME,
164
+ CONTEXT_COOKIE_MAX_AGE: () => CONTEXT_COOKIE_MAX_AGE
165
+ });
166
+ async function deriveKey(secret) {
167
+ const encoder = new TextEncoder;
168
+ const secretData = encoder.encode(secret);
169
+ const keyMaterial = await crypto.subtle.importKey("raw", secretData, { name: "PBKDF2" }, false, ["deriveBits", "deriveKey"]);
170
+ const salt = encoder.encode("integrate-oauth-context-v1");
171
+ return await crypto.subtle.deriveKey({
172
+ name: "PBKDF2",
173
+ salt,
174
+ iterations: 1e5,
175
+ hash: "SHA-256"
176
+ }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
177
+ }
178
+ async function encryptPayload(payload, secret) {
179
+ const key = await deriveKey(secret);
180
+ const iv = crypto.getRandomValues(new Uint8Array(12));
181
+ const encoder = new TextEncoder;
182
+ const data = encoder.encode(JSON.stringify(payload));
183
+ const encrypted = await crypto.subtle.encrypt({
184
+ name: "AES-GCM",
185
+ iv
186
+ }, key, data);
187
+ const combined = new Uint8Array(iv.length + encrypted.byteLength);
188
+ combined.set(iv, 0);
189
+ combined.set(new Uint8Array(encrypted), iv.length);
190
+ return base64UrlEncode(combined);
191
+ }
192
+ async function decryptPayload(cookieValue, secret) {
193
+ try {
194
+ const combined = base64UrlDecode(cookieValue);
195
+ const iv = combined.slice(0, 12);
196
+ const encrypted = combined.slice(12);
197
+ const key = await deriveKey(secret);
198
+ const decrypted = await crypto.subtle.decrypt({
199
+ name: "AES-GCM",
200
+ iv
201
+ }, key, encrypted);
202
+ const decoder = new TextDecoder;
203
+ const json = decoder.decode(decrypted);
204
+ const payload = JSON.parse(json);
205
+ const age = Date.now() - payload.timestamp;
206
+ if (age > CONTEXT_COOKIE_MAX_AGE * 1000) {
207
+ return;
208
+ }
209
+ return payload;
210
+ } catch (error) {
211
+ return;
212
+ }
213
+ }
214
+ function base64UrlEncode(data) {
215
+ const base64 = btoa(String.fromCharCode(...data));
216
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
217
+ }
218
+ function base64UrlDecode(str) {
219
+ let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
220
+ const padding = base64.length % 4;
221
+ if (padding) {
222
+ base64 += "=".repeat(4 - padding);
223
+ }
224
+ const binary = atob(base64);
225
+ const bytes = new Uint8Array(binary.length);
226
+ for (let i = 0;i < binary.length; i++) {
227
+ bytes[i] = binary.charCodeAt(i);
228
+ }
229
+ return bytes;
230
+ }
231
+ async function createContextCookie(context, provider, secret) {
232
+ const payload = {
233
+ context,
234
+ provider,
235
+ timestamp: Date.now()
236
+ };
237
+ return await encryptPayload(payload, secret);
238
+ }
239
+ async function readContextCookie(cookieValue, secret) {
240
+ const payload = await decryptPayload(cookieValue, secret);
241
+ if (!payload) {
242
+ return;
243
+ }
244
+ return {
245
+ context: payload.context,
246
+ provider: payload.provider
247
+ };
248
+ }
249
+ function getSetCookieHeader(cookieValue, maxAge = CONTEXT_COOKIE_MAX_AGE) {
250
+ const attributes = [
251
+ `${CONTEXT_COOKIE_NAME}=${cookieValue}`,
252
+ `Max-Age=${maxAge}`,
253
+ "HttpOnly",
254
+ "Secure",
255
+ "SameSite=Lax",
256
+ "Path=/"
257
+ ];
258
+ return attributes.join("; ");
259
+ }
260
+ function getClearCookieHeader() {
261
+ const attributes = [
262
+ `${CONTEXT_COOKIE_NAME}=`,
263
+ "Max-Age=0",
264
+ "HttpOnly",
265
+ "Secure",
266
+ "SameSite=Lax",
267
+ "Path=/"
268
+ ];
269
+ return attributes.join("; ");
270
+ }
271
+ function getContextCookieFromRequest(request) {
272
+ const cookieHeader = request.headers.get("cookie");
273
+ if (!cookieHeader) {
274
+ return;
275
+ }
276
+ const cookies = cookieHeader.split(";");
277
+ for (const cookie of cookies) {
278
+ const [name, ...valueParts] = cookie.split("=");
279
+ if (name && name.trim() === CONTEXT_COOKIE_NAME) {
280
+ return valueParts.join("=").trim();
281
+ }
282
+ }
283
+ return;
284
+ }
285
+ var CONTEXT_COOKIE_NAME = "__integrate_oauth_ctx", CONTEXT_COOKIE_MAX_AGE = 300;
286
+
13
287
  // base-handler.ts
14
288
  class OAuthHandler {
15
289
  config;
@@ -33,25 +307,35 @@ class OAuthHandler {
33
307
  return headers;
34
308
  }
35
309
  async handleAuthorize(request) {
36
- const providerConfig = this.config.providers[request.provider];
310
+ let webRequest;
311
+ let authorizeRequest;
312
+ if (request instanceof Request) {
313
+ webRequest = request;
314
+ authorizeRequest = await request.json();
315
+ } else if (typeof request === "object" && "json" in request && typeof request.json === "function") {
316
+ authorizeRequest = await request.json();
317
+ } else {
318
+ authorizeRequest = request;
319
+ }
320
+ const providerConfig = this.config.providers[authorizeRequest.provider];
37
321
  if (!providerConfig) {
38
- throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
322
+ throw new Error(`Provider ${authorizeRequest.provider} not configured. Add OAuth credentials to your API route configuration.`);
39
323
  }
40
324
  if (!providerConfig.clientId || !providerConfig.clientSecret) {
41
- throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
325
+ throw new Error(`Missing OAuth credentials for ${authorizeRequest.provider}. Check your environment variables.`);
42
326
  }
43
327
  const url = new URL("/oauth/authorize", this.serverUrl);
44
- url.searchParams.set("provider", request.provider);
328
+ url.searchParams.set("provider", authorizeRequest.provider);
45
329
  url.searchParams.set("client_id", providerConfig.clientId);
46
330
  url.searchParams.set("client_secret", providerConfig.clientSecret);
47
- const scopes = request.scopes || providerConfig.scopes || [];
331
+ const scopes = authorizeRequest.scopes || providerConfig.scopes || [];
48
332
  if (scopes.length > 0) {
49
333
  url.searchParams.set("scope", scopes.join(","));
50
334
  }
51
- url.searchParams.set("state", request.state);
52
- url.searchParams.set("code_challenge", request.codeChallenge);
53
- url.searchParams.set("code_challenge_method", request.codeChallengeMethod);
54
- const redirectUri = request.redirectUri || providerConfig.redirectUri;
335
+ url.searchParams.set("state", authorizeRequest.state);
336
+ url.searchParams.set("code_challenge", authorizeRequest.codeChallenge);
337
+ url.searchParams.set("code_challenge_method", authorizeRequest.codeChallengeMethod);
338
+ const redirectUri = authorizeRequest.redirectUri || providerConfig.redirectUri;
55
339
  if (redirectUri) {
56
340
  url.searchParams.set("redirect_uri", redirectUri);
57
341
  }
@@ -64,15 +348,62 @@ class OAuthHandler {
64
348
  throw new Error(`MCP server failed to generate authorization URL: ${error}`);
65
349
  }
66
350
  const data = await response.json();
67
- return data;
351
+ const result = data;
352
+ if (webRequest) {
353
+ try {
354
+ const { detectSessionContext: detectSessionContext2 } = await Promise.resolve().then(() => exports_session_detector);
355
+ const { createContextCookie: createContextCookie2, getSetCookieHeader: getSetCookieHeader2 } = await Promise.resolve().then(() => exports_context_cookie);
356
+ let context;
357
+ if (this.config.getSessionContext) {
358
+ context = await this.config.getSessionContext(webRequest);
359
+ }
360
+ if (!context || !context.userId) {
361
+ context = await detectSessionContext2(webRequest);
362
+ }
363
+ if (context && context.userId) {
364
+ const secret = this.apiKey || providerConfig.clientSecret;
365
+ const cookieValue = await createContextCookie2(context, authorizeRequest.provider, secret);
366
+ result.setCookie = getSetCookieHeader2(cookieValue);
367
+ }
368
+ } catch (error) {
369
+ console.warn("[OAuth] Failed to capture user context:", error);
370
+ }
371
+ }
372
+ return result;
68
373
  }
69
374
  async handleCallback(request) {
70
- const providerConfig = this.config.providers[request.provider];
375
+ let webRequest;
376
+ let callbackRequest;
377
+ if (request instanceof Request) {
378
+ webRequest = request;
379
+ callbackRequest = await request.json();
380
+ } else if (typeof request === "object" && "json" in request && typeof request.json === "function") {
381
+ callbackRequest = await request.json();
382
+ } else {
383
+ callbackRequest = request;
384
+ }
385
+ const providerConfig = this.config.providers[callbackRequest.provider];
71
386
  if (!providerConfig) {
72
- throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
387
+ throw new Error(`Provider ${callbackRequest.provider} not configured. Add OAuth credentials to your API route configuration.`);
73
388
  }
74
389
  if (!providerConfig.clientId || !providerConfig.clientSecret) {
75
- throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
390
+ throw new Error(`Missing OAuth credentials for ${callbackRequest.provider}. Check your environment variables.`);
391
+ }
392
+ let context;
393
+ if (webRequest) {
394
+ try {
395
+ const { getContextCookieFromRequest: getContextCookieFromRequest2, readContextCookie: readContextCookie2 } = await Promise.resolve().then(() => exports_context_cookie);
396
+ const cookieValue = getContextCookieFromRequest2(webRequest);
397
+ if (cookieValue) {
398
+ const secret = this.apiKey || providerConfig.clientSecret;
399
+ const contextData = await readContextCookie2(cookieValue, secret);
400
+ if (contextData && contextData.provider === callbackRequest.provider) {
401
+ context = contextData.context;
402
+ }
403
+ }
404
+ } catch (error) {
405
+ console.warn("[OAuth] Failed to restore user context:", error);
406
+ }
76
407
  }
77
408
  const url = new URL("/oauth/callback", this.serverUrl);
78
409
  const response = await fetch(url.toString(), {
@@ -81,10 +412,10 @@ class OAuthHandler {
81
412
  "Content-Type": "application/json"
82
413
  }),
83
414
  body: JSON.stringify({
84
- provider: request.provider,
85
- code: request.code,
86
- code_verifier: request.codeVerifier,
87
- state: request.state,
415
+ provider: callbackRequest.provider,
416
+ code: callbackRequest.code,
417
+ code_verifier: callbackRequest.codeVerifier,
418
+ state: callbackRequest.state,
88
419
  client_id: providerConfig.clientId,
89
420
  client_secret: providerConfig.clientSecret,
90
421
  redirect_uri: providerConfig.redirectUri
@@ -95,7 +426,26 @@ class OAuthHandler {
95
426
  throw new Error(`MCP server failed to exchange authorization code: ${error}`);
96
427
  }
97
428
  const data = await response.json();
98
- return data;
429
+ const result = data;
430
+ if (this.config.setProviderToken && context) {
431
+ try {
432
+ const tokenData = {
433
+ accessToken: result.accessToken,
434
+ refreshToken: result.refreshToken,
435
+ tokenType: result.tokenType,
436
+ expiresIn: result.expiresIn,
437
+ expiresAt: result.expiresAt
438
+ };
439
+ await this.config.setProviderToken(callbackRequest.provider, tokenData, context);
440
+ } catch (error) {
441
+ console.error("[OAuth] Failed to save provider token:", error);
442
+ }
443
+ }
444
+ if (webRequest) {
445
+ const { getClearCookieHeader: getClearCookieHeader2 } = await Promise.resolve().then(() => exports_context_cookie);
446
+ result.clearCookie = getClearCookieHeader2();
447
+ }
448
+ return result;
99
449
  }
100
450
  async handleStatus(provider, accessToken) {
101
451
  const url = new URL("/oauth/status", this.serverUrl);
@@ -197,14 +547,20 @@ async function POST(req, context) {
197
547
  }
198
548
  try {
199
549
  if (action === "authorize") {
200
- const body = await parseRequestBody(req);
201
- const result = await handler.handleAuthorize(body);
202
- return createSuccessResponse(result);
550
+ const result = await handler.handleAuthorize(req);
551
+ const response = createSuccessResponse(result);
552
+ if (result.setCookie) {
553
+ response.headers?.set?.("Set-Cookie", result.setCookie);
554
+ }
555
+ return response;
203
556
  }
204
557
  if (action === "callback") {
205
- const body = await parseRequestBody(req);
206
- const result = await handler.handleCallback(body);
207
- return createSuccessResponse(result);
558
+ const result = await handler.handleCallback(req);
559
+ const response = createSuccessResponse(result);
560
+ if (result.clearCookie) {
561
+ response.headers?.set?.("Set-Cookie", result.clearCookie);
562
+ }
563
+ return response;
208
564
  }
209
565
  if (action === "disconnect") {
210
566
  const body = await parseRequestBody(req);
@@ -2,6 +2,8 @@
2
2
  * Base OAuth Handler
3
3
  * Framework-agnostic OAuth route logic for secure server-side token management
4
4
  */
5
+ import type { MCPContext } from '../config/types.js';
6
+ import type { ProviderTokenData } from '../oauth/types.js';
5
7
  /**
6
8
  * OAuth handler configuration
7
9
  * OAuth credentials for each provider
@@ -28,6 +30,42 @@ export interface OAuthHandlerConfig {
28
30
  * Sent as X-API-KEY header with all OAuth requests to the MCP server
29
31
  */
30
32
  apiKey?: string;
33
+ /**
34
+ * Optional callback to extract user context from request
35
+ * If not provided, SDK will attempt to auto-detect from common auth libraries
36
+ *
37
+ * @param request - Web Request object
38
+ * @returns User context (userId, organizationId, etc.) or undefined
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * getSessionContext: async (req) => {
43
+ * const session = await getMyAuthSession(req);
44
+ * return { userId: session.userId };
45
+ * }
46
+ * ```
47
+ */
48
+ getSessionContext?: (request: Request) => Promise<MCPContext | undefined> | MCPContext | undefined;
49
+ /**
50
+ * Optional callback to save provider tokens with user context
51
+ * Called automatically after successful OAuth callback
52
+ *
53
+ * @param provider - Provider name (e.g., 'github')
54
+ * @param tokenData - OAuth tokens (accessToken, refreshToken, etc.)
55
+ * @param context - User context (userId, organizationId, etc.)
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * setProviderToken: async (provider, tokens, context) => {
60
+ * await db.tokens.upsert({
61
+ * where: { provider_userId: { provider, userId: context.userId } },
62
+ * create: { provider, userId: context.userId, ...tokens },
63
+ * update: tokens,
64
+ * });
65
+ * }
66
+ * ```
67
+ */
68
+ setProviderToken?: (provider: string, tokenData: ProviderTokenData, context?: MCPContext) => Promise<void> | void;
31
69
  }
32
70
  /**
33
71
  * Request body for authorize endpoint
@@ -45,6 +83,8 @@ export interface AuthorizeRequest {
45
83
  */
46
84
  export interface AuthorizeResponse {
47
85
  authorizationUrl: string;
86
+ /** Optional Set-Cookie header value for context cookie */
87
+ setCookie?: string;
48
88
  }
49
89
  /**
50
90
  * Request body for callback endpoint
@@ -65,6 +105,8 @@ export interface CallbackResponse {
65
105
  expiresIn: number;
66
106
  expiresAt?: string;
67
107
  scopes?: string[];
108
+ /** Optional Set-Cookie header value to clear context cookie */
109
+ clearCookie?: string;
68
110
  }
69
111
  /**
70
112
  * Response from status endpoint
@@ -127,25 +169,27 @@ export declare class OAuthHandler {
127
169
  /**
128
170
  * Handle authorization URL request
129
171
  * Gets authorization URL from MCP server with full OAuth credentials
172
+ * Also captures user context for later use in callback
130
173
  *
131
- * @param request - Authorization request from client
132
- * @returns Authorization URL to redirect/open for user
174
+ * @param request - Authorization request from client OR full Web Request object
175
+ * @returns Authorization URL to redirect/open for user, plus optional context cookie
133
176
  *
134
177
  * @throws Error if provider is not configured
135
178
  * @throws Error if MCP server request fails
136
179
  */
137
- handleAuthorize(request: AuthorizeRequest): Promise<AuthorizeResponse>;
180
+ handleAuthorize(request: AuthorizeRequest | Request): Promise<AuthorizeResponse>;
138
181
  /**
139
182
  * Handle OAuth callback
140
183
  * Exchanges authorization code for access token
184
+ * Also restores user context and saves tokens if callback is configured
141
185
  *
142
- * @param request - Callback request with authorization code
143
- * @returns Access token and authorization details
186
+ * @param request - Callback request with authorization code OR full Web Request object
187
+ * @returns Access token and authorization details, plus cookie clear header
144
188
  *
145
189
  * @throws Error if provider is not configured
146
190
  * @throws Error if MCP server request fails
147
191
  */
148
- handleCallback(request: CallbackRequest): Promise<CallbackResponse>;
192
+ handleCallback(request: CallbackRequest | Request): Promise<CallbackResponse>;
149
193
  /**
150
194
  * Handle authorization status check
151
195
  * Checks if a provider access token is valid
@@ -1 +1 @@
1
- {"version":3,"file":"base-handler.d.ts","sourceRoot":"","sources":["../../../src/adapters/base-handler.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-handler.d.ts","sourceRoot":"","sources":["../../../src/adapters/base-handler.ts"],"names":[],"mappings":"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"}