mcp-use 1.2.5-dev.3 → 1.2.5-dev.5
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/.tsbuildinfo +1 -1
- package/dist/src/server/connect-adapter.d.ts +31 -0
- package/dist/src/server/connect-adapter.d.ts.map +1 -0
- package/dist/src/server/index.cjs +332 -115
- package/dist/src/server/index.d.ts +2 -1
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +332 -115
- package/dist/src/server/logging.d.ts.map +1 -1
- package/dist/src/server/mcp-server.d.ts +12 -4
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/tsup.config.d.ts.map +1 -1
- package/package.json +47 -42
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { MiddlewareHandler } from "hono";
|
|
2
|
+
/**
|
|
3
|
+
* Detects if a middleware is Express/Connect style or Hono style
|
|
4
|
+
*
|
|
5
|
+
* Express/Connect middleware: (req, res, next) => void or (err, req, res, next) => void
|
|
6
|
+
* Hono middleware: (c, next) => Promise<Response | void> or (c, next) => Response | void
|
|
7
|
+
*
|
|
8
|
+
* @param middleware - The middleware function to check
|
|
9
|
+
* @returns true if it's Express/Connect middleware, false if it's Hono middleware
|
|
10
|
+
*/
|
|
11
|
+
export declare function isExpressMiddleware(middleware: any): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Automatically adapts middleware to work with Hono
|
|
14
|
+
* Detects if the middleware is Express/Connect style and adapts it accordingly
|
|
15
|
+
* If it's already Hono-compatible middleware, returns it as-is
|
|
16
|
+
*
|
|
17
|
+
* @param middleware - The middleware function (Express/Connect or Hono)
|
|
18
|
+
* @param middlewarePath - The path pattern the middleware is mounted at (optional, only used for Express/Connect middleware)
|
|
19
|
+
* @returns A Hono middleware function
|
|
20
|
+
*/
|
|
21
|
+
export declare function adaptMiddleware(middleware: any, middlewarePath?: string): Promise<MiddlewareHandler>;
|
|
22
|
+
/**
|
|
23
|
+
* Adapts Connect/Express middleware to work with Hono
|
|
24
|
+
* Based on @hono/connect approach using node-mocks-http
|
|
25
|
+
*
|
|
26
|
+
* @param connectMiddleware - The Connect middleware handler
|
|
27
|
+
* @param middlewarePath - The path pattern the middleware is mounted at (e.g., "/mcp-use/widgets/*")
|
|
28
|
+
* @returns A Hono middleware function
|
|
29
|
+
*/
|
|
30
|
+
export declare function adaptConnectMiddleware(connectMiddleware: any, middlewarePath: string): Promise<MiddlewareHandler>;
|
|
31
|
+
//# sourceMappingURL=connect-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect-adapter.d.ts","sourceRoot":"","sources":["../../../src/server/connect-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAW,iBAAiB,EAAQ,MAAM,MAAM,CAAC;AAE7D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,GAAG,GAAG,OAAO,CA0C5D;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CACnC,UAAU,EAAE,GAAG,EACf,cAAc,GAAE,MAAY,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAQ5B;AAED;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC1C,iBAAiB,EAAE,GAAG,EACtB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,iBAAiB,CAAC,CAqJ5B"}
|
|
@@ -31,12 +31,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/server/index.ts
|
|
32
32
|
var server_exports = {};
|
|
33
33
|
__export(server_exports, {
|
|
34
|
+
adaptConnectMiddleware: () => adaptConnectMiddleware,
|
|
35
|
+
adaptMiddleware: () => adaptMiddleware,
|
|
34
36
|
buildWidgetUrl: () => buildWidgetUrl,
|
|
35
37
|
createExternalUrlResource: () => createExternalUrlResource,
|
|
36
38
|
createMCPServer: () => createMCPServer,
|
|
37
39
|
createRawHtmlResource: () => createRawHtmlResource,
|
|
38
40
|
createRemoteDomResource: () => createRemoteDomResource,
|
|
39
|
-
createUIResourceFromDefinition: () => createUIResourceFromDefinition
|
|
41
|
+
createUIResourceFromDefinition: () => createUIResourceFromDefinition,
|
|
42
|
+
isExpressMiddleware: () => isExpressMiddleware
|
|
40
43
|
});
|
|
41
44
|
module.exports = __toCommonJS(server_exports);
|
|
42
45
|
|
|
@@ -153,6 +156,149 @@ function createUIResourceFromDefinition(definition, params, config) {
|
|
|
153
156
|
}
|
|
154
157
|
__name(createUIResourceFromDefinition, "createUIResourceFromDefinition");
|
|
155
158
|
|
|
159
|
+
// src/server/connect-adapter.ts
|
|
160
|
+
function isExpressMiddleware(middleware) {
|
|
161
|
+
if (!middleware || typeof middleware !== "function") {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
const paramCount = middleware.length;
|
|
165
|
+
if (paramCount === 3 || paramCount === 4) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
if (paramCount === 2) {
|
|
169
|
+
const fnString = middleware.toString();
|
|
170
|
+
const expressPatterns = [
|
|
171
|
+
/\bres\.(send|json|status|end|redirect|render|sendFile|download)\b/,
|
|
172
|
+
/\breq\.(body|params|query|cookies|session)\b/,
|
|
173
|
+
/\breq\.get\s*\(/,
|
|
174
|
+
/\bres\.set\s*\(/
|
|
175
|
+
];
|
|
176
|
+
const hasExpressPattern = expressPatterns.some(
|
|
177
|
+
(pattern) => pattern.test(fnString)
|
|
178
|
+
);
|
|
179
|
+
if (hasExpressPattern) {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
__name(isExpressMiddleware, "isExpressMiddleware");
|
|
187
|
+
async function adaptMiddleware(middleware, middlewarePath = "*") {
|
|
188
|
+
if (isExpressMiddleware(middleware)) {
|
|
189
|
+
return adaptConnectMiddleware(middleware, middlewarePath);
|
|
190
|
+
}
|
|
191
|
+
return middleware;
|
|
192
|
+
}
|
|
193
|
+
__name(adaptMiddleware, "adaptMiddleware");
|
|
194
|
+
async function adaptConnectMiddleware(connectMiddleware, middlewarePath) {
|
|
195
|
+
let createRequest;
|
|
196
|
+
let createResponse;
|
|
197
|
+
try {
|
|
198
|
+
const httpMocks = await import("node-mocks-http");
|
|
199
|
+
createRequest = httpMocks.createRequest;
|
|
200
|
+
createResponse = httpMocks.createResponse;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error(
|
|
203
|
+
"[WIDGETS] node-mocks-http not available. Install connect and node-mocks-http for Vite middleware support."
|
|
204
|
+
);
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
207
|
+
let normalizedPath = middlewarePath;
|
|
208
|
+
if (normalizedPath.endsWith("*")) {
|
|
209
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
210
|
+
}
|
|
211
|
+
if (normalizedPath.endsWith("/")) {
|
|
212
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
213
|
+
}
|
|
214
|
+
const honoMiddleware = /* @__PURE__ */ __name(async (c, next) => {
|
|
215
|
+
const request = c.req.raw;
|
|
216
|
+
const parsedURL = new URL(request.url, "http://localhost");
|
|
217
|
+
const query = {};
|
|
218
|
+
for (const [key, value] of parsedURL.searchParams.entries()) {
|
|
219
|
+
query[key] = value;
|
|
220
|
+
}
|
|
221
|
+
let middlewarePathname = parsedURL.pathname;
|
|
222
|
+
if (normalizedPath && middlewarePathname.startsWith(normalizedPath)) {
|
|
223
|
+
middlewarePathname = middlewarePathname.substring(normalizedPath.length);
|
|
224
|
+
if (middlewarePathname === "") {
|
|
225
|
+
middlewarePathname = "/";
|
|
226
|
+
} else if (!middlewarePathname.startsWith("/")) {
|
|
227
|
+
middlewarePathname = "/" + middlewarePathname;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const mockRequest = createRequest({
|
|
231
|
+
method: request.method.toUpperCase(),
|
|
232
|
+
url: middlewarePathname + parsedURL.search,
|
|
233
|
+
headers: Object.fromEntries(request.headers.entries()),
|
|
234
|
+
query,
|
|
235
|
+
...request.body && { body: request.body }
|
|
236
|
+
});
|
|
237
|
+
const mockResponse = createResponse();
|
|
238
|
+
let responseResolved = false;
|
|
239
|
+
const res = await new Promise((resolve) => {
|
|
240
|
+
const originalEnd = mockResponse.end.bind(mockResponse);
|
|
241
|
+
mockResponse.end = (...args) => {
|
|
242
|
+
const result = originalEnd(...args);
|
|
243
|
+
if (!responseResolved && mockResponse.writableEnded) {
|
|
244
|
+
responseResolved = true;
|
|
245
|
+
const statusCode = mockResponse.statusCode;
|
|
246
|
+
const noBodyStatuses = [204, 304];
|
|
247
|
+
const responseBody = noBodyStatuses.includes(statusCode) ? null : mockResponse._getData() || mockResponse._getBuffer() || null;
|
|
248
|
+
const connectResponse = new Response(responseBody, {
|
|
249
|
+
status: statusCode,
|
|
250
|
+
statusText: mockResponse.statusMessage,
|
|
251
|
+
headers: mockResponse.getHeaders()
|
|
252
|
+
});
|
|
253
|
+
resolve(connectResponse);
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
};
|
|
257
|
+
connectMiddleware(mockRequest, mockResponse, () => {
|
|
258
|
+
if (!responseResolved && !mockResponse.writableEnded) {
|
|
259
|
+
responseResolved = true;
|
|
260
|
+
const statusCode = mockResponse.statusCode;
|
|
261
|
+
const noBodyStatuses = [204, 304];
|
|
262
|
+
const responseBody = noBodyStatuses.includes(statusCode) ? null : mockResponse._getData() || mockResponse._getBuffer() || null;
|
|
263
|
+
const preparedHeaders = c.newResponse(null, 204, {}).headers;
|
|
264
|
+
for (const key of [...preparedHeaders.keys()]) {
|
|
265
|
+
if (preparedHeaders.has(key)) {
|
|
266
|
+
c.header(key, void 0);
|
|
267
|
+
}
|
|
268
|
+
if (c.res && c.res.headers.has(key)) {
|
|
269
|
+
c.res.headers.delete(key);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
const connectHeaders = mockResponse.getHeaders();
|
|
273
|
+
for (const [key, value] of Object.entries(connectHeaders)) {
|
|
274
|
+
if (value !== void 0) {
|
|
275
|
+
c.header(
|
|
276
|
+
key,
|
|
277
|
+
Array.isArray(value) ? value.join(", ") : String(value)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
c.status(statusCode);
|
|
282
|
+
if (noBodyStatuses.includes(statusCode)) {
|
|
283
|
+
resolve(c.newResponse(null, statusCode));
|
|
284
|
+
} else if (responseBody) {
|
|
285
|
+
resolve(c.body(responseBody));
|
|
286
|
+
} else {
|
|
287
|
+
resolve(void 0);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
if (res) {
|
|
293
|
+
c.res = res;
|
|
294
|
+
return res;
|
|
295
|
+
}
|
|
296
|
+
await next();
|
|
297
|
+
}, "honoMiddleware");
|
|
298
|
+
return honoMiddleware;
|
|
299
|
+
}
|
|
300
|
+
__name(adaptConnectMiddleware, "adaptConnectMiddleware");
|
|
301
|
+
|
|
156
302
|
// src/server/logging.ts
|
|
157
303
|
async function requestLogger(c, next) {
|
|
158
304
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
|
|
@@ -161,7 +307,8 @@ async function requestLogger(c, next) {
|
|
|
161
307
|
let body = null;
|
|
162
308
|
if (method === "POST" && url.includes("/mcp")) {
|
|
163
309
|
try {
|
|
164
|
-
|
|
310
|
+
const clonedRequest = c.req.raw.clone();
|
|
311
|
+
body = await clonedRequest.json().catch(() => null);
|
|
165
312
|
} catch {
|
|
166
313
|
}
|
|
167
314
|
}
|
|
@@ -219,7 +366,10 @@ var fsHelpers = {
|
|
|
219
366
|
}
|
|
220
367
|
const { readFileSync } = await import("fs");
|
|
221
368
|
const buffer = readFileSync(path);
|
|
222
|
-
return buffer.buffer.slice(
|
|
369
|
+
return buffer.buffer.slice(
|
|
370
|
+
buffer.byteOffset,
|
|
371
|
+
buffer.byteOffset + buffer.byteLength
|
|
372
|
+
);
|
|
223
373
|
},
|
|
224
374
|
async existsSync(path) {
|
|
225
375
|
if (isDeno) {
|
|
@@ -314,6 +464,52 @@ var McpServer = class {
|
|
|
314
464
|
this.app.use("*", requestLogger);
|
|
315
465
|
return new Proxy(this, {
|
|
316
466
|
get(target, prop) {
|
|
467
|
+
if (prop === "use") {
|
|
468
|
+
return (...args) => {
|
|
469
|
+
const hasPath = typeof args[0] === "string";
|
|
470
|
+
const path = hasPath ? args[0] : "*";
|
|
471
|
+
const handlers = hasPath ? args.slice(1) : args;
|
|
472
|
+
const adaptedHandlers = handlers.map((handler) => {
|
|
473
|
+
if (isExpressMiddleware(handler)) {
|
|
474
|
+
return { __isExpressMiddleware: true, handler, path };
|
|
475
|
+
}
|
|
476
|
+
return handler;
|
|
477
|
+
});
|
|
478
|
+
const hasExpressMiddleware = adaptedHandlers.some(
|
|
479
|
+
(h) => h.__isExpressMiddleware
|
|
480
|
+
);
|
|
481
|
+
if (hasExpressMiddleware) {
|
|
482
|
+
Promise.all(
|
|
483
|
+
adaptedHandlers.map(async (h) => {
|
|
484
|
+
if (h.__isExpressMiddleware) {
|
|
485
|
+
const adapted = await adaptConnectMiddleware(
|
|
486
|
+
h.handler,
|
|
487
|
+
h.path
|
|
488
|
+
);
|
|
489
|
+
if (hasPath) {
|
|
490
|
+
target.app.use(path, adapted);
|
|
491
|
+
} else {
|
|
492
|
+
target.app.use(adapted);
|
|
493
|
+
}
|
|
494
|
+
} else {
|
|
495
|
+
if (hasPath) {
|
|
496
|
+
target.app.use(path, h);
|
|
497
|
+
} else {
|
|
498
|
+
target.app.use(h);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
).catch((err) => {
|
|
503
|
+
console.error(
|
|
504
|
+
"[MIDDLEWARE] Failed to adapt Express middleware:",
|
|
505
|
+
err
|
|
506
|
+
);
|
|
507
|
+
});
|
|
508
|
+
return target;
|
|
509
|
+
}
|
|
510
|
+
return target.app.use(...args);
|
|
511
|
+
};
|
|
512
|
+
}
|
|
317
513
|
if (prop in target) {
|
|
318
514
|
return target[prop];
|
|
319
515
|
}
|
|
@@ -880,13 +1076,11 @@ var McpServer = class {
|
|
|
880
1076
|
* @returns Promise that resolves when all widgets are mounted
|
|
881
1077
|
*/
|
|
882
1078
|
async mountWidgets(options) {
|
|
883
|
-
if (this.isProductionMode()) {
|
|
1079
|
+
if (this.isProductionMode() || isDeno) {
|
|
1080
|
+
console.log("[WIDGETS] Mounting widgets in production mode");
|
|
884
1081
|
await this.mountWidgetsProduction(options);
|
|
885
1082
|
} else {
|
|
886
|
-
|
|
887
|
-
console.log("[WIDGETS] Skipping dev mode widget mounting in Deno runtime (use production build)");
|
|
888
|
-
return;
|
|
889
|
-
}
|
|
1083
|
+
console.log("[WIDGETS] Mounting widgets in development mode");
|
|
890
1084
|
await this.mountWidgetsDev(options);
|
|
891
1085
|
}
|
|
892
1086
|
}
|
|
@@ -937,13 +1131,21 @@ var McpServer = class {
|
|
|
937
1131
|
try {
|
|
938
1132
|
const viteModule = await new Function('return import("vite")')();
|
|
939
1133
|
createServer = viteModule.createServer;
|
|
940
|
-
const reactModule = await new Function(
|
|
1134
|
+
const reactModule = await new Function(
|
|
1135
|
+
'return import("@vitejs/plugin-react")'
|
|
1136
|
+
)();
|
|
941
1137
|
react = reactModule.default;
|
|
942
|
-
const tailwindModule = await new Function(
|
|
1138
|
+
const tailwindModule = await new Function(
|
|
1139
|
+
'return import("@tailwindcss/vite")'
|
|
1140
|
+
)();
|
|
943
1141
|
tailwindcss = tailwindModule.default;
|
|
944
1142
|
} catch (error) {
|
|
945
|
-
console.error(
|
|
946
|
-
|
|
1143
|
+
console.error(
|
|
1144
|
+
"[WIDGETS] Dev dependencies not available. Install vite, @vitejs/plugin-react, and @tailwindcss/vite for widget development."
|
|
1145
|
+
);
|
|
1146
|
+
console.error(
|
|
1147
|
+
"[WIDGETS] For production, use 'mcp-use build' to pre-build widgets."
|
|
1148
|
+
);
|
|
947
1149
|
return;
|
|
948
1150
|
}
|
|
949
1151
|
const widgets = entries.map((entry) => {
|
|
@@ -959,16 +1161,17 @@ var McpServer = class {
|
|
|
959
1161
|
const widgetTempDir = pathHelpers.join(tempDir, widget.name);
|
|
960
1162
|
await fs.mkdir(widgetTempDir, { recursive: true });
|
|
961
1163
|
const resourcesPath = pathHelpers.join(getCwd(), resourcesDir);
|
|
962
|
-
const relativeResourcesPath = pathHelpers.relative(
|
|
963
|
-
widgetTempDir,
|
|
964
|
-
resourcesPath
|
|
965
|
-
).replace(/\\/g, "/");
|
|
1164
|
+
const relativeResourcesPath = pathHelpers.relative(widgetTempDir, resourcesPath).replace(/\\/g, "/");
|
|
966
1165
|
const cssContent = `@import "tailwindcss";
|
|
967
1166
|
|
|
968
1167
|
/* Configure Tailwind to scan the resources directory */
|
|
969
1168
|
@source "${relativeResourcesPath}";
|
|
970
1169
|
`;
|
|
971
|
-
await fs.writeFile(
|
|
1170
|
+
await fs.writeFile(
|
|
1171
|
+
pathHelpers.join(widgetTempDir, "styles.css"),
|
|
1172
|
+
cssContent,
|
|
1173
|
+
"utf8"
|
|
1174
|
+
);
|
|
972
1175
|
const entryContent = `import React from 'react'
|
|
973
1176
|
import { createRoot } from 'react-dom/client'
|
|
974
1177
|
import './styles.css'
|
|
@@ -1021,67 +1224,6 @@ if (container && Component) {
|
|
|
1021
1224
|
origin: serverOrigin
|
|
1022
1225
|
}
|
|
1023
1226
|
});
|
|
1024
|
-
const adaptExpressMiddleware = /* @__PURE__ */ __name((middleware) => {
|
|
1025
|
-
return async (c, next) => {
|
|
1026
|
-
const req = c.req.raw;
|
|
1027
|
-
let handled = false;
|
|
1028
|
-
const responseBody = [];
|
|
1029
|
-
let statusCode = 200;
|
|
1030
|
-
const headers = {};
|
|
1031
|
-
const res = {
|
|
1032
|
-
statusCode: 200,
|
|
1033
|
-
status: /* @__PURE__ */ __name((code) => {
|
|
1034
|
-
statusCode = code;
|
|
1035
|
-
res.statusCode = code;
|
|
1036
|
-
return res;
|
|
1037
|
-
}, "status"),
|
|
1038
|
-
setHeader: /* @__PURE__ */ __name((name, value) => {
|
|
1039
|
-
headers[name] = value;
|
|
1040
|
-
}, "setHeader"),
|
|
1041
|
-
getHeader: /* @__PURE__ */ __name((name) => headers[name], "getHeader"),
|
|
1042
|
-
write: /* @__PURE__ */ __name((chunk) => {
|
|
1043
|
-
responseBody.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
|
|
1044
|
-
}, "write"),
|
|
1045
|
-
end: /* @__PURE__ */ __name((chunk) => {
|
|
1046
|
-
if (chunk) {
|
|
1047
|
-
responseBody.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
|
|
1048
|
-
}
|
|
1049
|
-
handled = true;
|
|
1050
|
-
}, "end"),
|
|
1051
|
-
on: /* @__PURE__ */ __name(() => {
|
|
1052
|
-
}, "on"),
|
|
1053
|
-
once: /* @__PURE__ */ __name(() => {
|
|
1054
|
-
}, "once"),
|
|
1055
|
-
removeListener: /* @__PURE__ */ __name(() => {
|
|
1056
|
-
}, "removeListener")
|
|
1057
|
-
};
|
|
1058
|
-
const expressReq = {
|
|
1059
|
-
...req,
|
|
1060
|
-
url: new URL(req.url).pathname + new URL(req.url).search,
|
|
1061
|
-
originalUrl: req.url,
|
|
1062
|
-
baseUrl: "",
|
|
1063
|
-
path: new URL(req.url).pathname,
|
|
1064
|
-
query: Object.fromEntries(new URL(req.url).searchParams),
|
|
1065
|
-
params: {},
|
|
1066
|
-
body: {},
|
|
1067
|
-
headers: Object.fromEntries(req.headers.entries())
|
|
1068
|
-
};
|
|
1069
|
-
await new Promise((resolve, reject) => {
|
|
1070
|
-
middleware(expressReq, res, (err) => {
|
|
1071
|
-
if (err) reject(err);
|
|
1072
|
-
else resolve();
|
|
1073
|
-
});
|
|
1074
|
-
});
|
|
1075
|
-
if (handled) {
|
|
1076
|
-
const body = Buffer.concat(responseBody);
|
|
1077
|
-
return new Response(body, {
|
|
1078
|
-
status: statusCode,
|
|
1079
|
-
headers
|
|
1080
|
-
});
|
|
1081
|
-
}
|
|
1082
|
-
return next();
|
|
1083
|
-
};
|
|
1084
|
-
}, "adaptExpressMiddleware");
|
|
1085
1227
|
this.app.use(`${baseRoute}/*`, async (c, next) => {
|
|
1086
1228
|
const url = new URL(c.req.url);
|
|
1087
1229
|
const pathname = url.pathname;
|
|
@@ -1109,7 +1251,11 @@ if (container && Component) {
|
|
|
1109
1251
|
}
|
|
1110
1252
|
await next();
|
|
1111
1253
|
});
|
|
1112
|
-
|
|
1254
|
+
const viteMiddleware = await adaptConnectMiddleware(
|
|
1255
|
+
viteServer.middlewares,
|
|
1256
|
+
`${baseRoute}/*`
|
|
1257
|
+
);
|
|
1258
|
+
this.app.use(`${baseRoute}/*`, viteMiddleware);
|
|
1113
1259
|
widgets.forEach((widget) => {
|
|
1114
1260
|
console.log(
|
|
1115
1261
|
`[WIDGET] ${widget.name} mounted at ${baseRoute}/${widget.name}`
|
|
@@ -1249,26 +1395,46 @@ if (container && Component) {
|
|
|
1249
1395
|
*/
|
|
1250
1396
|
async mountWidgetsProduction(options) {
|
|
1251
1397
|
const baseRoute = options?.baseRoute || "/mcp-use/widgets";
|
|
1252
|
-
const widgetsDir = pathHelpers.join(
|
|
1253
|
-
|
|
1398
|
+
const widgetsDir = pathHelpers.join(
|
|
1399
|
+
getCwd(),
|
|
1400
|
+
"dist",
|
|
1401
|
+
"resources",
|
|
1402
|
+
"widgets"
|
|
1403
|
+
);
|
|
1404
|
+
console.log("widgetsDir", widgetsDir);
|
|
1405
|
+
this.setupWidgetRoutes();
|
|
1406
|
+
const manifestPath = pathHelpers.join(getCwd(), "dist", ".mcp-use-manifest.json");
|
|
1407
|
+
let widgets = [];
|
|
1408
|
+
try {
|
|
1409
|
+
const manifestContent = await fsHelpers.readFileSync(manifestPath, "utf8");
|
|
1410
|
+
const manifest = JSON.parse(manifestContent);
|
|
1411
|
+
if (manifest.widgets && Array.isArray(manifest.widgets)) {
|
|
1412
|
+
widgets = manifest.widgets;
|
|
1413
|
+
console.log(`[WIDGETS] Loaded ${widgets.length} widget(s) from manifest`);
|
|
1414
|
+
} else {
|
|
1415
|
+
console.log("[WIDGETS] No widgets array found in manifest");
|
|
1416
|
+
}
|
|
1417
|
+
} catch (error) {
|
|
1254
1418
|
console.log(
|
|
1255
|
-
"[WIDGETS]
|
|
1419
|
+
"[WIDGETS] Could not read manifest file, falling back to directory listing:",
|
|
1420
|
+
error
|
|
1256
1421
|
);
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1422
|
+
try {
|
|
1423
|
+
const allEntries = await fsHelpers.readdirSync(widgetsDir);
|
|
1424
|
+
for (const name of allEntries) {
|
|
1425
|
+
const widgetPath = pathHelpers.join(widgetsDir, name);
|
|
1426
|
+
const indexPath = pathHelpers.join(widgetPath, "index.html");
|
|
1427
|
+
if (await fsHelpers.existsSync(indexPath)) {
|
|
1428
|
+
widgets.push(name);
|
|
1429
|
+
}
|
|
1430
|
+
}
|
|
1431
|
+
} catch (dirError) {
|
|
1432
|
+
console.log("[WIDGETS] Directory listing also failed:", dirError);
|
|
1267
1433
|
}
|
|
1268
1434
|
}
|
|
1269
1435
|
if (widgets.length === 0) {
|
|
1270
1436
|
console.log(
|
|
1271
|
-
"[WIDGETS] No built widgets found
|
|
1437
|
+
"[WIDGETS] No built widgets found"
|
|
1272
1438
|
);
|
|
1273
1439
|
return;
|
|
1274
1440
|
}
|
|
@@ -1329,7 +1495,10 @@ if (container && Component) {
|
|
|
1329
1495
|
let props = {};
|
|
1330
1496
|
let description = `Widget: ${widgetName}`;
|
|
1331
1497
|
try {
|
|
1332
|
-
const metadataContent = await fsHelpers.readFileSync(
|
|
1498
|
+
const metadataContent = await fsHelpers.readFileSync(
|
|
1499
|
+
metadataPath,
|
|
1500
|
+
"utf8"
|
|
1501
|
+
);
|
|
1333
1502
|
metadata = JSON.parse(metadataContent);
|
|
1334
1503
|
if (metadata.description) {
|
|
1335
1504
|
description = metadata.description;
|
|
@@ -1497,23 +1666,27 @@ if (container && Component) {
|
|
|
1497
1666
|
}
|
|
1498
1667
|
}, "send")
|
|
1499
1668
|
};
|
|
1500
|
-
return {
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1669
|
+
return {
|
|
1670
|
+
expressReq,
|
|
1671
|
+
expressRes,
|
|
1672
|
+
getResponse: /* @__PURE__ */ __name(() => {
|
|
1673
|
+
if (ended) {
|
|
1674
|
+
if (responseBody.length > 0) {
|
|
1675
|
+
const body = isDeno ? Buffer.concat(responseBody) : Buffer.concat(responseBody);
|
|
1676
|
+
return new Response(body, {
|
|
1677
|
+
status: statusCode,
|
|
1678
|
+
headers
|
|
1679
|
+
});
|
|
1680
|
+
} else {
|
|
1681
|
+
return new Response(null, {
|
|
1682
|
+
status: statusCode,
|
|
1683
|
+
headers
|
|
1684
|
+
});
|
|
1685
|
+
}
|
|
1513
1686
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
}
|
|
1687
|
+
return null;
|
|
1688
|
+
}, "getResponse")
|
|
1689
|
+
};
|
|
1517
1690
|
}, "createExpressLikeObjects");
|
|
1518
1691
|
this.app.post(endpoint, async (c) => {
|
|
1519
1692
|
const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
|
|
@@ -1654,14 +1827,16 @@ if (container && Component) {
|
|
|
1654
1827
|
* Unlike `listen()`, this method does not start a server - it only prepares the
|
|
1655
1828
|
* routes and returns the handler function that can be used with external servers.
|
|
1656
1829
|
*
|
|
1830
|
+
* @param options - Optional configuration for the handler
|
|
1831
|
+
* @param options.provider - Platform provider (e.g., 'supabase') to handle platform-specific path rewriting
|
|
1657
1832
|
* @returns Promise that resolves to the fetch handler function
|
|
1658
1833
|
*
|
|
1659
1834
|
* @example
|
|
1660
1835
|
* ```typescript
|
|
1661
|
-
* // For Supabase Edge Functions
|
|
1836
|
+
* // For Supabase Edge Functions (handles path rewriting automatically)
|
|
1662
1837
|
* const server = createMCPServer('my-server');
|
|
1663
1838
|
* server.tool({ ... });
|
|
1664
|
-
* const handler = await server.getHandler();
|
|
1839
|
+
* const handler = await server.getHandler({ provider: 'supabase' });
|
|
1665
1840
|
* Deno.serve(handler);
|
|
1666
1841
|
* ```
|
|
1667
1842
|
*
|
|
@@ -1674,14 +1849,46 @@ if (container && Component) {
|
|
|
1674
1849
|
* export default { fetch: handler };
|
|
1675
1850
|
* ```
|
|
1676
1851
|
*/
|
|
1677
|
-
async getHandler() {
|
|
1852
|
+
async getHandler(options) {
|
|
1853
|
+
console.log("[MCP] Mounting widgets");
|
|
1678
1854
|
await this.mountWidgets({
|
|
1679
1855
|
baseRoute: "/mcp-use/widgets",
|
|
1680
1856
|
resourcesDir: "resources"
|
|
1681
1857
|
});
|
|
1858
|
+
console.log("[MCP] Mounted widgets");
|
|
1682
1859
|
await this.mountMcp();
|
|
1860
|
+
console.log("[MCP] Mounted MCP");
|
|
1861
|
+
console.log("[MCP] Mounting inspector");
|
|
1683
1862
|
await this.mountInspector();
|
|
1863
|
+
console.log("[MCP] Mounted inspector");
|
|
1684
1864
|
const fetchHandler = this.app.fetch.bind(this.app);
|
|
1865
|
+
if (options?.provider === "supabase") {
|
|
1866
|
+
return async (req) => {
|
|
1867
|
+
const url = new URL(req.url);
|
|
1868
|
+
const pathname = url.pathname;
|
|
1869
|
+
let newPathname = pathname;
|
|
1870
|
+
const functionsMatch = pathname.match(
|
|
1871
|
+
/^\/functions\/v1\/[^/]+(\/.*)?$/
|
|
1872
|
+
);
|
|
1873
|
+
if (functionsMatch) {
|
|
1874
|
+
newPathname = functionsMatch[1] || "/";
|
|
1875
|
+
} else {
|
|
1876
|
+
const functionNameMatch = pathname.match(/^\/([^/]+)(\/.*)?$/);
|
|
1877
|
+
if (functionNameMatch && functionNameMatch[2]) {
|
|
1878
|
+
newPathname = functionNameMatch[2] || "/";
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
const newUrl = new URL(newPathname + url.search, url.origin);
|
|
1882
|
+
const newReq = new Request(newUrl, {
|
|
1883
|
+
method: req.method,
|
|
1884
|
+
headers: req.headers,
|
|
1885
|
+
body: req.body,
|
|
1886
|
+
redirect: req.redirect
|
|
1887
|
+
});
|
|
1888
|
+
const result = await fetchHandler(newReq);
|
|
1889
|
+
return result;
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1685
1892
|
return async (req) => {
|
|
1686
1893
|
const result = await fetchHandler(req);
|
|
1687
1894
|
return result;
|
|
@@ -1781,11 +1988,21 @@ if (container && Component) {
|
|
|
1781
1988
|
});
|
|
1782
1989
|
this.app.get("/mcp-use/widgets/assets/*", async (c) => {
|
|
1783
1990
|
const assetFile = c.req.path.split("/assets/")[1];
|
|
1784
|
-
const widgetsDir = pathHelpers.join(
|
|
1991
|
+
const widgetsDir = pathHelpers.join(
|
|
1992
|
+
getCwd(),
|
|
1993
|
+
"dist",
|
|
1994
|
+
"resources",
|
|
1995
|
+
"widgets"
|
|
1996
|
+
);
|
|
1785
1997
|
try {
|
|
1786
1998
|
const widgets = await fsHelpers.readdirSync(widgetsDir);
|
|
1787
1999
|
for (const widget of widgets) {
|
|
1788
|
-
const assetPath = pathHelpers.join(
|
|
2000
|
+
const assetPath = pathHelpers.join(
|
|
2001
|
+
widgetsDir,
|
|
2002
|
+
widget,
|
|
2003
|
+
"assets",
|
|
2004
|
+
assetFile
|
|
2005
|
+
);
|
|
1789
2006
|
if (await fsHelpers.existsSync(assetPath)) {
|
|
1790
2007
|
const content = await fsHelpers.readFile(assetPath);
|
|
1791
2008
|
const ext = assetFile.split(".").pop()?.toLowerCase();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { createMCPServer, type McpServerInstance } from "./mcp-server.js";
|
|
2
2
|
export * from "./types/index.js";
|
|
3
3
|
export { buildWidgetUrl, createExternalUrlResource, createRawHtmlResource, createRemoteDomResource, createUIResourceFromDefinition, type UrlConfig, } from "./adapters/mcp-ui-adapter.js";
|
|
4
|
-
export
|
|
4
|
+
export { adaptConnectMiddleware, adaptMiddleware, isExpressMiddleware, } from "./connect-adapter.js";
|
|
5
|
+
export type { DiscoverWidgetsOptions, ExternalUrlUIResource, InputDefinition, PromptCallback, PromptDefinition, RawHtmlUIResource, ReadResourceCallback, ReadResourceTemplateCallback, RemoteDomUIResource, ResourceDefinition, ServerConfig, ToolCallback, ToolDefinition, UIResourceDefinition, WidgetConfig, WidgetManifest, WidgetProps, } from "./types/index.js";
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,KAAK,SAAS,GACf,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE1E,cAAc,kBAAkB,CAAC;AAGjC,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,qBAAqB,EACrB,uBAAuB,EACvB,8BAA8B,EAC9B,KAAK,SAAS,GACf,MAAM,8BAA8B,CAAC;AAGtC,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,4BAA4B,EAC5B,mBAAmB,EACnB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,cAAc,EAEd,oBAAoB,EACpB,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
|