integrate-sdk 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/auto-routes.js +1 -2
- package/dist/adapters/base-handler.js +1 -2
- package/dist/adapters/nextjs.js +97 -98
- package/dist/adapters/node.js +1 -2
- package/dist/adapters/solid-start.js +165 -206
- package/dist/adapters/svelte-kit.js +165 -206
- package/dist/index.js +187 -206
- package/dist/oauth.js +5 -1
- package/dist/server.js +187 -207
- package/dist/src/client.d.ts +0 -6
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/server.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -11,8 +11,6 @@ var __export = (target, all) => {
|
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
13
|
// src/adapters/base-handler.ts
|
|
14
|
-
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
15
|
-
|
|
16
14
|
class OAuthHandler {
|
|
17
15
|
config;
|
|
18
16
|
serverUrl;
|
|
@@ -175,6 +173,7 @@ class OAuthHandler {
|
|
|
175
173
|
return jsonRpcResponse.result;
|
|
176
174
|
}
|
|
177
175
|
}
|
|
176
|
+
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
178
177
|
|
|
179
178
|
// src/adapters/auto-routes.ts
|
|
180
179
|
var globalOAuthConfig = null;
|
|
@@ -11,8 +11,6 @@ var __export = (target, all) => {
|
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
13
|
// src/adapters/base-handler.ts
|
|
14
|
-
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
15
|
-
|
|
16
14
|
class OAuthHandler {
|
|
17
15
|
config;
|
|
18
16
|
serverUrl;
|
|
@@ -175,6 +173,7 @@ class OAuthHandler {
|
|
|
175
173
|
return jsonRpcResponse.result;
|
|
176
174
|
}
|
|
177
175
|
}
|
|
176
|
+
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
178
177
|
export {
|
|
179
178
|
OAuthHandler
|
|
180
179
|
};
|
package/dist/adapters/nextjs.js
CHANGED
|
@@ -10,105 +10,7 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
|
-
// src/oauth/pkce.ts
|
|
14
|
-
var exports_pkce = {};
|
|
15
|
-
__export(exports_pkce, {
|
|
16
|
-
parseState: () => parseState,
|
|
17
|
-
generateStateWithReturnUrl: () => generateStateWithReturnUrl,
|
|
18
|
-
generateState: () => generateState,
|
|
19
|
-
generateCodeVerifier: () => generateCodeVerifier,
|
|
20
|
-
generateCodeChallenge: () => generateCodeChallenge
|
|
21
|
-
});
|
|
22
|
-
function generateCodeVerifier() {
|
|
23
|
-
const array = new Uint8Array(32);
|
|
24
|
-
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
25
|
-
crypto.getRandomValues(array);
|
|
26
|
-
} else if (typeof globalThis !== "undefined" && globalThis.crypto) {
|
|
27
|
-
globalThis.crypto.getRandomValues(array);
|
|
28
|
-
} else {
|
|
29
|
-
throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
|
|
30
|
-
}
|
|
31
|
-
return base64UrlEncode(array);
|
|
32
|
-
}
|
|
33
|
-
async function generateCodeChallenge(verifier) {
|
|
34
|
-
const encoder = new TextEncoder;
|
|
35
|
-
const data = encoder.encode(verifier);
|
|
36
|
-
let hashBuffer;
|
|
37
|
-
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
38
|
-
hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
39
|
-
} else if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
|
|
40
|
-
hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
41
|
-
} else {
|
|
42
|
-
throw new Error("crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.");
|
|
43
|
-
}
|
|
44
|
-
return base64UrlEncode(new Uint8Array(hashBuffer));
|
|
45
|
-
}
|
|
46
|
-
function generateState() {
|
|
47
|
-
const array = new Uint8Array(16);
|
|
48
|
-
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
49
|
-
crypto.getRandomValues(array);
|
|
50
|
-
} else if (typeof globalThis !== "undefined" && globalThis.crypto) {
|
|
51
|
-
globalThis.crypto.getRandomValues(array);
|
|
52
|
-
} else {
|
|
53
|
-
throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
|
|
54
|
-
}
|
|
55
|
-
return base64UrlEncode(array);
|
|
56
|
-
}
|
|
57
|
-
function generateStateWithReturnUrl(returnUrl) {
|
|
58
|
-
const csrf = generateState();
|
|
59
|
-
const stateData = returnUrl ? { csrf, returnUrl } : { csrf };
|
|
60
|
-
const encoder = new TextEncoder;
|
|
61
|
-
const jsonBytes = encoder.encode(JSON.stringify(stateData));
|
|
62
|
-
return base64UrlEncode(jsonBytes);
|
|
63
|
-
}
|
|
64
|
-
function parseState(state) {
|
|
65
|
-
try {
|
|
66
|
-
const decoded = base64UrlDecode(state);
|
|
67
|
-
const parsed = JSON.parse(decoded);
|
|
68
|
-
if (typeof parsed === "string") {
|
|
69
|
-
return { csrf: parsed };
|
|
70
|
-
} else if (parsed && typeof parsed === "object") {
|
|
71
|
-
return {
|
|
72
|
-
csrf: parsed.csrf || state,
|
|
73
|
-
returnUrl: parsed.returnUrl
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
return { csrf: state };
|
|
77
|
-
} catch {
|
|
78
|
-
return { csrf: state };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
function base64UrlEncode(array) {
|
|
82
|
-
let base64 = "";
|
|
83
|
-
if (typeof Buffer !== "undefined") {
|
|
84
|
-
base64 = Buffer.from(array).toString("base64");
|
|
85
|
-
} else {
|
|
86
|
-
const binary = String.fromCharCode(...array);
|
|
87
|
-
base64 = btoa(binary);
|
|
88
|
-
}
|
|
89
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
90
|
-
}
|
|
91
|
-
function base64UrlDecode(str) {
|
|
92
|
-
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
93
|
-
while (base64.length % 4 !== 0) {
|
|
94
|
-
base64 += "=";
|
|
95
|
-
}
|
|
96
|
-
if (typeof Buffer !== "undefined") {
|
|
97
|
-
return Buffer.from(base64, "base64").toString("utf-8");
|
|
98
|
-
} else {
|
|
99
|
-
const binary = atob(base64);
|
|
100
|
-
const bytes = new Uint8Array(binary.length);
|
|
101
|
-
for (let i = 0;i < binary.length; i++) {
|
|
102
|
-
bytes[i] = binary.charCodeAt(i);
|
|
103
|
-
}
|
|
104
|
-
const decoder = new TextDecoder;
|
|
105
|
-
return decoder.decode(bytes);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
13
|
// src/adapters/base-handler.ts
|
|
110
|
-
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
111
|
-
|
|
112
14
|
class OAuthHandler {
|
|
113
15
|
config;
|
|
114
16
|
serverUrl;
|
|
@@ -271,6 +173,103 @@ class OAuthHandler {
|
|
|
271
173
|
return jsonRpcResponse.result;
|
|
272
174
|
}
|
|
273
175
|
}
|
|
176
|
+
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
177
|
+
|
|
178
|
+
// src/oauth/pkce.ts
|
|
179
|
+
var exports_pkce = {};
|
|
180
|
+
__export(exports_pkce, {
|
|
181
|
+
parseState: () => parseState,
|
|
182
|
+
generateStateWithReturnUrl: () => generateStateWithReturnUrl,
|
|
183
|
+
generateState: () => generateState,
|
|
184
|
+
generateCodeVerifier: () => generateCodeVerifier,
|
|
185
|
+
generateCodeChallenge: () => generateCodeChallenge
|
|
186
|
+
});
|
|
187
|
+
function generateCodeVerifier() {
|
|
188
|
+
const array = new Uint8Array(32);
|
|
189
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
190
|
+
crypto.getRandomValues(array);
|
|
191
|
+
} else if (typeof globalThis !== "undefined" && globalThis.crypto) {
|
|
192
|
+
globalThis.crypto.getRandomValues(array);
|
|
193
|
+
} else {
|
|
194
|
+
throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
|
|
195
|
+
}
|
|
196
|
+
return base64UrlEncode(array);
|
|
197
|
+
}
|
|
198
|
+
async function generateCodeChallenge(verifier) {
|
|
199
|
+
const encoder = new TextEncoder;
|
|
200
|
+
const data = encoder.encode(verifier);
|
|
201
|
+
let hashBuffer;
|
|
202
|
+
if (typeof crypto !== "undefined" && crypto.subtle) {
|
|
203
|
+
hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
204
|
+
} else if (typeof globalThis !== "undefined" && globalThis.crypto?.subtle) {
|
|
205
|
+
hashBuffer = await globalThis.crypto.subtle.digest("SHA-256", data);
|
|
206
|
+
} else {
|
|
207
|
+
throw new Error("crypto.subtle.digest is not available. Please use Node.js 19+ or a modern browser.");
|
|
208
|
+
}
|
|
209
|
+
return base64UrlEncode(new Uint8Array(hashBuffer));
|
|
210
|
+
}
|
|
211
|
+
function generateState() {
|
|
212
|
+
const array = new Uint8Array(16);
|
|
213
|
+
if (typeof crypto !== "undefined" && crypto.getRandomValues) {
|
|
214
|
+
crypto.getRandomValues(array);
|
|
215
|
+
} else if (typeof globalThis !== "undefined" && globalThis.crypto) {
|
|
216
|
+
globalThis.crypto.getRandomValues(array);
|
|
217
|
+
} else {
|
|
218
|
+
throw new Error("crypto.getRandomValues is not available. Please use Node.js 19+ or a modern browser.");
|
|
219
|
+
}
|
|
220
|
+
return base64UrlEncode(array);
|
|
221
|
+
}
|
|
222
|
+
function generateStateWithReturnUrl(returnUrl) {
|
|
223
|
+
const csrf = generateState();
|
|
224
|
+
const stateData = returnUrl ? { csrf, returnUrl } : { csrf };
|
|
225
|
+
const encoder = new TextEncoder;
|
|
226
|
+
const jsonBytes = encoder.encode(JSON.stringify(stateData));
|
|
227
|
+
return base64UrlEncode(jsonBytes);
|
|
228
|
+
}
|
|
229
|
+
function parseState(state) {
|
|
230
|
+
try {
|
|
231
|
+
const decoded = base64UrlDecode(state);
|
|
232
|
+
const parsed = JSON.parse(decoded);
|
|
233
|
+
if (typeof parsed === "string") {
|
|
234
|
+
return { csrf: parsed };
|
|
235
|
+
} else if (parsed && typeof parsed === "object") {
|
|
236
|
+
return {
|
|
237
|
+
csrf: parsed.csrf || state,
|
|
238
|
+
returnUrl: parsed.returnUrl
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return { csrf: state };
|
|
242
|
+
} catch {
|
|
243
|
+
return { csrf: state };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
function base64UrlEncode(array) {
|
|
247
|
+
let base64 = "";
|
|
248
|
+
if (typeof Buffer !== "undefined") {
|
|
249
|
+
base64 = Buffer.from(array).toString("base64");
|
|
250
|
+
} else {
|
|
251
|
+
const binary = String.fromCharCode(...array);
|
|
252
|
+
base64 = btoa(binary);
|
|
253
|
+
}
|
|
254
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
255
|
+
}
|
|
256
|
+
function base64UrlDecode(str) {
|
|
257
|
+
let base64 = str.replace(/-/g, "+").replace(/_/g, "/");
|
|
258
|
+
while (base64.length % 4 !== 0) {
|
|
259
|
+
base64 += "=";
|
|
260
|
+
}
|
|
261
|
+
if (typeof Buffer !== "undefined") {
|
|
262
|
+
return Buffer.from(base64, "base64").toString("utf-8");
|
|
263
|
+
} else {
|
|
264
|
+
const binary = atob(base64);
|
|
265
|
+
const bytes = new Uint8Array(binary.length);
|
|
266
|
+
for (let i = 0;i < binary.length; i++) {
|
|
267
|
+
bytes[i] = binary.charCodeAt(i);
|
|
268
|
+
}
|
|
269
|
+
const decoder = new TextDecoder;
|
|
270
|
+
return decoder.decode(bytes);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
274
273
|
|
|
275
274
|
// src/adapters/nextjs.ts
|
|
276
275
|
function createNextOAuthHandler(config) {
|
package/dist/adapters/node.js
CHANGED
|
@@ -11,8 +11,6 @@ var __export = (target, all) => {
|
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
13
|
// src/adapters/base-handler.ts
|
|
14
|
-
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
15
|
-
|
|
16
14
|
class OAuthHandler {
|
|
17
15
|
config;
|
|
18
16
|
serverUrl;
|
|
@@ -175,6 +173,7 @@ class OAuthHandler {
|
|
|
175
173
|
return jsonRpcResponse.result;
|
|
176
174
|
}
|
|
177
175
|
}
|
|
176
|
+
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
178
177
|
|
|
179
178
|
// src/adapters/node.ts
|
|
180
179
|
function fromNodeHeaders(nodeHeaders) {
|
|
@@ -10,6 +10,171 @@ var __export = (target, all) => {
|
|
|
10
10
|
};
|
|
11
11
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
12
12
|
|
|
13
|
+
// src/adapters/base-handler.ts
|
|
14
|
+
class OAuthHandler {
|
|
15
|
+
config;
|
|
16
|
+
serverUrl;
|
|
17
|
+
apiKey;
|
|
18
|
+
constructor(config) {
|
|
19
|
+
this.config = config;
|
|
20
|
+
if (!config || !config.providers) {
|
|
21
|
+
throw new Error("OAuthHandler requires a valid config with providers");
|
|
22
|
+
}
|
|
23
|
+
this.serverUrl = config.serverUrl || MCP_SERVER_URL;
|
|
24
|
+
this.apiKey = config.apiKey;
|
|
25
|
+
}
|
|
26
|
+
getHeaders(additionalHeaders) {
|
|
27
|
+
const headers = {
|
|
28
|
+
...additionalHeaders
|
|
29
|
+
};
|
|
30
|
+
if (this.apiKey) {
|
|
31
|
+
headers["X-API-KEY"] = this.apiKey;
|
|
32
|
+
}
|
|
33
|
+
return headers;
|
|
34
|
+
}
|
|
35
|
+
async handleAuthorize(request) {
|
|
36
|
+
const providerConfig = this.config.providers[request.provider];
|
|
37
|
+
if (!providerConfig) {
|
|
38
|
+
throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
|
|
39
|
+
}
|
|
40
|
+
if (!providerConfig.clientId || !providerConfig.clientSecret) {
|
|
41
|
+
throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
|
|
42
|
+
}
|
|
43
|
+
const url = new URL("/oauth/authorize", this.serverUrl);
|
|
44
|
+
url.searchParams.set("provider", request.provider);
|
|
45
|
+
url.searchParams.set("client_id", providerConfig.clientId);
|
|
46
|
+
url.searchParams.set("client_secret", providerConfig.clientSecret);
|
|
47
|
+
url.searchParams.set("scope", request.scopes.join(","));
|
|
48
|
+
url.searchParams.set("state", request.state);
|
|
49
|
+
url.searchParams.set("code_challenge", request.codeChallenge);
|
|
50
|
+
url.searchParams.set("code_challenge_method", request.codeChallengeMethod);
|
|
51
|
+
const redirectUri = request.redirectUri || providerConfig.redirectUri;
|
|
52
|
+
if (redirectUri) {
|
|
53
|
+
url.searchParams.set("redirect_uri", redirectUri);
|
|
54
|
+
}
|
|
55
|
+
const response = await fetch(url.toString(), {
|
|
56
|
+
method: "GET",
|
|
57
|
+
headers: this.getHeaders()
|
|
58
|
+
});
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const error = await response.text();
|
|
61
|
+
throw new Error(`MCP server failed to generate authorization URL: ${error}`);
|
|
62
|
+
}
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
return data;
|
|
65
|
+
}
|
|
66
|
+
async handleCallback(request) {
|
|
67
|
+
const providerConfig = this.config.providers[request.provider];
|
|
68
|
+
if (!providerConfig) {
|
|
69
|
+
throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
|
|
70
|
+
}
|
|
71
|
+
if (!providerConfig.clientId || !providerConfig.clientSecret) {
|
|
72
|
+
throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
|
|
73
|
+
}
|
|
74
|
+
const url = new URL("/oauth/callback", this.serverUrl);
|
|
75
|
+
const response = await fetch(url.toString(), {
|
|
76
|
+
method: "POST",
|
|
77
|
+
headers: this.getHeaders({
|
|
78
|
+
"Content-Type": "application/json"
|
|
79
|
+
}),
|
|
80
|
+
body: JSON.stringify({
|
|
81
|
+
provider: request.provider,
|
|
82
|
+
code: request.code,
|
|
83
|
+
code_verifier: request.codeVerifier,
|
|
84
|
+
state: request.state,
|
|
85
|
+
client_id: providerConfig.clientId,
|
|
86
|
+
client_secret: providerConfig.clientSecret,
|
|
87
|
+
redirect_uri: providerConfig.redirectUri
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
const error = await response.text();
|
|
92
|
+
throw new Error(`MCP server failed to exchange authorization code: ${error}`);
|
|
93
|
+
}
|
|
94
|
+
const data = await response.json();
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
async handleStatus(provider, accessToken) {
|
|
98
|
+
const url = new URL("/oauth/status", this.serverUrl);
|
|
99
|
+
url.searchParams.set("provider", provider);
|
|
100
|
+
const response = await fetch(url.toString(), {
|
|
101
|
+
method: "GET",
|
|
102
|
+
headers: this.getHeaders({
|
|
103
|
+
Authorization: `Bearer ${accessToken}`
|
|
104
|
+
})
|
|
105
|
+
});
|
|
106
|
+
if (!response.ok) {
|
|
107
|
+
if (response.status === 401) {
|
|
108
|
+
return {
|
|
109
|
+
authorized: false
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const error = await response.text();
|
|
113
|
+
throw new Error(`MCP server failed to check authorization status: ${error}`);
|
|
114
|
+
}
|
|
115
|
+
const data = await response.json();
|
|
116
|
+
return data;
|
|
117
|
+
}
|
|
118
|
+
async handleDisconnect(request, accessToken) {
|
|
119
|
+
if (!accessToken) {
|
|
120
|
+
throw new Error("No access token provided. Cannot disconnect provider.");
|
|
121
|
+
}
|
|
122
|
+
const url = new URL("/oauth/disconnect", this.serverUrl);
|
|
123
|
+
const response = await fetch(url.toString(), {
|
|
124
|
+
method: "POST",
|
|
125
|
+
headers: this.getHeaders({
|
|
126
|
+
"Content-Type": "application/json",
|
|
127
|
+
Authorization: `Bearer ${accessToken}`
|
|
128
|
+
}),
|
|
129
|
+
body: JSON.stringify({
|
|
130
|
+
provider: request.provider
|
|
131
|
+
})
|
|
132
|
+
});
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
const error = await response.text();
|
|
135
|
+
throw new Error(`MCP server failed to disconnect provider: ${error}`);
|
|
136
|
+
}
|
|
137
|
+
const data = await response.json();
|
|
138
|
+
return data;
|
|
139
|
+
}
|
|
140
|
+
async handleToolCall(request, authHeader) {
|
|
141
|
+
const url = new URL("/tools/call", this.serverUrl);
|
|
142
|
+
const headers = this.getHeaders({
|
|
143
|
+
"Content-Type": "application/json"
|
|
144
|
+
});
|
|
145
|
+
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
146
|
+
headers["Authorization"] = authHeader;
|
|
147
|
+
}
|
|
148
|
+
const jsonRpcRequest = {
|
|
149
|
+
jsonrpc: "2.0",
|
|
150
|
+
id: Date.now() + Math.random(),
|
|
151
|
+
method: "tools/call",
|
|
152
|
+
params: {
|
|
153
|
+
name: request.name,
|
|
154
|
+
arguments: request.arguments || {}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
const response = await fetch(url.toString(), {
|
|
158
|
+
method: "POST",
|
|
159
|
+
headers,
|
|
160
|
+
body: JSON.stringify(jsonRpcRequest)
|
|
161
|
+
});
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
const error = await response.text();
|
|
164
|
+
throw new Error(`MCP server failed to execute tool call: ${error}`);
|
|
165
|
+
}
|
|
166
|
+
const jsonRpcResponse = await response.json();
|
|
167
|
+
if (jsonRpcResponse.error) {
|
|
168
|
+
const error = new Error(jsonRpcResponse.error.message || "Tool call failed");
|
|
169
|
+
error.code = jsonRpcResponse.error.code;
|
|
170
|
+
error.data = jsonRpcResponse.error.data;
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
return jsonRpcResponse.result;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
177
|
+
|
|
13
178
|
// src/oauth/pkce.ts
|
|
14
179
|
var exports_pkce = {};
|
|
15
180
|
__export(exports_pkce, {
|
|
@@ -244,172 +409,6 @@ var init_errors = __esm(() => {
|
|
|
244
409
|
};
|
|
245
410
|
});
|
|
246
411
|
|
|
247
|
-
// src/adapters/base-handler.ts
|
|
248
|
-
var MCP_SERVER_URL = "https://mcp.integrate.dev/api/v1/mcp";
|
|
249
|
-
|
|
250
|
-
class OAuthHandler {
|
|
251
|
-
config;
|
|
252
|
-
serverUrl;
|
|
253
|
-
apiKey;
|
|
254
|
-
constructor(config) {
|
|
255
|
-
this.config = config;
|
|
256
|
-
if (!config || !config.providers) {
|
|
257
|
-
throw new Error("OAuthHandler requires a valid config with providers");
|
|
258
|
-
}
|
|
259
|
-
this.serverUrl = config.serverUrl || MCP_SERVER_URL;
|
|
260
|
-
this.apiKey = config.apiKey;
|
|
261
|
-
}
|
|
262
|
-
getHeaders(additionalHeaders) {
|
|
263
|
-
const headers = {
|
|
264
|
-
...additionalHeaders
|
|
265
|
-
};
|
|
266
|
-
if (this.apiKey) {
|
|
267
|
-
headers["X-API-KEY"] = this.apiKey;
|
|
268
|
-
}
|
|
269
|
-
return headers;
|
|
270
|
-
}
|
|
271
|
-
async handleAuthorize(request) {
|
|
272
|
-
const providerConfig = this.config.providers[request.provider];
|
|
273
|
-
if (!providerConfig) {
|
|
274
|
-
throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
|
|
275
|
-
}
|
|
276
|
-
if (!providerConfig.clientId || !providerConfig.clientSecret) {
|
|
277
|
-
throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
|
|
278
|
-
}
|
|
279
|
-
const url = new URL("/oauth/authorize", this.serverUrl);
|
|
280
|
-
url.searchParams.set("provider", request.provider);
|
|
281
|
-
url.searchParams.set("client_id", providerConfig.clientId);
|
|
282
|
-
url.searchParams.set("client_secret", providerConfig.clientSecret);
|
|
283
|
-
url.searchParams.set("scope", request.scopes.join(","));
|
|
284
|
-
url.searchParams.set("state", request.state);
|
|
285
|
-
url.searchParams.set("code_challenge", request.codeChallenge);
|
|
286
|
-
url.searchParams.set("code_challenge_method", request.codeChallengeMethod);
|
|
287
|
-
const redirectUri = request.redirectUri || providerConfig.redirectUri;
|
|
288
|
-
if (redirectUri) {
|
|
289
|
-
url.searchParams.set("redirect_uri", redirectUri);
|
|
290
|
-
}
|
|
291
|
-
const response = await fetch(url.toString(), {
|
|
292
|
-
method: "GET",
|
|
293
|
-
headers: this.getHeaders()
|
|
294
|
-
});
|
|
295
|
-
if (!response.ok) {
|
|
296
|
-
const error = await response.text();
|
|
297
|
-
throw new Error(`MCP server failed to generate authorization URL: ${error}`);
|
|
298
|
-
}
|
|
299
|
-
const data = await response.json();
|
|
300
|
-
return data;
|
|
301
|
-
}
|
|
302
|
-
async handleCallback(request) {
|
|
303
|
-
const providerConfig = this.config.providers[request.provider];
|
|
304
|
-
if (!providerConfig) {
|
|
305
|
-
throw new Error(`Provider ${request.provider} not configured. Add OAuth credentials to your API route configuration.`);
|
|
306
|
-
}
|
|
307
|
-
if (!providerConfig.clientId || !providerConfig.clientSecret) {
|
|
308
|
-
throw new Error(`Missing OAuth credentials for ${request.provider}. Check your environment variables.`);
|
|
309
|
-
}
|
|
310
|
-
const url = new URL("/oauth/callback", this.serverUrl);
|
|
311
|
-
const response = await fetch(url.toString(), {
|
|
312
|
-
method: "POST",
|
|
313
|
-
headers: this.getHeaders({
|
|
314
|
-
"Content-Type": "application/json"
|
|
315
|
-
}),
|
|
316
|
-
body: JSON.stringify({
|
|
317
|
-
provider: request.provider,
|
|
318
|
-
code: request.code,
|
|
319
|
-
code_verifier: request.codeVerifier,
|
|
320
|
-
state: request.state,
|
|
321
|
-
client_id: providerConfig.clientId,
|
|
322
|
-
client_secret: providerConfig.clientSecret,
|
|
323
|
-
redirect_uri: providerConfig.redirectUri
|
|
324
|
-
})
|
|
325
|
-
});
|
|
326
|
-
if (!response.ok) {
|
|
327
|
-
const error = await response.text();
|
|
328
|
-
throw new Error(`MCP server failed to exchange authorization code: ${error}`);
|
|
329
|
-
}
|
|
330
|
-
const data = await response.json();
|
|
331
|
-
return data;
|
|
332
|
-
}
|
|
333
|
-
async handleStatus(provider, accessToken) {
|
|
334
|
-
const url = new URL("/oauth/status", this.serverUrl);
|
|
335
|
-
url.searchParams.set("provider", provider);
|
|
336
|
-
const response = await fetch(url.toString(), {
|
|
337
|
-
method: "GET",
|
|
338
|
-
headers: this.getHeaders({
|
|
339
|
-
Authorization: `Bearer ${accessToken}`
|
|
340
|
-
})
|
|
341
|
-
});
|
|
342
|
-
if (!response.ok) {
|
|
343
|
-
if (response.status === 401) {
|
|
344
|
-
return {
|
|
345
|
-
authorized: false
|
|
346
|
-
};
|
|
347
|
-
}
|
|
348
|
-
const error = await response.text();
|
|
349
|
-
throw new Error(`MCP server failed to check authorization status: ${error}`);
|
|
350
|
-
}
|
|
351
|
-
const data = await response.json();
|
|
352
|
-
return data;
|
|
353
|
-
}
|
|
354
|
-
async handleDisconnect(request, accessToken) {
|
|
355
|
-
if (!accessToken) {
|
|
356
|
-
throw new Error("No access token provided. Cannot disconnect provider.");
|
|
357
|
-
}
|
|
358
|
-
const url = new URL("/oauth/disconnect", this.serverUrl);
|
|
359
|
-
const response = await fetch(url.toString(), {
|
|
360
|
-
method: "POST",
|
|
361
|
-
headers: this.getHeaders({
|
|
362
|
-
"Content-Type": "application/json",
|
|
363
|
-
Authorization: `Bearer ${accessToken}`
|
|
364
|
-
}),
|
|
365
|
-
body: JSON.stringify({
|
|
366
|
-
provider: request.provider
|
|
367
|
-
})
|
|
368
|
-
});
|
|
369
|
-
if (!response.ok) {
|
|
370
|
-
const error = await response.text();
|
|
371
|
-
throw new Error(`MCP server failed to disconnect provider: ${error}`);
|
|
372
|
-
}
|
|
373
|
-
const data = await response.json();
|
|
374
|
-
return data;
|
|
375
|
-
}
|
|
376
|
-
async handleToolCall(request, authHeader) {
|
|
377
|
-
const url = new URL("/tools/call", this.serverUrl);
|
|
378
|
-
const headers = this.getHeaders({
|
|
379
|
-
"Content-Type": "application/json"
|
|
380
|
-
});
|
|
381
|
-
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
382
|
-
headers["Authorization"] = authHeader;
|
|
383
|
-
}
|
|
384
|
-
const jsonRpcRequest = {
|
|
385
|
-
jsonrpc: "2.0",
|
|
386
|
-
id: Date.now() + Math.random(),
|
|
387
|
-
method: "tools/call",
|
|
388
|
-
params: {
|
|
389
|
-
name: request.name,
|
|
390
|
-
arguments: request.arguments || {}
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
const response = await fetch(url.toString(), {
|
|
394
|
-
method: "POST",
|
|
395
|
-
headers,
|
|
396
|
-
body: JSON.stringify(jsonRpcRequest)
|
|
397
|
-
});
|
|
398
|
-
if (!response.ok) {
|
|
399
|
-
const error = await response.text();
|
|
400
|
-
throw new Error(`MCP server failed to execute tool call: ${error}`);
|
|
401
|
-
}
|
|
402
|
-
const jsonRpcResponse = await response.json();
|
|
403
|
-
if (jsonRpcResponse.error) {
|
|
404
|
-
const error = new Error(jsonRpcResponse.error.message || "Tool call failed");
|
|
405
|
-
error.code = jsonRpcResponse.error.code;
|
|
406
|
-
error.data = jsonRpcResponse.error.data;
|
|
407
|
-
throw error;
|
|
408
|
-
}
|
|
409
|
-
return jsonRpcResponse.result;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
|
|
413
412
|
// src/adapters/nextjs.ts
|
|
414
413
|
function createNextOAuthHandler(config) {
|
|
415
414
|
const handler = new OAuthHandler(config);
|
|
@@ -1327,8 +1326,6 @@ class MCPClient {
|
|
|
1327
1326
|
onReauthRequired;
|
|
1328
1327
|
maxReauthRetries;
|
|
1329
1328
|
authState = new Map;
|
|
1330
|
-
connectionMode;
|
|
1331
|
-
connecting = null;
|
|
1332
1329
|
oauthManager;
|
|
1333
1330
|
eventEmitter = new SimpleEventEmitter;
|
|
1334
1331
|
apiRouteBase;
|
|
@@ -1362,7 +1359,6 @@ class MCPClient {
|
|
|
1362
1359
|
};
|
|
1363
1360
|
this.onReauthRequired = config.onReauthRequired;
|
|
1364
1361
|
this.maxReauthRetries = config.maxReauthRetries ?? 1;
|
|
1365
|
-
this.connectionMode = config.connectionMode ?? "lazy";
|
|
1366
1362
|
this.oauthManager = new OAuthManager(oauthApiBase, config.oauthFlow);
|
|
1367
1363
|
const providers = this.plugins.filter((p) => p.oauth).map((p) => p.oauth.provider);
|
|
1368
1364
|
this.oauthManager.loadAllProviderTokens(providers);
|
|
@@ -1388,28 +1384,10 @@ class MCPClient {
|
|
|
1388
1384
|
const normalizedPath = oauthApiBase.replace(/\/$/, "");
|
|
1389
1385
|
return `${origin}${normalizedPath}/callback`;
|
|
1390
1386
|
}
|
|
1391
|
-
async ensureConnected() {
|
|
1392
|
-
if (this.initialized && this.transport.isConnected()) {
|
|
1393
|
-
return;
|
|
1394
|
-
}
|
|
1395
|
-
if (this.connecting) {
|
|
1396
|
-
return this.connecting;
|
|
1397
|
-
}
|
|
1398
|
-
if (this.connectionMode === "manual" && !this.initialized) {
|
|
1399
|
-
throw new Error("Client not connected. Call connect() first when using manual connection mode.");
|
|
1400
|
-
}
|
|
1401
|
-
this.connecting = this.connect();
|
|
1402
|
-
try {
|
|
1403
|
-
await this.connecting;
|
|
1404
|
-
} finally {
|
|
1405
|
-
this.connecting = null;
|
|
1406
|
-
}
|
|
1407
|
-
}
|
|
1408
1387
|
createPluginProxy(pluginId) {
|
|
1409
1388
|
return new Proxy({}, {
|
|
1410
1389
|
get: (_target, methodName) => {
|
|
1411
1390
|
return async (args) => {
|
|
1412
|
-
await this.ensureConnected();
|
|
1413
1391
|
const toolName = methodToToolName(methodName, pluginId);
|
|
1414
1392
|
return await this.callToolWithRetry(toolName, args, 0);
|
|
1415
1393
|
};
|
|
@@ -1420,7 +1398,6 @@ class MCPClient {
|
|
|
1420
1398
|
return new Proxy({}, {
|
|
1421
1399
|
get: (_target, methodName) => {
|
|
1422
1400
|
return async (args) => {
|
|
1423
|
-
await this.ensureConnected();
|
|
1424
1401
|
const toolName = methodToToolName(methodName, "");
|
|
1425
1402
|
const finalToolName = toolName.startsWith("_") ? toolName.substring(1) : toolName;
|
|
1426
1403
|
return await this.callServerToolInternal(finalToolName, args);
|
|
@@ -1429,12 +1406,6 @@ class MCPClient {
|
|
|
1429
1406
|
});
|
|
1430
1407
|
}
|
|
1431
1408
|
async callServerToolInternal(name, args) {
|
|
1432
|
-
if (!this.initialized) {
|
|
1433
|
-
throw new Error("Client not initialized. Call connect() first.");
|
|
1434
|
-
}
|
|
1435
|
-
if (!this.availableTools.has(name)) {
|
|
1436
|
-
throw new Error(`Tool "${name}" is not available on the server. Available tools: ${Array.from(this.availableTools.keys()).join(", ")}`);
|
|
1437
|
-
}
|
|
1438
1409
|
try {
|
|
1439
1410
|
const response = await this.callToolThroughHandler(name, args);
|
|
1440
1411
|
return response;
|
|
@@ -1489,12 +1460,6 @@ class MCPClient {
|
|
|
1489
1460
|
return await this.callToolWithRetry(name, args, 0);
|
|
1490
1461
|
}
|
|
1491
1462
|
async callServerTool(name, args) {
|
|
1492
|
-
if (!this.initialized) {
|
|
1493
|
-
throw new Error("Client not initialized. Call connect() first.");
|
|
1494
|
-
}
|
|
1495
|
-
if (!this.availableTools.has(name)) {
|
|
1496
|
-
throw new Error(`Tool "${name}" is not available on the server. Available tools: ${Array.from(this.availableTools.keys()).join(", ")}`);
|
|
1497
|
-
}
|
|
1498
1463
|
try {
|
|
1499
1464
|
const response = await this.callToolThroughHandler(name, args);
|
|
1500
1465
|
return response;
|
|
@@ -1548,15 +1513,9 @@ class MCPClient {
|
|
|
1548
1513
|
return result;
|
|
1549
1514
|
}
|
|
1550
1515
|
async callToolWithRetry(name, args, retryCount = 0) {
|
|
1551
|
-
if (!this.initialized) {
|
|
1552
|
-
throw new Error("Client not initialized. Call connect() first.");
|
|
1553
|
-
}
|
|
1554
1516
|
if (!this.enabledToolNames.has(name)) {
|
|
1555
1517
|
throw new Error(`Tool "${name}" is not enabled. Enable it by adding the appropriate plugin.`);
|
|
1556
1518
|
}
|
|
1557
|
-
if (!this.availableTools.has(name)) {
|
|
1558
|
-
throw new Error(`Tool "${name}" is not available on the server. Available tools: ${Array.from(this.availableTools.keys()).join(", ")}`);
|
|
1559
|
-
}
|
|
1560
1519
|
const provider = this.getProviderForTool(name);
|
|
1561
1520
|
try {
|
|
1562
1521
|
const response = await this.callToolThroughHandler(name, args, provider);
|