integrate-sdk 0.6.8 → 0.7.0
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 +36 -0
- package/dist/adapters/base-handler.js +36 -0
- package/dist/adapters/nextjs-oauth-redirect.js +1 -0
- package/dist/adapters/nextjs.js +53 -0
- package/dist/adapters/node.js +36 -0
- package/dist/adapters/solid-start.js +1829 -3
- package/dist/adapters/svelte-kit.js +1840 -5
- package/dist/adapters/tanstack-start.js +1 -0
- package/dist/index.js +421 -82
- package/dist/oauth.js +35 -0
- package/dist/server.js +248 -38
- package/dist/src/adapters/base-handler.d.ts +34 -0
- package/dist/src/adapters/base-handler.d.ts.map +1 -1
- package/dist/src/adapters/nextjs.d.ts +26 -0
- package/dist/src/adapters/nextjs.d.ts.map +1 -1
- package/dist/src/adapters/solid-start.d.ts +2 -48
- package/dist/src/adapters/solid-start.d.ts.map +1 -1
- package/dist/src/adapters/svelte-kit.d.ts +7 -6
- package/dist/src/adapters/svelte-kit.d.ts.map +1 -1
- package/dist/src/client.d.ts +6 -0
- package/dist/src/client.d.ts.map +1 -1
- package/dist/src/config/types.d.ts +18 -0
- package/dist/src/config/types.d.ts.map +1 -1
- package/dist/src/server.d.ts +158 -0
- package/dist/src/server.d.ts.map +1 -1
- package/dist/src/utils/env.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1014,6 +1014,7 @@ class MCPClient {
|
|
|
1014
1014
|
connecting = null;
|
|
1015
1015
|
oauthManager;
|
|
1016
1016
|
eventEmitter = new SimpleEventEmitter;
|
|
1017
|
+
apiRouteBase;
|
|
1017
1018
|
github;
|
|
1018
1019
|
gmail;
|
|
1019
1020
|
server;
|
|
@@ -1025,6 +1026,7 @@ class MCPClient {
|
|
|
1025
1026
|
});
|
|
1026
1027
|
const oauthApiBase = config.oauthApiBase || "/api/integrate/oauth";
|
|
1027
1028
|
const defaultRedirectUri = this.getDefaultRedirectUri(oauthApiBase);
|
|
1029
|
+
this.apiRouteBase = config.apiRouteBase || "/api/integrate";
|
|
1028
1030
|
this.plugins = config.plugins.map((plugin) => {
|
|
1029
1031
|
if (plugin.oauth && !plugin.oauth.redirectUri) {
|
|
1030
1032
|
return {
|
|
@@ -1116,12 +1118,8 @@ class MCPClient {
|
|
|
1116
1118
|
if (!this.availableTools.has(name)) {
|
|
1117
1119
|
throw new Error(`Tool "${name}" is not available on the server. Available tools: ${Array.from(this.availableTools.keys()).join(", ")}`);
|
|
1118
1120
|
}
|
|
1119
|
-
const params = {
|
|
1120
|
-
name,
|
|
1121
|
-
arguments: args
|
|
1122
|
-
};
|
|
1123
1121
|
try {
|
|
1124
|
-
const response = await this.
|
|
1122
|
+
const response = await this.callToolThroughHandler(name, args);
|
|
1125
1123
|
return response;
|
|
1126
1124
|
} catch (error) {
|
|
1127
1125
|
const parsedError = parseServerError(error, { toolName: name });
|
|
@@ -1180,18 +1178,58 @@ class MCPClient {
|
|
|
1180
1178
|
if (!this.availableTools.has(name)) {
|
|
1181
1179
|
throw new Error(`Tool "${name}" is not available on the server. Available tools: ${Array.from(this.availableTools.keys()).join(", ")}`);
|
|
1182
1180
|
}
|
|
1183
|
-
const params = {
|
|
1184
|
-
name,
|
|
1185
|
-
arguments: args
|
|
1186
|
-
};
|
|
1187
1181
|
try {
|
|
1188
|
-
const response = await this.
|
|
1182
|
+
const response = await this.callToolThroughHandler(name, args);
|
|
1189
1183
|
return response;
|
|
1190
1184
|
} catch (error) {
|
|
1191
1185
|
const parsedError = parseServerError(error, { toolName: name });
|
|
1192
1186
|
throw parsedError;
|
|
1193
1187
|
}
|
|
1194
1188
|
}
|
|
1189
|
+
async callToolThroughHandler(name, args, provider) {
|
|
1190
|
+
const url = `${this.apiRouteBase}/mcp`;
|
|
1191
|
+
const headers = {
|
|
1192
|
+
"Content-Type": "application/json"
|
|
1193
|
+
};
|
|
1194
|
+
if (provider) {
|
|
1195
|
+
const tokenData = this.oauthManager.getProviderToken(provider);
|
|
1196
|
+
if (tokenData) {
|
|
1197
|
+
headers["Authorization"] = `Bearer ${tokenData.accessToken}`;
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
const response = await fetch(url, {
|
|
1201
|
+
method: "POST",
|
|
1202
|
+
headers,
|
|
1203
|
+
body: JSON.stringify({
|
|
1204
|
+
name,
|
|
1205
|
+
arguments: args
|
|
1206
|
+
})
|
|
1207
|
+
});
|
|
1208
|
+
if (!response.ok) {
|
|
1209
|
+
let errorMessage = `Request failed: ${response.statusText}`;
|
|
1210
|
+
const error = new Error(errorMessage);
|
|
1211
|
+
error.statusCode = response.status;
|
|
1212
|
+
try {
|
|
1213
|
+
const errorData = await response.json();
|
|
1214
|
+
if (errorData.error) {
|
|
1215
|
+
errorMessage = typeof errorData.error === "string" ? errorData.error : errorData.error.message || errorMessage;
|
|
1216
|
+
error.message = errorMessage;
|
|
1217
|
+
}
|
|
1218
|
+
if (errorData.code) {
|
|
1219
|
+
error.code = errorData.code;
|
|
1220
|
+
}
|
|
1221
|
+
if (errorData.data) {
|
|
1222
|
+
error.data = errorData.data;
|
|
1223
|
+
}
|
|
1224
|
+
if (errorData.error && typeof errorData.error === "object") {
|
|
1225
|
+
error.jsonrpcError = errorData.error;
|
|
1226
|
+
}
|
|
1227
|
+
} catch {}
|
|
1228
|
+
throw error;
|
|
1229
|
+
}
|
|
1230
|
+
const result = await response.json();
|
|
1231
|
+
return result;
|
|
1232
|
+
}
|
|
1195
1233
|
async callToolWithRetry(name, args, retryCount = 0) {
|
|
1196
1234
|
if (!this.initialized) {
|
|
1197
1235
|
throw new Error("Client not initialized. Call connect() first.");
|
|
@@ -1203,35 +1241,24 @@ class MCPClient {
|
|
|
1203
1241
|
throw new Error(`Tool "${name}" is not available on the server. Available tools: ${Array.from(this.availableTools.keys()).join(", ")}`);
|
|
1204
1242
|
}
|
|
1205
1243
|
const provider = this.getProviderForTool(name);
|
|
1206
|
-
if (provider) {
|
|
1207
|
-
const tokenData = this.oauthManager.getProviderToken(provider);
|
|
1208
|
-
if (tokenData) {
|
|
1209
|
-
this.transport.setHeader("Authorization", `Bearer ${tokenData.accessToken}`);
|
|
1210
|
-
}
|
|
1211
|
-
}
|
|
1212
|
-
const params = {
|
|
1213
|
-
name,
|
|
1214
|
-
arguments: args
|
|
1215
|
-
};
|
|
1216
1244
|
try {
|
|
1217
|
-
const response = await this.
|
|
1245
|
+
const response = await this.callToolThroughHandler(name, args, provider);
|
|
1218
1246
|
if (provider) {
|
|
1219
1247
|
this.authState.set(provider, { authenticated: true });
|
|
1220
1248
|
}
|
|
1221
1249
|
return response;
|
|
1222
1250
|
} catch (error) {
|
|
1223
|
-
const
|
|
1224
|
-
const parsedError = parseServerError(error, { toolName: name, provider: provider2 });
|
|
1251
|
+
const parsedError = parseServerError(error, { toolName: name, provider });
|
|
1225
1252
|
if (isAuthError(parsedError) && retryCount < this.maxReauthRetries) {
|
|
1226
|
-
if (
|
|
1227
|
-
this.authState.set(
|
|
1253
|
+
if (provider) {
|
|
1254
|
+
this.authState.set(provider, {
|
|
1228
1255
|
authenticated: false,
|
|
1229
1256
|
lastError: parsedError
|
|
1230
1257
|
});
|
|
1231
1258
|
}
|
|
1232
|
-
if (this.onReauthRequired &&
|
|
1259
|
+
if (this.onReauthRequired && provider) {
|
|
1233
1260
|
const reauthSuccess = await this.onReauthRequired({
|
|
1234
|
-
provider
|
|
1261
|
+
provider,
|
|
1235
1262
|
error: parsedError,
|
|
1236
1263
|
toolName: name
|
|
1237
1264
|
});
|
|
@@ -1684,6 +1711,41 @@ class OAuthHandler {
|
|
|
1684
1711
|
const data = await response.json();
|
|
1685
1712
|
return data;
|
|
1686
1713
|
}
|
|
1714
|
+
async handleToolCall(request, authHeader) {
|
|
1715
|
+
const url = new URL("/tools/call", this.serverUrl);
|
|
1716
|
+
const headers = this.getHeaders({
|
|
1717
|
+
"Content-Type": "application/json"
|
|
1718
|
+
});
|
|
1719
|
+
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
1720
|
+
headers["Authorization"] = authHeader;
|
|
1721
|
+
}
|
|
1722
|
+
const jsonRpcRequest = {
|
|
1723
|
+
jsonrpc: "2.0",
|
|
1724
|
+
id: Date.now() + Math.random(),
|
|
1725
|
+
method: "tools/call",
|
|
1726
|
+
params: {
|
|
1727
|
+
name: request.name,
|
|
1728
|
+
arguments: request.arguments || {}
|
|
1729
|
+
}
|
|
1730
|
+
};
|
|
1731
|
+
const response = await fetch(url.toString(), {
|
|
1732
|
+
method: "POST",
|
|
1733
|
+
headers,
|
|
1734
|
+
body: JSON.stringify(jsonRpcRequest)
|
|
1735
|
+
});
|
|
1736
|
+
if (!response.ok) {
|
|
1737
|
+
const error = await response.text();
|
|
1738
|
+
throw new Error(`MCP server failed to execute tool call: ${error}`);
|
|
1739
|
+
}
|
|
1740
|
+
const jsonRpcResponse = await response.json();
|
|
1741
|
+
if (jsonRpcResponse.error) {
|
|
1742
|
+
const error = new Error(jsonRpcResponse.error.message || "Tool call failed");
|
|
1743
|
+
error.code = jsonRpcResponse.error.code;
|
|
1744
|
+
error.data = jsonRpcResponse.error.data;
|
|
1745
|
+
throw error;
|
|
1746
|
+
}
|
|
1747
|
+
return jsonRpcResponse.result;
|
|
1748
|
+
}
|
|
1687
1749
|
}
|
|
1688
1750
|
// src/adapters/nextjs.ts
|
|
1689
1751
|
function createNextOAuthHandler(config) {
|
|
@@ -1760,6 +1822,9 @@ function createNextOAuthHandler(config) {
|
|
|
1760
1822
|
if (action === "disconnect") {
|
|
1761
1823
|
return handlers.disconnect(req);
|
|
1762
1824
|
}
|
|
1825
|
+
if (action === "mcp") {
|
|
1826
|
+
return handlers.mcp(req);
|
|
1827
|
+
}
|
|
1763
1828
|
return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
|
|
1764
1829
|
},
|
|
1765
1830
|
async GET(req, context) {
|
|
@@ -1772,6 +1837,17 @@ function createNextOAuthHandler(config) {
|
|
|
1772
1837
|
}
|
|
1773
1838
|
};
|
|
1774
1839
|
},
|
|
1840
|
+
async mcp(req) {
|
|
1841
|
+
try {
|
|
1842
|
+
const body = await req.json();
|
|
1843
|
+
const authHeader = req.headers.get("authorization");
|
|
1844
|
+
const result = await handler.handleToolCall(body, authHeader);
|
|
1845
|
+
return Response.json(result);
|
|
1846
|
+
} catch (error) {
|
|
1847
|
+
console.error("[MCP Tool Call] Error:", error);
|
|
1848
|
+
return Response.json({ error: error.message || "Failed to execute tool call" }, { status: error.statusCode || 500 });
|
|
1849
|
+
}
|
|
1850
|
+
},
|
|
1775
1851
|
toNextJsHandler(redirectConfig) {
|
|
1776
1852
|
const defaultRedirectUrl = redirectConfig?.redirectUrl || "/";
|
|
1777
1853
|
const errorRedirectUrl = redirectConfig?.errorRedirectUrl || "/auth-error";
|
|
@@ -1792,6 +1868,9 @@ function createNextOAuthHandler(config) {
|
|
|
1792
1868
|
}
|
|
1793
1869
|
return Response.json({ error: `Unknown action: ${action}` }, { status: 404 });
|
|
1794
1870
|
}
|
|
1871
|
+
if (segments.length === 1 && segments[0] === "mcp") {
|
|
1872
|
+
return handlers.mcp(req);
|
|
1873
|
+
}
|
|
1795
1874
|
return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
|
|
1796
1875
|
},
|
|
1797
1876
|
async GET(req, context) {
|
|
@@ -2025,64 +2104,10 @@ function toNodeHandler(config) {
|
|
|
2025
2104
|
}
|
|
2026
2105
|
};
|
|
2027
2106
|
}
|
|
2028
|
-
// src/adapters/solid-start.ts
|
|
2029
|
-
function toSolidStartHandler(baseHandler) {
|
|
2030
|
-
const handler = async (event) => {
|
|
2031
|
-
return baseHandler(event.request);
|
|
2032
|
-
};
|
|
2033
|
-
return {
|
|
2034
|
-
GET: handler,
|
|
2035
|
-
POST: handler,
|
|
2036
|
-
PATCH: handler,
|
|
2037
|
-
PUT: handler,
|
|
2038
|
-
DELETE: handler
|
|
2039
|
-
};
|
|
2040
|
-
}
|
|
2041
|
-
// src/adapters/svelte-kit.ts
|
|
2042
|
-
async function svelteKitHandler({
|
|
2043
|
-
authConfig,
|
|
2044
|
-
event,
|
|
2045
|
-
resolve,
|
|
2046
|
-
basePath = "/api/integrate"
|
|
2047
|
-
}) {
|
|
2048
|
-
const { url } = event;
|
|
2049
|
-
const baseUrl = new URL(basePath, url.origin);
|
|
2050
|
-
if (!url.pathname.startsWith(baseUrl.pathname)) {
|
|
2051
|
-
return resolve(event);
|
|
2052
|
-
}
|
|
2053
|
-
return authConfig(event.request);
|
|
2054
|
-
}
|
|
2055
|
-
function toSvelteKitHandler(baseHandler) {
|
|
2056
|
-
return async (event) => {
|
|
2057
|
-
return baseHandler(event.request);
|
|
2058
|
-
};
|
|
2059
|
-
}
|
|
2060
|
-
// src/adapters/tanstack-start.ts
|
|
2061
|
-
function toTanStackStartHandler(handler) {
|
|
2062
|
-
const baseHandler = async ({ request }) => {
|
|
2063
|
-
return handler(request);
|
|
2064
|
-
};
|
|
2065
|
-
return {
|
|
2066
|
-
GET: baseHandler,
|
|
2067
|
-
POST: baseHandler
|
|
2068
|
-
};
|
|
2069
|
-
}
|
|
2070
|
-
var createTanStackOAuthHandler = toTanStackStartHandler;
|
|
2071
|
-
|
|
2072
|
-
// src/index.ts
|
|
2073
|
-
init_errors();
|
|
2074
|
-
|
|
2075
2107
|
// src/utils/env.ts
|
|
2076
2108
|
function getEnv(key) {
|
|
2077
2109
|
try {
|
|
2078
|
-
const
|
|
2079
|
-
try {
|
|
2080
|
-
return typeof import.meta !== "undefined" ? import.meta.env : undefined;
|
|
2081
|
-
} catch {
|
|
2082
|
-
return;
|
|
2083
|
-
}
|
|
2084
|
-
};
|
|
2085
|
-
const metaEnv = getMetaEnv();
|
|
2110
|
+
const metaEnv = import.meta.env;
|
|
2086
2111
|
if (metaEnv && typeof metaEnv === "object" && metaEnv !== null) {
|
|
2087
2112
|
const value = metaEnv[key];
|
|
2088
2113
|
if (value !== undefined && value !== null && value !== "") {
|
|
@@ -2206,6 +2231,320 @@ function createSimplePlugin(config) {
|
|
|
2206
2231
|
onDisconnect: config.onDisconnect
|
|
2207
2232
|
};
|
|
2208
2233
|
}
|
|
2234
|
+
|
|
2235
|
+
// src/server.ts
|
|
2236
|
+
var globalServerConfig = null;
|
|
2237
|
+
function getDefaultRedirectUri() {
|
|
2238
|
+
if (typeof window !== "undefined") {
|
|
2239
|
+
return `${window.location.origin}/api/integrate/oauth/callback`;
|
|
2240
|
+
}
|
|
2241
|
+
const integrateUrl = getEnv("INTEGRATE_URL");
|
|
2242
|
+
if (integrateUrl) {
|
|
2243
|
+
return `${integrateUrl}/api/integrate/oauth/callback`;
|
|
2244
|
+
}
|
|
2245
|
+
const vercelUrl = getEnv("VERCEL_URL");
|
|
2246
|
+
if (vercelUrl) {
|
|
2247
|
+
return `https://${vercelUrl}/api/integrate/oauth/callback`;
|
|
2248
|
+
}
|
|
2249
|
+
return "http://localhost:3000/api/integrate/oauth/callback";
|
|
2250
|
+
}
|
|
2251
|
+
function createMCPServer(config) {
|
|
2252
|
+
if (typeof window !== "undefined") {
|
|
2253
|
+
throw new Error("createMCPServer() should only be called on the server-side. " + "Use createMCPClient() for client-side code.");
|
|
2254
|
+
}
|
|
2255
|
+
const providers = {};
|
|
2256
|
+
const updatedPlugins = config.plugins.map((plugin) => {
|
|
2257
|
+
if (plugin.oauth) {
|
|
2258
|
+
const { clientId, clientSecret, redirectUri: pluginRedirectUri } = plugin.oauth;
|
|
2259
|
+
if (!clientId || !clientSecret) {
|
|
2260
|
+
console.warn(`Warning: Plugin "${plugin.id}" is missing OAuth credentials. ` + `Provide clientId and clientSecret in the plugin configuration.`);
|
|
2261
|
+
return plugin;
|
|
2262
|
+
}
|
|
2263
|
+
const redirectUri = pluginRedirectUri || config.redirectUri || getDefaultRedirectUri();
|
|
2264
|
+
providers[plugin.id] = {
|
|
2265
|
+
clientId,
|
|
2266
|
+
clientSecret,
|
|
2267
|
+
redirectUri
|
|
2268
|
+
};
|
|
2269
|
+
return {
|
|
2270
|
+
...plugin,
|
|
2271
|
+
oauth: {
|
|
2272
|
+
...plugin.oauth,
|
|
2273
|
+
redirectUri
|
|
2274
|
+
}
|
|
2275
|
+
};
|
|
2276
|
+
}
|
|
2277
|
+
return plugin;
|
|
2278
|
+
});
|
|
2279
|
+
globalServerConfig = {
|
|
2280
|
+
providers,
|
|
2281
|
+
serverUrl: config.serverUrl,
|
|
2282
|
+
apiKey: config.apiKey
|
|
2283
|
+
};
|
|
2284
|
+
const clientConfig = {
|
|
2285
|
+
...config,
|
|
2286
|
+
plugins: updatedPlugins,
|
|
2287
|
+
connectionMode: config.connectionMode || "lazy",
|
|
2288
|
+
singleton: config.singleton ?? true
|
|
2289
|
+
};
|
|
2290
|
+
const client = new MCPClient(clientConfig);
|
|
2291
|
+
if (config.apiKey) {
|
|
2292
|
+
client.setRequestHeader("X-API-KEY", config.apiKey);
|
|
2293
|
+
}
|
|
2294
|
+
client.__oauthConfig = {
|
|
2295
|
+
providers,
|
|
2296
|
+
serverUrl: config.serverUrl,
|
|
2297
|
+
apiKey: config.apiKey
|
|
2298
|
+
};
|
|
2299
|
+
const { POST, GET } = createOAuthRouteHandlers({
|
|
2300
|
+
providers,
|
|
2301
|
+
serverUrl: config.serverUrl,
|
|
2302
|
+
apiKey: config.apiKey
|
|
2303
|
+
});
|
|
2304
|
+
const handler = async (request, context) => {
|
|
2305
|
+
const method = request.method.toUpperCase();
|
|
2306
|
+
let action;
|
|
2307
|
+
let segments = [];
|
|
2308
|
+
if (context?.params?.action) {
|
|
2309
|
+
action = context.params.action;
|
|
2310
|
+
} else if (context?.params?.all) {
|
|
2311
|
+
const all = context.params.all;
|
|
2312
|
+
if (Array.isArray(all)) {
|
|
2313
|
+
segments = all;
|
|
2314
|
+
} else if (typeof all === "string") {
|
|
2315
|
+
segments = all.split("/").filter(Boolean);
|
|
2316
|
+
}
|
|
2317
|
+
if (segments.length === 2 && segments[0] === "oauth") {
|
|
2318
|
+
action = segments[1];
|
|
2319
|
+
} else if (segments.length === 1) {
|
|
2320
|
+
action = segments[0];
|
|
2321
|
+
} else if (segments.length > 0) {
|
|
2322
|
+
action = segments[segments.length - 1];
|
|
2323
|
+
}
|
|
2324
|
+
} else {
|
|
2325
|
+
const url = new URL(request.url);
|
|
2326
|
+
const pathParts = url.pathname.split("/").filter(Boolean);
|
|
2327
|
+
segments = pathParts;
|
|
2328
|
+
const oauthIndex = pathParts.indexOf("oauth");
|
|
2329
|
+
if (oauthIndex >= 0 && oauthIndex < pathParts.length - 1) {
|
|
2330
|
+
action = pathParts[oauthIndex + 1];
|
|
2331
|
+
} else if (pathParts.length > 0) {
|
|
2332
|
+
action = pathParts[pathParts.length - 1];
|
|
2333
|
+
} else {
|
|
2334
|
+
action = "callback";
|
|
2335
|
+
}
|
|
2336
|
+
}
|
|
2337
|
+
if (segments.length > 0) {
|
|
2338
|
+
if (segments.length === 2 && segments[0] !== "oauth") {
|
|
2339
|
+
return Response.json({ error: `Invalid route: /${segments.join("/")}` }, { status: 404 });
|
|
2340
|
+
}
|
|
2341
|
+
if (segments.length === 1 && segments[0] === "mcp") {}
|
|
2342
|
+
}
|
|
2343
|
+
if (method === "GET" && action === "callback") {
|
|
2344
|
+
const url = new URL(request.url);
|
|
2345
|
+
const searchParams = url.searchParams;
|
|
2346
|
+
const code = searchParams.get("code");
|
|
2347
|
+
const state = searchParams.get("state");
|
|
2348
|
+
const error = searchParams.get("error");
|
|
2349
|
+
const errorDescription = searchParams.get("error_description");
|
|
2350
|
+
const defaultRedirectUrl = "/";
|
|
2351
|
+
const errorRedirectUrl = "/auth-error";
|
|
2352
|
+
if (error) {
|
|
2353
|
+
const errorMsg = errorDescription || error;
|
|
2354
|
+
console.error("[OAuth Redirect] Error:", errorMsg);
|
|
2355
|
+
return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent(errorMsg)}`, request.url));
|
|
2356
|
+
}
|
|
2357
|
+
if (!code || !state) {
|
|
2358
|
+
console.error("[OAuth Redirect] Missing code or state parameter");
|
|
2359
|
+
return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent("Invalid OAuth callback")}`, request.url));
|
|
2360
|
+
}
|
|
2361
|
+
let returnUrl = defaultRedirectUrl;
|
|
2362
|
+
try {
|
|
2363
|
+
const { parseState: parseState2 } = await Promise.resolve().then(() => exports_pkce);
|
|
2364
|
+
const stateData = parseState2(state);
|
|
2365
|
+
if (stateData.returnUrl) {
|
|
2366
|
+
returnUrl = stateData.returnUrl;
|
|
2367
|
+
}
|
|
2368
|
+
} catch (e) {
|
|
2369
|
+
try {
|
|
2370
|
+
const referrer = request.headers.get("referer") || request.headers.get("referrer");
|
|
2371
|
+
if (referrer) {
|
|
2372
|
+
const referrerUrl = new URL(referrer);
|
|
2373
|
+
const currentUrl = new URL(request.url);
|
|
2374
|
+
if (referrerUrl.origin === currentUrl.origin) {
|
|
2375
|
+
returnUrl = referrerUrl.pathname + referrerUrl.search;
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
} catch {}
|
|
2379
|
+
}
|
|
2380
|
+
const targetUrl = new URL(returnUrl, request.url);
|
|
2381
|
+
targetUrl.hash = `oauth_callback=${encodeURIComponent(JSON.stringify({ code, state }))}`;
|
|
2382
|
+
return Response.redirect(targetUrl);
|
|
2383
|
+
}
|
|
2384
|
+
const handlerContext = { params: { action: action || "callback" } };
|
|
2385
|
+
if (method === "POST") {
|
|
2386
|
+
return POST(request, handlerContext);
|
|
2387
|
+
} else if (method === "GET") {
|
|
2388
|
+
return GET(request, handlerContext);
|
|
2389
|
+
} else {
|
|
2390
|
+
return Response.json({ error: `Method ${method} not allowed` }, { status: 405 });
|
|
2391
|
+
}
|
|
2392
|
+
};
|
|
2393
|
+
return {
|
|
2394
|
+
client,
|
|
2395
|
+
POST,
|
|
2396
|
+
GET,
|
|
2397
|
+
handler
|
|
2398
|
+
};
|
|
2399
|
+
}
|
|
2400
|
+
function createOAuthRouteHandlers(config) {
|
|
2401
|
+
const handler = createNextOAuthHandler(config);
|
|
2402
|
+
return handler.createRoutes();
|
|
2403
|
+
}
|
|
2404
|
+
var POST = async (req, context) => {
|
|
2405
|
+
if (!globalServerConfig) {
|
|
2406
|
+
return Response.json({ error: "OAuth not configured. Call createMCPServer() in your server initialization file first." }, { status: 500 });
|
|
2407
|
+
}
|
|
2408
|
+
const handler = createNextOAuthHandler(globalServerConfig);
|
|
2409
|
+
const routes = handler.createRoutes();
|
|
2410
|
+
return routes.POST(req, context);
|
|
2411
|
+
};
|
|
2412
|
+
var GET = async (req, context) => {
|
|
2413
|
+
if (!globalServerConfig) {
|
|
2414
|
+
return Response.json({ error: "OAuth not configured. Call createMCPServer() in your server initialization file first." }, { status: 500 });
|
|
2415
|
+
}
|
|
2416
|
+
const handler = createNextOAuthHandler(globalServerConfig);
|
|
2417
|
+
const routes = handler.createRoutes();
|
|
2418
|
+
return routes.GET(req, context);
|
|
2419
|
+
};
|
|
2420
|
+
function toNextJsHandler(options) {
|
|
2421
|
+
const POST2 = async (req, context) => {
|
|
2422
|
+
const config = options.config || options.client?.__oauthConfig;
|
|
2423
|
+
if (!config) {
|
|
2424
|
+
return Response.json({ error: 'OAuth not configured. You must pass either "client" (from createMCPServer) or "config" to toNextJsHandler().' }, { status: 500 });
|
|
2425
|
+
}
|
|
2426
|
+
const handler = createNextOAuthHandler(config);
|
|
2427
|
+
const routes = handler.toNextJsHandler({
|
|
2428
|
+
redirectUrl: options.redirectUrl,
|
|
2429
|
+
errorRedirectUrl: options.errorRedirectUrl
|
|
2430
|
+
});
|
|
2431
|
+
return routes.POST(req, context);
|
|
2432
|
+
};
|
|
2433
|
+
const GET2 = async (req, context) => {
|
|
2434
|
+
const config = options.config || options.client?.__oauthConfig;
|
|
2435
|
+
if (!config) {
|
|
2436
|
+
return Response.json({ error: 'OAuth not configured. You must pass either "client" (from createMCPServer) or "config" to toNextJsHandler().' }, { status: 500 });
|
|
2437
|
+
}
|
|
2438
|
+
const handler = createNextOAuthHandler(config);
|
|
2439
|
+
const routes = handler.toNextJsHandler({
|
|
2440
|
+
redirectUrl: options.redirectUrl,
|
|
2441
|
+
errorRedirectUrl: options.errorRedirectUrl
|
|
2442
|
+
});
|
|
2443
|
+
return routes.GET(req, context);
|
|
2444
|
+
};
|
|
2445
|
+
return { POST: POST2, GET: GET2 };
|
|
2446
|
+
}
|
|
2447
|
+
function toAstroHandler(baseHandler, options) {
|
|
2448
|
+
const defaultRedirectUrl = options?.redirectUrl || "/";
|
|
2449
|
+
const errorRedirectUrl = options?.errorRedirectUrl || "/auth-error";
|
|
2450
|
+
return async (ctx) => {
|
|
2451
|
+
const wrappedHandler = async (request, context) => {
|
|
2452
|
+
const url = new URL(request.url);
|
|
2453
|
+
const method = request.method.toUpperCase();
|
|
2454
|
+
const pathParts = url.pathname.split("/").filter(Boolean);
|
|
2455
|
+
const oauthIndex = pathParts.indexOf("oauth");
|
|
2456
|
+
if (method === "GET" && oauthIndex >= 0 && pathParts[oauthIndex + 1] === "callback") {
|
|
2457
|
+
const searchParams = url.searchParams;
|
|
2458
|
+
const code = searchParams.get("code");
|
|
2459
|
+
const state = searchParams.get("state");
|
|
2460
|
+
const error = searchParams.get("error");
|
|
2461
|
+
const errorDescription = searchParams.get("error_description");
|
|
2462
|
+
if (error) {
|
|
2463
|
+
const errorMsg = errorDescription || error;
|
|
2464
|
+
console.error("[OAuth Redirect] Error:", errorMsg);
|
|
2465
|
+
return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent(errorMsg)}`, request.url));
|
|
2466
|
+
}
|
|
2467
|
+
if (!code || !state) {
|
|
2468
|
+
console.error("[OAuth Redirect] Missing code or state parameter");
|
|
2469
|
+
return Response.redirect(new URL(`${errorRedirectUrl}?error=${encodeURIComponent("Invalid OAuth callback")}`, request.url));
|
|
2470
|
+
}
|
|
2471
|
+
let returnUrl = defaultRedirectUrl;
|
|
2472
|
+
try {
|
|
2473
|
+
const { parseState: parseState2 } = await Promise.resolve().then(() => exports_pkce);
|
|
2474
|
+
const stateData = parseState2(state);
|
|
2475
|
+
if (stateData.returnUrl) {
|
|
2476
|
+
returnUrl = stateData.returnUrl;
|
|
2477
|
+
}
|
|
2478
|
+
} catch (e) {
|
|
2479
|
+
try {
|
|
2480
|
+
const referrer = request.headers.get("referer") || request.headers.get("referrer");
|
|
2481
|
+
if (referrer) {
|
|
2482
|
+
const referrerUrl = new URL(referrer);
|
|
2483
|
+
const currentUrl = new URL(request.url);
|
|
2484
|
+
if (referrerUrl.origin === currentUrl.origin) {
|
|
2485
|
+
returnUrl = referrerUrl.pathname + referrerUrl.search;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
} catch {}
|
|
2489
|
+
}
|
|
2490
|
+
const targetUrl = new URL(returnUrl, request.url);
|
|
2491
|
+
targetUrl.hash = `oauth_callback=${encodeURIComponent(JSON.stringify({ code, state }))}`;
|
|
2492
|
+
return Response.redirect(targetUrl);
|
|
2493
|
+
}
|
|
2494
|
+
return baseHandler(request, context);
|
|
2495
|
+
};
|
|
2496
|
+
return wrappedHandler(ctx.request, { params: { all: ctx.params.all } });
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
function toSolidStartHandler(baseHandler, options) {
|
|
2500
|
+
const wrappedHandler = toAstroHandler(baseHandler, options);
|
|
2501
|
+
const handler = async (event) => {
|
|
2502
|
+
return wrappedHandler({ request: event.request, params: {} });
|
|
2503
|
+
};
|
|
2504
|
+
return {
|
|
2505
|
+
GET: handler,
|
|
2506
|
+
POST: handler,
|
|
2507
|
+
PATCH: handler,
|
|
2508
|
+
PUT: handler,
|
|
2509
|
+
DELETE: handler
|
|
2510
|
+
};
|
|
2511
|
+
}
|
|
2512
|
+
function toSvelteKitHandler(baseHandler, options) {
|
|
2513
|
+
const wrappedHandler = toAstroHandler(baseHandler, options);
|
|
2514
|
+
return async (event) => {
|
|
2515
|
+
const all = event.params?.all;
|
|
2516
|
+
return wrappedHandler({ request: event.request, params: { all } });
|
|
2517
|
+
};
|
|
2518
|
+
}
|
|
2519
|
+
// src/adapters/svelte-kit.ts
|
|
2520
|
+
async function svelteKitHandler({
|
|
2521
|
+
authConfig,
|
|
2522
|
+
event,
|
|
2523
|
+
resolve,
|
|
2524
|
+
basePath = "/api/integrate"
|
|
2525
|
+
}) {
|
|
2526
|
+
const { url } = event;
|
|
2527
|
+
const baseUrl = new URL(basePath, url.origin);
|
|
2528
|
+
if (!url.pathname.startsWith(baseUrl.pathname)) {
|
|
2529
|
+
return resolve(event);
|
|
2530
|
+
}
|
|
2531
|
+
return authConfig(event.request);
|
|
2532
|
+
}
|
|
2533
|
+
// src/adapters/tanstack-start.ts
|
|
2534
|
+
function toTanStackStartHandler(handler) {
|
|
2535
|
+
const baseHandler = async ({ request }) => {
|
|
2536
|
+
return handler(request);
|
|
2537
|
+
};
|
|
2538
|
+
return {
|
|
2539
|
+
GET: baseHandler,
|
|
2540
|
+
POST: baseHandler
|
|
2541
|
+
};
|
|
2542
|
+
}
|
|
2543
|
+
var createTanStackOAuthHandler = toTanStackStartHandler;
|
|
2544
|
+
|
|
2545
|
+
// src/index.ts
|
|
2546
|
+
init_errors();
|
|
2547
|
+
|
|
2209
2548
|
// node_modules/zod/v3/external.js
|
|
2210
2549
|
var exports_external = {};
|
|
2211
2550
|
__export(exports_external, {
|
package/dist/oauth.js
CHANGED
|
@@ -139,6 +139,41 @@ class OAuthHandler {
|
|
|
139
139
|
const data = await response.json();
|
|
140
140
|
return data;
|
|
141
141
|
}
|
|
142
|
+
async handleToolCall(request, authHeader) {
|
|
143
|
+
const url = new URL("/tools/call", this.serverUrl);
|
|
144
|
+
const headers = this.getHeaders({
|
|
145
|
+
"Content-Type": "application/json"
|
|
146
|
+
});
|
|
147
|
+
if (authHeader && authHeader.startsWith("Bearer ")) {
|
|
148
|
+
headers["Authorization"] = authHeader;
|
|
149
|
+
}
|
|
150
|
+
const jsonRpcRequest = {
|
|
151
|
+
jsonrpc: "2.0",
|
|
152
|
+
id: Date.now() + Math.random(),
|
|
153
|
+
method: "tools/call",
|
|
154
|
+
params: {
|
|
155
|
+
name: request.name,
|
|
156
|
+
arguments: request.arguments || {}
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const response = await fetch(url.toString(), {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers,
|
|
162
|
+
body: JSON.stringify(jsonRpcRequest)
|
|
163
|
+
});
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
const error = await response.text();
|
|
166
|
+
throw new Error(`MCP server failed to execute tool call: ${error}`);
|
|
167
|
+
}
|
|
168
|
+
const jsonRpcResponse = await response.json();
|
|
169
|
+
if (jsonRpcResponse.error) {
|
|
170
|
+
const error = new Error(jsonRpcResponse.error.message || "Tool call failed");
|
|
171
|
+
error.code = jsonRpcResponse.error.code;
|
|
172
|
+
error.data = jsonRpcResponse.error.data;
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
return jsonRpcResponse.result;
|
|
176
|
+
}
|
|
142
177
|
}
|
|
143
178
|
|
|
144
179
|
// src/adapters/auto-routes.ts
|