integrate-sdk 0.5.7 → 0.5.9

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
@@ -26,44 +26,60 @@ npm install integrate-sdk
26
26
  bun add integrate-sdk
27
27
  ```
28
28
 
29
- ## Quick Start
29
+ ## Quick Start (2 Files Only!)
30
30
 
31
- ### Server-Side Setup
31
+ ### 1. Create Server Config
32
32
 
33
- First, create your server configuration with OAuth secrets:
33
+ Define your OAuth providers once:
34
34
 
35
35
  ```typescript
36
36
  // lib/integrate-server.ts (server-side only!)
37
- import { createMCPServer, githubPlugin, gmailPlugin } from 'integrate-sdk/server';
37
+ import {
38
+ createMCPServer,
39
+ githubPlugin,
40
+ gmailPlugin,
41
+ } from "integrate-sdk/server";
38
42
 
39
- export const { client: serverClient, handlers } = createMCPServer({
43
+ export const { client: serverClient } = createMCPServer({
40
44
  plugins: [
41
45
  githubPlugin({
42
46
  clientId: process.env.GITHUB_CLIENT_ID,
43
47
  clientSecret: process.env.GITHUB_CLIENT_SECRET,
44
- scopes: ['repo', 'user'],
48
+ scopes: ["repo", "user"],
45
49
  }),
46
50
  gmailPlugin({
47
51
  clientId: process.env.GMAIL_CLIENT_ID,
48
52
  clientSecret: process.env.GMAIL_CLIENT_SECRET,
49
- scopes: ['gmail.readonly'],
53
+ scopes: ["gmail.readonly"],
50
54
  }),
51
55
  ],
52
56
  });
53
57
  ```
54
58
 
55
- Create OAuth route (handles authorization automatically):
59
+ ### 2. Create Single Catch-All Route
60
+
61
+ That's it! Just import and export:
56
62
 
57
63
  ```typescript
58
- // app/api/integrate/oauth/[action]/route.ts
59
- export * from 'integrate-sdk/oauth';
64
+ // app/api/integrate/[...all]/route.ts
65
+ import { serverClient } from "@/lib/integrate-server";
66
+ import { toNextJsHandler } from "integrate-sdk/server";
67
+
68
+ export const { POST, GET } = toNextJsHandler({
69
+ client: serverClient, // Pass the client
70
+ redirectUrl: "/dashboard",
71
+ });
60
72
  ```
61
73
 
74
+ This imports your config from step 1 and handles ALL OAuth operations (authorize, callback, status, disconnect) in one file!
75
+
76
+ ### 3. Use in Your App
77
+
62
78
  Use the server client in API routes or server components:
63
79
 
64
80
  ```typescript
65
81
  // app/api/repos/route.ts
66
- import { serverClient } from '@/lib/integrate-server';
82
+ import { serverClient } from "@/lib/integrate-server";
67
83
 
68
84
  export async function GET() {
69
85
  // Automatically connects on first call - no manual setup needed!
@@ -77,34 +93,35 @@ export async function GET() {
77
93
  Use in your client components (no secrets needed):
78
94
 
79
95
  ```typescript
80
- 'use client';
81
- import { createMCPClient, githubPlugin } from 'integrate-sdk';
96
+ "use client";
97
+ import { createMCPClient, githubPlugin } from "integrate-sdk";
82
98
 
83
99
  const client = createMCPClient({
84
100
  plugins: [
85
101
  githubPlugin({
86
- scopes: ['repo', 'user'],
102
+ scopes: ["repo", "user"],
87
103
  // No clientId or clientSecret needed!
88
104
  }),
89
105
  ],
90
- oauthFlow: { mode: 'popup' },
106
+ oauthFlow: { mode: "popup" },
91
107
  });
92
108
 
93
109
  // Authorize user (opens popup)
94
- await client.authorize('github');
110
+ await client.authorize("github");
95
111
 
96
112
  // Use the client - automatically connects!
97
113
  const result = await client.github.createIssue({
98
- owner: 'owner',
99
- repo: 'repo',
100
- title: 'Bug report',
101
- body: 'Description of the bug',
114
+ owner: "owner",
115
+ repo: "repo",
116
+ title: "Bug report",
117
+ body: "Description of the bug",
102
118
  });
103
119
 
104
- console.log('Issue created:', result);
120
+ console.log("Issue created:", result);
105
121
  ```
106
122
 
107
123
  **That's it!** The SDK automatically:
124
+
108
125
  - ✅ Connects on first method call (no manual `connect()` needed)
109
126
  - ✅ Cleans up on exit (no manual `disconnect()` needed)
110
127
  - ✅ Manages OAuth tokens securely through your API routes
@@ -115,6 +132,7 @@ console.log('Issue created:', result);
115
132
  The SDK automatically manages connections for you - no manual `connect()` or `disconnect()` calls needed!
116
133
 
117
134
  **Features:**
135
+
118
136
  - **Lazy Connection**: Automatically connects on first method call
119
137
  - **Auto-Cleanup**: Cleans up on process exit
120
138
  - **Singleton Pattern**: Reuses connections efficiently (configurable)
@@ -124,25 +142,25 @@ The SDK automatically manages connections for you - no manual `connect()` or `di
124
142
  const client = createMCPClient({
125
143
  plugins: [
126
144
  githubPlugin({
127
- scopes: ['repo', 'user'],
145
+ scopes: ["repo", "user"],
128
146
  }),
129
147
  ],
130
148
  });
131
149
 
132
150
  // Use immediately - no connect() needed!
133
- await client.authorize('github');
134
- await client.github.listRepos({ username: 'octocat' });
151
+ await client.authorize("github");
152
+ await client.github.listRepos({ username: "octocat" });
135
153
 
136
154
  // ✅ Want manual control? Use manual mode
137
155
  const manualClient = createMCPClient({
138
- plugins: [githubPlugin({ scopes: ['repo'] })],
139
- connectionMode: 'manual',
156
+ plugins: [githubPlugin({ scopes: ["repo"] })],
157
+ connectionMode: "manual",
140
158
  singleton: false,
141
159
  });
142
160
 
143
161
  await manualClient.connect();
144
- await manualClient.authorize('github');
145
- await manualClient.github.listRepos({ username: 'octocat' });
162
+ await manualClient.authorize("github");
163
+ await manualClient.github.listRepos({ username: "octocat" });
146
164
  await manualClient.disconnect();
147
165
  ```
148
166
 
@@ -165,7 +183,11 @@ Instead of generic tool calls, use typed methods with full autocomplete:
165
183
 
166
184
  ```typescript
167
185
  // ✅ New: Typed methods with autocomplete
168
- await client.github.createIssue({ owner: "user", repo: "project", title: "Bug" });
186
+ await client.github.createIssue({
187
+ owner: "user",
188
+ repo: "project",
189
+ title: "Bug",
190
+ });
169
191
  await client.gmail.sendEmail({ to: "user@example.com", subject: "Hello" });
170
192
  ```
171
193
 
@@ -180,14 +202,21 @@ await client.gmail.sendEmail({ to: "user@example.com", subject: "Hello" });
180
202
 
181
203
  ```typescript
182
204
  // 1. Typed plugin methods (recommended for built-in plugins like GitHub/Gmail)
183
- await client.github.createIssue({ owner: "user", repo: "project", title: "Bug" });
205
+ await client.github.createIssue({
206
+ owner: "user",
207
+ repo: "project",
208
+ title: "Bug",
209
+ });
184
210
  await client.gmail.sendEmail({ to: "user@example.com", subject: "Hello" });
185
211
 
186
212
  // 2. Typed server methods (for server-level tools)
187
213
  await client.server.listToolsByIntegration({ integration: "github" });
188
214
 
189
215
  // 3. Direct tool calls (for other server-supported integrations)
190
- await client._callToolByName("slack_send_message", { channel: "#general", text: "Hello" });
216
+ await client._callToolByName("slack_send_message", {
217
+ channel: "#general",
218
+ text: "Hello",
219
+ });
191
220
  ```
192
221
 
193
222
  ## OAuth Authorization
@@ -195,16 +224,18 @@ await client._callToolByName("slack_send_message", { channel: "#general", text:
195
224
  The SDK implements OAuth 2.0 Authorization Code Flow with PKCE for secure authorization.
196
225
 
197
226
  **Key Features:**
227
+
198
228
  - ✅ Popup or redirect flow modes
199
229
  - ✅ Session token management
200
230
  - ✅ Multiple provider support
201
231
  - ✅ PKCE security
202
232
 
203
233
  **Basic Usage:**
234
+
204
235
  ```typescript
205
236
  // Check authorization
206
- if (!await client.isAuthorized('github')) {
207
- await client.authorize('github'); // Opens popup or redirects
237
+ if (!(await client.isAuthorized("github"))) {
238
+ await client.authorize("github"); // Opens popup or redirects
208
239
  }
209
240
 
210
241
  // Use authorized client
@@ -212,6 +243,7 @@ const repos = await client.github.listOwnRepos({});
212
243
  ```
213
244
 
214
245
  For complete OAuth setup including:
246
+
215
247
  - Popup vs redirect flows
216
248
  - Session token management
217
249
  - Multiple providers
@@ -227,9 +259,13 @@ Access GitHub repositories, issues, pull requests, and more with type-safe metho
227
259
 
228
260
  ```typescript
229
261
  // Available methods
230
- await client.github.getRepo({ owner: 'facebook', repo: 'react' });
231
- await client.github.createIssue({ owner: 'user', repo: 'repo', title: 'Bug' });
232
- await client.github.listPullRequests({ owner: 'user', repo: 'repo', state: 'open' });
262
+ await client.github.getRepo({ owner: "facebook", repo: "react" });
263
+ await client.github.createIssue({ owner: "user", repo: "repo", title: "Bug" });
264
+ await client.github.listPullRequests({
265
+ owner: "user",
266
+ repo: "repo",
267
+ state: "open",
268
+ });
233
269
  await client.github.listOwnRepos({});
234
270
  ```
235
271
 
@@ -241,9 +277,13 @@ Send emails, manage labels, and search messages with type-safe methods.
241
277
 
242
278
  ```typescript
243
279
  // Available methods
244
- await client.gmail.sendEmail({ to: 'user@example.com', subject: 'Hello', body: 'Hi!' });
245
- await client.gmail.listEmails({ maxResults: 10, q: 'is:unread' });
246
- await client.gmail.searchEmails({ query: 'from:notifications@github.com' });
280
+ await client.gmail.sendEmail({
281
+ to: "user@example.com",
282
+ subject: "Hello",
283
+ body: "Hi!",
284
+ });
285
+ await client.gmail.listEmails({ maxResults: 10, q: "is:unread" });
286
+ await client.gmail.searchEmails({ query: "from:notifications@github.com" });
247
287
  ```
248
288
 
249
289
  [→ Gmail plugin documentation](https://integrate.dev/docs/plugins/gmail)
@@ -253,15 +293,15 @@ await client.gmail.searchEmails({ query: 'from:notifications@github.com' });
253
293
  Use `genericOAuthPlugin` to configure any server-supported integration:
254
294
 
255
295
  ```typescript
256
- import { genericOAuthPlugin } from 'integrate-sdk/server';
296
+ import { genericOAuthPlugin } from "integrate-sdk/server";
257
297
 
258
298
  const slackPlugin = genericOAuthPlugin({
259
- id: 'slack',
260
- provider: 'slack',
299
+ id: "slack",
300
+ provider: "slack",
261
301
  clientId: process.env.SLACK_CLIENT_ID,
262
302
  clientSecret: process.env.SLACK_CLIENT_SECRET,
263
- scopes: ['chat:write', 'channels:read'],
264
- tools: ['slack_send_message', 'slack_list_channels'],
303
+ scopes: ["chat:write", "channels:read"],
304
+ tools: ["slack_send_message", "slack_list_channels"],
265
305
  });
266
306
  ```
267
307
 
package/dist/index.js CHANGED
@@ -148,6 +148,102 @@ var init_errors = __esm(() => {
148
148
  };
149
149
  });
150
150
 
151
+ // src/oauth/pkce.ts
152
+ var exports_pkce = {};
153
+ __export(exports_pkce, {
154
+ parseState: () => parseState,
155
+ generateStateWithReturnUrl: () => generateStateWithReturnUrl,
156
+ generateState: () => generateState,
157
+ generateCodeVerifier: () => generateCodeVerifier,
158
+ generateCodeChallenge: () => generateCodeChallenge
159
+ });
160
+ function generateCodeVerifier() {
161
+ const array = new Uint8Array(32);
162
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
163
+ crypto.getRandomValues(array);
164
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
165
+ globalThis.crypto.getRandomValues(array);
166
+ } else {
167
+ throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
168
+ }
169
+ return base64UrlEncode(array);
170
+ }
171
+ async function generateCodeChallenge(verifier) {
172
+ const encoder = new TextEncoder;
173
+ const data = encoder.encode(verifier);
174
+ let hashBuffer;
175
+ if (typeof crypto !== "undefined" && crypto.subtle) {
176
+ hashBuffer = await crypto.subtle.digest("SHA-256", data);
177
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
178
+ hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
179
+ } else {
180
+ throw new Error("crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.");
181
+ }
182
+ return base64UrlEncode(new Uint8Array(hashBuffer));
183
+ }
184
+ function generateState() {
185
+ const array = new Uint8Array(16);
186
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
187
+ crypto.getRandomValues(array);
188
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
189
+ globalThis.crypto.getRandomValues(array);
190
+ } else {
191
+ throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
192
+ }
193
+ return base64UrlEncode(array);
194
+ }
195
+ function generateStateWithReturnUrl(returnUrl) {
196
+ const csrf = generateState();
197
+ const stateData = returnUrl ? { csrf, returnUrl } : { csrf };
198
+ const encoder = new TextEncoder;
199
+ const jsonBytes = encoder.encode(JSON.stringify(stateData));
200
+ return base64UrlEncode(jsonBytes);
201
+ }
202
+ function parseState(state) {
203
+ try {
204
+ const decoded = base64UrlDecode(state);
205
+ const parsed = JSON.parse(decoded);
206
+ if (typeof parsed === "string") {
207
+ return { csrf: parsed };
208
+ } else if (parsed && typeof parsed === "object") {
209
+ return {
210
+ csrf: parsed.csrf || state,
211
+ returnUrl: parsed.returnUrl
212
+ };
213
+ }
214
+ return { csrf: state };
215
+ } catch {
216
+ return { csrf: state };
217
+ }
218
+ }
219
+ function base64UrlEncode(array) {
220
+ let base64 = "";
221
+ if (typeof Buffer !== "undefined") {
222
+ base64 = Buffer.from(array).toString("base64");
223
+ } else {
224
+ const binary = String.fromCharCode(...array);
225
+ base64 = btoa(binary);
226
+ }
227
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
228
+ }
229
+ function base64UrlDecode(str) {
230
+ let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
231
+ while (base64.length % 4 !== 0) {
232
+ base64 += "=";
233
+ }
234
+ if (typeof Buffer !== "undefined") {
235
+ return Buffer.from(base64, "base64").toString("utf-8");
236
+ } else {
237
+ const binary = atob(base64);
238
+ const bytes = new Uint8Array(binary.length);
239
+ for (let i = 0;i < binary.length; i++) {
240
+ bytes[i] = binary.charCodeAt(i);
241
+ }
242
+ const decoder = new TextDecoder;
243
+ return decoder.decode(bytes);
244
+ }
245
+ }
246
+
151
247
  // src/protocol/jsonrpc.ts
152
248
  function parseMessage(message) {
153
249
  try {
@@ -369,95 +465,6 @@ function methodToToolName(methodName, pluginId) {
369
465
  const snakeCaseMethod = camelToSnake(methodName);
370
466
  return `${pluginId}_${snakeCaseMethod}`;
371
467
  }
372
-
373
- // src/oauth/pkce.ts
374
- function generateCodeVerifier() {
375
- const array = new Uint8Array(32);
376
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
377
- crypto.getRandomValues(array);
378
- } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
379
- globalThis.crypto.getRandomValues(array);
380
- } else {
381
- throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
382
- }
383
- return base64UrlEncode(array);
384
- }
385
- async function generateCodeChallenge(verifier) {
386
- const encoder = new TextEncoder;
387
- const data = encoder.encode(verifier);
388
- let hashBuffer;
389
- if (typeof crypto !== "undefined" && crypto.subtle) {
390
- hashBuffer = await crypto.subtle.digest("SHA-256", data);
391
- } else if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
392
- hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
393
- } else {
394
- throw new Error("crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.");
395
- }
396
- return base64UrlEncode(new Uint8Array(hashBuffer));
397
- }
398
- function generateState() {
399
- const array = new Uint8Array(16);
400
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
401
- crypto.getRandomValues(array);
402
- } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
403
- globalThis.crypto.getRandomValues(array);
404
- } else {
405
- throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
406
- }
407
- return base64UrlEncode(array);
408
- }
409
- function generateStateWithReturnUrl(returnUrl) {
410
- const csrf = generateState();
411
- const stateData = returnUrl ? { csrf, returnUrl } : { csrf };
412
- const encoder = new TextEncoder;
413
- const jsonBytes = encoder.encode(JSON.stringify(stateData));
414
- return base64UrlEncode(jsonBytes);
415
- }
416
- function parseState(state) {
417
- try {
418
- const decoded = base64UrlDecode(state);
419
- const parsed = JSON.parse(decoded);
420
- if (typeof parsed === "string") {
421
- return { csrf: parsed };
422
- } else if (parsed && typeof parsed === "object") {
423
- return {
424
- csrf: parsed.csrf || state,
425
- returnUrl: parsed.returnUrl
426
- };
427
- }
428
- return { csrf: state };
429
- } catch {
430
- return { csrf: state };
431
- }
432
- }
433
- function base64UrlEncode(array) {
434
- let base64 = "";
435
- if (typeof Buffer !== "undefined") {
436
- base64 = Buffer.from(array).toString("base64");
437
- } else {
438
- const binary = String.fromCharCode(...array);
439
- base64 = btoa(binary);
440
- }
441
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
442
- }
443
- function base64UrlDecode(str) {
444
- let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
445
- while (base64.length % 4 !== 0) {
446
- base64 += "=";
447
- }
448
- if (typeof Buffer !== "undefined") {
449
- return Buffer.from(base64, "base64").toString("utf-8");
450
- } else {
451
- const binary = atob(base64);
452
- const bytes = new Uint8Array(binary.length);
453
- for (let i = 0;i < binary.length; i++) {
454
- bytes[i] = binary.charCodeAt(i);
455
- }
456
- const decoder = new TextDecoder;
457
- return decoder.decode(bytes);
458
- }
459
- }
460
-
461
468
  // src/oauth/window-manager.ts
462
469
  function isBrowser() {
463
470
  return typeof window !== "undefined" && typeof window.document !== "undefined";
@@ -1747,6 +1754,80 @@ function createNextOAuthHandler(config) {
1747
1754
  return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
1748
1755
  }
1749
1756
  };
1757
+ },
1758
+ toNextJsHandler(redirectConfig) {
1759
+ const defaultRedirectUrl = redirectConfig?.redirectUrl || "/";
1760
+ const errorRedirectUrl = redirectConfig?.errorRedirectUrl || "/auth-error";
1761
+ return {
1762
+ async POST(req, context) {
1763
+ const params = context.params instanceof Promise ? await context.params : context.params;
1764
+ const segments = params.all || [];
1765
+ if (segments.length === 2 && segments[0] === "oauth") {
1766
+ const action = segments[1];
1767
+ if (action === "authorize") {
1768
+ return handlers.authorize(req);
1769
+ }
1770
+ if (action === "callback") {
1771
+ return handlers.callback(req);
1772
+ }
1773
+ if (action === "disconnect") {
1774
+ return handlers.disconnect(req);
1775
+ }
1776
+ return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
1777
+ }
1778
+ return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
1779
+ },
1780
+ async GET(req, context) {
1781
+ const params = context.params instanceof Promise ? await context.params : context.params;
1782
+ const segments = params.all || [];
1783
+ if (segments.length === 2 && segments[0] === "oauth") {
1784
+ const action = segments[1];
1785
+ if (action === "status") {
1786
+ return handlers.status(req);
1787
+ }
1788
+ if (action === "callback") {
1789
+ const { searchParams } = new URL(req.url);
1790
+ const code = searchParams.get("code");
1791
+ const state = searchParams.get("state");
1792
+ const error = searchParams.get("error");
1793
+ const errorDescription = searchParams.get("error_description");
1794
+ if (error) {
1795
+ const errorMsg = errorDescription || error;
1796
+ console.error("[OAuth Redirect] Error:", errorMsg);
1797
+ return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent(errorMsg)}`, req.url));
1798
+ }
1799
+ if (!code || !state) {
1800
+ console.error("[OAuth Redirect] Missing code or state parameter");
1801
+ return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent("Invalid OAuth callback")}`, req.url));
1802
+ }
1803
+ let returnUrl = defaultRedirectUrl;
1804
+ try {
1805
+ const { parseState: parseState2 } = await Promise.resolve().then(() => exports_pkce);
1806
+ const stateData = parseState2(state);
1807
+ if (stateData.returnUrl) {
1808
+ returnUrl = stateData.returnUrl;
1809
+ }
1810
+ } catch (e) {
1811
+ try {
1812
+ const referrer = req.headers?.get?.("referer") || req.headers?.get?.("referrer");
1813
+ if (referrer) {
1814
+ const referrerUrl = new URL(referrer);
1815
+ const currentUrl = new URL(req.url);
1816
+ if (referrerUrl.origin === currentUrl.origin) {
1817
+ returnUrl = referrerUrl.pathname + referrerUrl.search;
1818
+ }
1819
+ }
1820
+ } catch {}
1821
+ }
1822
+ const targetUrl = new URL(returnUrl, req.url);
1823
+ targetUrl.hash = `oauth_callback=${encodeURIComponent(JSON.stringify({ code, state }))}`;
1824
+ return Response.redirect(targetUrl);
1825
+ }
1826
+ return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
1827
+ }
1828
+ return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
1829
+ }
1830
+ };
1750
1831
  }
1751
1832
  };
1752
1833
  return handlers;
package/dist/server.js CHANGED
@@ -148,6 +148,102 @@ var init_errors = __esm(() => {
148
148
  };
149
149
  });
150
150
 
151
+ // src/oauth/pkce.ts
152
+ var exports_pkce = {};
153
+ __export(exports_pkce, {
154
+ parseState: () => parseState,
155
+ generateStateWithReturnUrl: () => generateStateWithReturnUrl,
156
+ generateState: () => generateState,
157
+ generateCodeVerifier: () => generateCodeVerifier,
158
+ generateCodeChallenge: () => generateCodeChallenge
159
+ });
160
+ function generateCodeVerifier() {
161
+ const array = new Uint8Array(32);
162
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
163
+ crypto.getRandomValues(array);
164
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
165
+ globalThis.crypto.getRandomValues(array);
166
+ } else {
167
+ throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
168
+ }
169
+ return base64UrlEncode(array);
170
+ }
171
+ async function generateCodeChallenge(verifier) {
172
+ const encoder = new TextEncoder;
173
+ const data = encoder.encode(verifier);
174
+ let hashBuffer;
175
+ if (typeof crypto !== "undefined" && crypto.subtle) {
176
+ hashBuffer = await crypto.subtle.digest("SHA-256", data);
177
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
178
+ hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
179
+ } else {
180
+ throw new Error("crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.");
181
+ }
182
+ return base64UrlEncode(new Uint8Array(hashBuffer));
183
+ }
184
+ function generateState() {
185
+ const array = new Uint8Array(16);
186
+ if (typeof crypto !== "undefined" && crypto.getRandomValues) {
187
+ crypto.getRandomValues(array);
188
+ } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
189
+ globalThis.crypto.getRandomValues(array);
190
+ } else {
191
+ throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
192
+ }
193
+ return base64UrlEncode(array);
194
+ }
195
+ function generateStateWithReturnUrl(returnUrl) {
196
+ const csrf = generateState();
197
+ const stateData = returnUrl ? { csrf, returnUrl } : { csrf };
198
+ const encoder = new TextEncoder;
199
+ const jsonBytes = encoder.encode(JSON.stringify(stateData));
200
+ return base64UrlEncode(jsonBytes);
201
+ }
202
+ function parseState(state) {
203
+ try {
204
+ const decoded = base64UrlDecode(state);
205
+ const parsed = JSON.parse(decoded);
206
+ if (typeof parsed === "string") {
207
+ return { csrf: parsed };
208
+ } else if (parsed && typeof parsed === "object") {
209
+ return {
210
+ csrf: parsed.csrf || state,
211
+ returnUrl: parsed.returnUrl
212
+ };
213
+ }
214
+ return { csrf: state };
215
+ } catch {
216
+ return { csrf: state };
217
+ }
218
+ }
219
+ function base64UrlEncode(array) {
220
+ let base64 = "";
221
+ if (typeof Buffer !== "undefined") {
222
+ base64 = Buffer.from(array).toString("base64");
223
+ } else {
224
+ const binary = String.fromCharCode(...array);
225
+ base64 = btoa(binary);
226
+ }
227
+ return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
228
+ }
229
+ function base64UrlDecode(str) {
230
+ let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
231
+ while (base64.length % 4 !== 0) {
232
+ base64 += "=";
233
+ }
234
+ if (typeof Buffer !== "undefined") {
235
+ return Buffer.from(base64, "base64").toString("utf-8");
236
+ } else {
237
+ const binary = atob(base64);
238
+ const bytes = new Uint8Array(binary.length);
239
+ for (let i = 0;i < binary.length; i++) {
240
+ bytes[i] = binary.charCodeAt(i);
241
+ }
242
+ const decoder = new TextDecoder;
243
+ return decoder.decode(bytes);
244
+ }
245
+ }
246
+
151
247
  // src/protocol/jsonrpc.ts
152
248
  function parseMessage(message) {
153
249
  try {
@@ -369,95 +465,6 @@ function methodToToolName(methodName, pluginId) {
369
465
  const snakeCaseMethod = camelToSnake(methodName);
370
466
  return `${pluginId}_${snakeCaseMethod}`;
371
467
  }
372
-
373
- // src/oauth/pkce.ts
374
- function generateCodeVerifier() {
375
- const array = new Uint8Array(32);
376
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
377
- crypto.getRandomValues(array);
378
- } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
379
- globalThis.crypto.getRandomValues(array);
380
- } else {
381
- throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
382
- }
383
- return base64UrlEncode(array);
384
- }
385
- async function generateCodeChallenge(verifier) {
386
- const encoder = new TextEncoder;
387
- const data = encoder.encode(verifier);
388
- let hashBuffer;
389
- if (typeof crypto !== "undefined" && crypto.subtle) {
390
- hashBuffer = await crypto.subtle.digest("SHA-256", data);
391
- } else if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
392
- hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
393
- } else {
394
- throw new Error("crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.");
395
- }
396
- return base64UrlEncode(new Uint8Array(hashBuffer));
397
- }
398
- function generateState() {
399
- const array = new Uint8Array(16);
400
- if (typeof crypto !== "undefined" && crypto.getRandomValues) {
401
- crypto.getRandomValues(array);
402
- } else if (typeof globalThis !== "undefined" && globalThis.crypto) {
403
- globalThis.crypto.getRandomValues(array);
404
- } else {
405
- throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
406
- }
407
- return base64UrlEncode(array);
408
- }
409
- function generateStateWithReturnUrl(returnUrl) {
410
- const csrf = generateState();
411
- const stateData = returnUrl ? { csrf, returnUrl } : { csrf };
412
- const encoder = new TextEncoder;
413
- const jsonBytes = encoder.encode(JSON.stringify(stateData));
414
- return base64UrlEncode(jsonBytes);
415
- }
416
- function parseState(state) {
417
- try {
418
- const decoded = base64UrlDecode(state);
419
- const parsed = JSON.parse(decoded);
420
- if (typeof parsed === "string") {
421
- return { csrf: parsed };
422
- } else if (parsed && typeof parsed === "object") {
423
- return {
424
- csrf: parsed.csrf || state,
425
- returnUrl: parsed.returnUrl
426
- };
427
- }
428
- return { csrf: state };
429
- } catch {
430
- return { csrf: state };
431
- }
432
- }
433
- function base64UrlEncode(array) {
434
- let base64 = "";
435
- if (typeof Buffer !== "undefined") {
436
- base64 = Buffer.from(array).toString("base64");
437
- } else {
438
- const binary = String.fromCharCode(...array);
439
- base64 = btoa(binary);
440
- }
441
- return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
442
- }
443
- function base64UrlDecode(str) {
444
- let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
445
- while (base64.length % 4 !== 0) {
446
- base64 += "=";
447
- }
448
- if (typeof Buffer !== "undefined") {
449
- return Buffer.from(base64, "base64").toString("utf-8");
450
- } else {
451
- const binary = atob(base64);
452
- const bytes = new Uint8Array(binary.length);
453
- for (let i = 0;i < binary.length; i++) {
454
- bytes[i] = binary.charCodeAt(i);
455
- }
456
- const decoder = new TextDecoder;
457
- return decoder.decode(bytes);
458
- }
459
- }
460
-
461
468
  // src/oauth/window-manager.ts
462
469
  function isBrowser() {
463
470
  return typeof window !== "undefined" && typeof window.document !== "undefined";
@@ -1749,6 +1756,80 @@ function createNextOAuthHandler(config) {
1749
1756
  return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
1750
1757
  }
1751
1758
  };
1759
+ },
1760
+ toNextJsHandler(redirectConfig) {
1761
+ const defaultRedirectUrl = redirectConfig?.redirectUrl || "/";
1762
+ const errorRedirectUrl = redirectConfig?.errorRedirectUrl || "/auth-error";
1763
+ return {
1764
+ async POST(req, context) {
1765
+ const params = context.params instanceof Promise ? await context.params : context.params;
1766
+ const segments = params.all || [];
1767
+ if (segments.length === 2 && segments[0] === "oauth") {
1768
+ const action = segments[1];
1769
+ if (action === "authorize") {
1770
+ return handlers.authorize(req);
1771
+ }
1772
+ if (action === "callback") {
1773
+ return handlers.callback(req);
1774
+ }
1775
+ if (action === "disconnect") {
1776
+ return handlers.disconnect(req);
1777
+ }
1778
+ return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
1779
+ }
1780
+ return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
1781
+ },
1782
+ async GET(req, context) {
1783
+ const params = context.params instanceof Promise ? await context.params : context.params;
1784
+ const segments = params.all || [];
1785
+ if (segments.length === 2 && segments[0] === "oauth") {
1786
+ const action = segments[1];
1787
+ if (action === "status") {
1788
+ return handlers.status(req);
1789
+ }
1790
+ if (action === "callback") {
1791
+ const { searchParams } = new URL(req.url);
1792
+ const code = searchParams.get("code");
1793
+ const state = searchParams.get("state");
1794
+ const error = searchParams.get("error");
1795
+ const errorDescription = searchParams.get("error_description");
1796
+ if (error) {
1797
+ const errorMsg = errorDescription || error;
1798
+ console.error("[OAuth Redirect] Error:", errorMsg);
1799
+ return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent(errorMsg)}`, req.url));
1800
+ }
1801
+ if (!code || !state) {
1802
+ console.error("[OAuth Redirect] Missing code or state parameter");
1803
+ return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent("Invalid OAuth callback")}`, req.url));
1804
+ }
1805
+ let returnUrl = defaultRedirectUrl;
1806
+ try {
1807
+ const { parseState: parseState2 } = await Promise.resolve().then(() => exports_pkce);
1808
+ const stateData = parseState2(state);
1809
+ if (stateData.returnUrl) {
1810
+ returnUrl = stateData.returnUrl;
1811
+ }
1812
+ } catch (e) {
1813
+ try {
1814
+ const referrer = req.headers?.get?.("referer") || req.headers?.get?.("referrer");
1815
+ if (referrer) {
1816
+ const referrerUrl = new URL(referrer);
1817
+ const currentUrl = new URL(req.url);
1818
+ if (referrerUrl.origin === currentUrl.origin) {
1819
+ returnUrl = referrerUrl.pathname + referrerUrl.search;
1820
+ }
1821
+ }
1822
+ } catch {}
1823
+ }
1824
+ const targetUrl = new URL(returnUrl, req.url);
1825
+ targetUrl.hash = `oauth_callback=${encodeURIComponent(JSON.stringify({ code, state }))}`;
1826
+ return Response.redirect(targetUrl);
1827
+ }
1828
+ return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
1829
+ }
1830
+ return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
1831
+ }
1832
+ };
1752
1833
  }
1753
1834
  };
1754
1835
  return handlers;
@@ -1911,6 +1992,7 @@ function createMCPServer(config) {
1911
1992
  singleton: config.singleton ?? true
1912
1993
  };
1913
1994
  const client = new MCPClient(clientConfig);
1995
+ client.__oauthConfig = { providers };
1914
1996
  const { POST, GET } = createOAuthRouteHandlers({ providers });
1915
1997
  return {
1916
1998
  client,
@@ -1938,7 +2020,35 @@ var GET = async (req, context) => {
1938
2020
  const routes = handler.createRoutes();
1939
2021
  return routes.GET(req, context);
1940
2022
  };
2023
+ function toNextJsHandler(options) {
2024
+ const POST2 = async (req, context) => {
2025
+ const config = options.config || options.client?.__oauthConfig;
2026
+ if (!config) {
2027
+ return Response.json({ error: 'OAuth not configured. You must pass either "client" (from createMCPServer) or "config" to toNextJsHandler().' }, { status: 500 });
2028
+ }
2029
+ const handler = createNextOAuthHandler(config);
2030
+ const routes = handler.toNextJsHandler({
2031
+ redirectUrl: options.redirectUrl,
2032
+ errorRedirectUrl: options.errorRedirectUrl
2033
+ });
2034
+ return routes.POST(req, context);
2035
+ };
2036
+ const GET2 = async (req, context) => {
2037
+ const config = options.config || options.client?.__oauthConfig;
2038
+ if (!config) {
2039
+ return Response.json({ error: 'OAuth not configured. You must pass either "client" (from createMCPServer) or "config" to toNextJsHandler().' }, { status: 500 });
2040
+ }
2041
+ const handler = createNextOAuthHandler(config);
2042
+ const routes = handler.toNextJsHandler({
2043
+ redirectUrl: options.redirectUrl,
2044
+ errorRedirectUrl: options.errorRedirectUrl
2045
+ });
2046
+ return routes.GET(req, context);
2047
+ };
2048
+ return { POST: POST2, GET: GET2 };
2049
+ }
1941
2050
  export {
2051
+ toNextJsHandler,
1942
2052
  gmailPlugin,
1943
2053
  githubPlugin,
1944
2054
  genericOAuthPlugin,
@@ -265,6 +265,68 @@ export declare function createNextOAuthHandler(config: OAuthHandlerConfig): {
265
265
  }>;
266
266
  }): Promise<NextResponse>;
267
267
  };
268
+ /**
269
+ * Create unified catch-all route handler
270
+ *
271
+ * This is the simplest way to set up OAuth routes - create a single catch-all
272
+ * route file that handles ALL OAuth actions including provider redirects.
273
+ *
274
+ * @param redirectConfig - Configuration for OAuth redirect behavior
275
+ * @returns Object with POST and GET handlers for Next.js catch-all routes
276
+ *
277
+ * @example
278
+ * ```typescript
279
+ * // app/api/integrate/[...all]/route.ts
280
+ * import { createNextOAuthHandler } from 'integrate-sdk';
281
+ *
282
+ * const handler = createNextOAuthHandler({
283
+ * providers: {
284
+ * github: {
285
+ * clientId: process.env.GITHUB_CLIENT_ID!,
286
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
287
+ * },
288
+ * },
289
+ * });
290
+ *
291
+ * export const { POST, GET } = handler.toNextJsHandler({
292
+ * redirectUrl: '/',
293
+ * });
294
+ * ```
295
+ *
296
+ * This single route file handles:
297
+ * - POST /api/integrate/oauth/authorize - Get authorization URL
298
+ * - POST /api/integrate/oauth/callback - Exchange code for token
299
+ * - GET /api/integrate/oauth/callback - Provider OAuth redirect
300
+ * - GET /api/integrate/oauth/status - Check authorization status
301
+ * - POST /api/integrate/oauth/disconnect - Disconnect provider
302
+ */
303
+ toNextJsHandler(redirectConfig?: {
304
+ /** URL to redirect to after OAuth callback (default: '/') */
305
+ redirectUrl?: string;
306
+ /** URL to redirect to on OAuth error (default: '/auth-error') */
307
+ errorRedirectUrl?: string;
308
+ }): {
309
+ /**
310
+ * POST handler for authorize, callback, and disconnect actions
311
+ */
312
+ POST(req: NextRequest, context: {
313
+ params: {
314
+ all: string[];
315
+ } | Promise<{
316
+ all: string[];
317
+ }>;
318
+ }): Promise<NextResponse>;
319
+ /**
320
+ * GET handler for status action and OAuth provider redirects
321
+ */
322
+ GET(req: NextRequest, context: {
323
+ params: {
324
+ all: string[];
325
+ } | Promise<{
326
+ all: string[];
327
+ }>;
328
+ }): Promise<NextResponse>;
329
+ };
268
330
  };
269
331
  export {};
270
332
  //# sourceMappingURL=nextjs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../../src/adapters/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG1E,KAAK,WAAW,GAAG,GAAG,CAAC;AACvB,KAAK,YAAY,GAAG,GAAG,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,kBAAkB;IAI7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;mBACkB,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAcxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;kBACiB,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAcvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;gBACe,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IA+BrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;oBACmB,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAiCzD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;;QAGC;;WAEG;kBAEI,WAAW,WACP;YAAE,MAAM,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GACpE,OAAO,CAAC,YAAY,CAAC;QAuBxB;;WAEG;iBAEI,WAAW,WACP;YAAE,MAAM,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GACpE,OAAO,CAAC,YAAY,CAAC;;EAmB/B"}
1
+ {"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../../../src/adapters/nextjs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG1E,KAAK,WAAW,GAAG,GAAG,CAAC;AACvB,KAAK,YAAY,GAAG,GAAG,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,kBAAkB;IAI7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAwCG;mBACkB,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAcxD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;kBACiB,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAcvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;gBACe,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IA+BrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;oBACmB,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC;IAiCzD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;;QAGC;;WAEG;kBAEI,WAAW,WACP;YAAE,MAAM,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GACpE,OAAO,CAAC,YAAY,CAAC;QAuBxB;;WAEG;iBAEI,WAAW,WACP;YAAE,MAAM,EAAE;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,GAAG,OAAO,CAAC;gBAAE,MAAM,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAAE,GACpE,OAAO,CAAC,YAAY,CAAC;;IAiB5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;qCAC8B;QAC/B,6DAA6D;QAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,iEAAiE;QACjE,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B;QAKG;;WAEG;kBAEI,WAAW,WACP;YAAE,MAAM,EAAE;gBAAE,GAAG,EAAE,MAAM,EAAE,CAAA;aAAE,GAAG,OAAO,CAAC;gBAAE,GAAG,EAAE,MAAM,EAAE,CAAA;aAAE,CAAC,CAAA;SAAE,GAClE,OAAO,CAAC,YAAY,CAAC;QAiCxB;;WAEG;iBAEI,WAAW,WACP;YAAE,MAAM,EAAE;gBAAE,GAAG,EAAE,MAAM,EAAE,CAAA;aAAE,GAAG,OAAO,CAAC;gBAAE,GAAG,EAAE,MAAM,EAAE,CAAA;aAAE,CAAC,CAAA;SAAE,GAClE,OAAO,CAAC,YAAY,CAAC;;EA+F/B"}
@@ -121,4 +121,84 @@ export declare const GET: (req: any, context: {
121
121
  action: string;
122
122
  }>;
123
123
  }) => Promise<any>;
124
+ /**
125
+ * Create catch-all route handlers from the global server configuration
126
+ *
127
+ * This is a helper function to create POST and GET handlers for catch-all routes
128
+ * that use the configuration from createMCPServer().
129
+ *
130
+ * @param redirectConfig - Optional configuration for OAuth redirect behavior
131
+ * @returns Object with POST and GET handlers for Next.js catch-all routes
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * // lib/integrate-server.ts
136
+ * import { createMCPServer, githubPlugin } from 'integrate-sdk/server';
137
+ *
138
+ * export const { client: serverClient } = createMCPServer({
139
+ * plugins: [
140
+ * githubPlugin({
141
+ * clientId: process.env.GITHUB_CLIENT_ID!,
142
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
143
+ * scopes: ['repo', 'user'],
144
+ * }),
145
+ * ],
146
+ * });
147
+ *
148
+ * // app/api/integrate/[...all]/route.ts
149
+ *
150
+ * // RECOMMENDED: Import serverClient from your server setup file
151
+ * import { serverClient } from '@/lib/integrate-server';
152
+ * import { toNextJsHandler } from 'integrate-sdk/server';
153
+ *
154
+ * export const { POST, GET } = toNextJsHandler({
155
+ * client: serverClient, // Pass the client from createMCPServer
156
+ * redirectUrl: '/dashboard',
157
+ * });
158
+ *
159
+ * // Alternative: Provide config inline
160
+ * export const { POST, GET } = toNextJsHandler({
161
+ * config: {
162
+ * providers: {
163
+ * github: {
164
+ * clientId: process.env.GITHUB_CLIENT_ID!,
165
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
166
+ * },
167
+ * },
168
+ * },
169
+ * redirectUrl: '/dashboard',
170
+ * });
171
+ * ```
172
+ */
173
+ export declare function toNextJsHandler(options: {
174
+ /** Server client instance from createMCPServer (extracts config automatically) */
175
+ client?: any;
176
+ /** Custom OAuth handler config (provide inline) */
177
+ config?: {
178
+ providers: Record<string, {
179
+ clientId: string;
180
+ clientSecret: string;
181
+ redirectUri?: string;
182
+ }>;
183
+ };
184
+ /** URL to redirect to after successful OAuth */
185
+ redirectUrl?: string;
186
+ /** URL to redirect to on OAuth error */
187
+ errorRedirectUrl?: string;
188
+ }): {
189
+ POST: (req: any, context: {
190
+ params: {
191
+ all: string[];
192
+ } | Promise<{
193
+ all: string[];
194
+ }>;
195
+ }) => Promise<any>;
196
+ GET: (req: any, context: {
197
+ params: {
198
+ all: string[];
199
+ } | Promise<{
200
+ all: string[];
201
+ }>;
202
+ }) => Promise<any>;
203
+ };
124
204
  //# sourceMappingURL=server.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAyCpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,eAAe,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE,EACnE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC;IAmE/B,2DAA2D;;IAG3D,4DAA4D;;;;;;;;IAG5D,2DAA2D;;;;;;;;EAG9D;AAYD,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GACf,KAAK,GAAG,EACR,SAAS;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,iBAYtE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,GAAG,GACd,KAAK,GAAG,EACR,SAAS;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,iBAYtE,CAAC"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAyCpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,wBAAgB,eAAe,CAAC,QAAQ,SAAS,SAAS,SAAS,EAAE,EACnE,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC;IAsE/B,2DAA2D;;IAG3D,4DAA4D;;;;;;;;IAG5D,2DAA2D;;;;;;;;EAG9D;AAYD,YAAY,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE9E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,IAAI,GACf,KAAK,GAAG,EACR,SAAS;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,iBAYtE,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,GAAG,GACd,KAAK,GAAG,EACR,SAAS;IAAE,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,iBAYtE,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,kFAAkF;IAClF,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,mDAAmD;IACnD,MAAM,CAAC,EAAE;QACP,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE;YACxB,QAAQ,EAAE,MAAM,CAAC;YACjB,YAAY,EAAE,MAAM,CAAC;YACrB,WAAW,CAAC,EAAE,MAAM,CAAC;SACtB,CAAC,CAAC;KACJ,CAAC;IACF,gDAAgD;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wCAAwC;IACxC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;gBAMQ,GAAG,WACC;QAAE,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,EAAE,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,GAAG,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAA;KAAE;eAwB9D,GAAG,WACC;QAAE,MAAM,EAAE;YAAE,GAAG,EAAE,MAAM,EAAE,CAAA;SAAE,GAAG,OAAO,CAAC;YAAE,GAAG,EAAE,MAAM,EAAE,CAAA;SAAE,CAAC,CAAA;KAAE;EAoBtE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "integrate-sdk",
3
- "version": "0.5.7",
3
+ "version": "0.5.9",
4
4
  "description": "Type-safe TypeScript SDK for MCP Client with plugin-based OAuth provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",