mcp-use 1.2.4-canary.1 → 1.2.5-canary.1

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.
@@ -7,42 +7,9 @@ import {
7
7
  McpServer as OfficialMcpServer,
8
8
  ResourceTemplate
9
9
  } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import { Hono } from "hono";
11
+ import { cors } from "hono/cors";
10
12
  import { z } from "zod";
11
- import express from "express";
12
- import cors from "cors";
13
- import { existsSync, readdirSync } from "fs";
14
- import { join } from "path";
15
- import { readFileSync } from "fs";
16
-
17
- // src/server/logging.ts
18
- function requestLogger(req, res, next) {
19
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
20
- const method = req.method;
21
- const url = req.url;
22
- const originalEnd = res.end.bind(res);
23
- res.end = function(chunk, encoding, cb) {
24
- const statusCode = res.statusCode;
25
- let statusColor = "";
26
- if (statusCode >= 200 && statusCode < 300) {
27
- statusColor = "\x1B[32m";
28
- } else if (statusCode >= 300 && statusCode < 400) {
29
- statusColor = "\x1B[33m";
30
- } else if (statusCode >= 400 && statusCode < 500) {
31
- statusColor = "\x1B[31m";
32
- } else if (statusCode >= 500) {
33
- statusColor = "\x1B[35m";
34
- }
35
- let logMessage = `[${timestamp}] ${method} \x1B[1m${url}\x1B[0m`;
36
- if (method === "POST" && url === "/mcp" && req.body?.method) {
37
- logMessage += ` \x1B[1m[${req.body.method}]\x1B[0m`;
38
- }
39
- logMessage += ` ${statusColor}${statusCode}\x1B[0m`;
40
- console.log(logMessage);
41
- return originalEnd(chunk, encoding, cb);
42
- };
43
- next();
44
- }
45
- __name(requestLogger, "requestLogger");
46
13
 
47
14
  // src/server/adapters/mcp-ui-adapter.ts
48
15
  import { createUIResource } from "@mcp-ui/server";
@@ -151,9 +118,264 @@ function createUIResourceFromDefinition(definition, params, config) {
151
118
  }
152
119
  __name(createUIResourceFromDefinition, "createUIResourceFromDefinition");
153
120
 
121
+ // src/server/connect-adapter.ts
122
+ function isExpressMiddleware(middleware) {
123
+ if (!middleware || typeof middleware !== "function") {
124
+ return false;
125
+ }
126
+ const paramCount = middleware.length;
127
+ if (paramCount === 3 || paramCount === 4) {
128
+ return true;
129
+ }
130
+ if (paramCount === 2) {
131
+ const fnString = middleware.toString();
132
+ const expressPatterns = [
133
+ /\bres\.(send|json|status|end|redirect|render|sendFile|download)\b/,
134
+ /\breq\.(body|params|query|cookies|session)\b/,
135
+ /\breq\.get\s*\(/,
136
+ /\bres\.set\s*\(/
137
+ ];
138
+ const hasExpressPattern = expressPatterns.some(
139
+ (pattern) => pattern.test(fnString)
140
+ );
141
+ if (hasExpressPattern) {
142
+ return true;
143
+ }
144
+ return false;
145
+ }
146
+ return false;
147
+ }
148
+ __name(isExpressMiddleware, "isExpressMiddleware");
149
+ async function adaptMiddleware(middleware, middlewarePath = "*") {
150
+ if (isExpressMiddleware(middleware)) {
151
+ return adaptConnectMiddleware(middleware, middlewarePath);
152
+ }
153
+ return middleware;
154
+ }
155
+ __name(adaptMiddleware, "adaptMiddleware");
156
+ async function adaptConnectMiddleware(connectMiddleware, middlewarePath) {
157
+ let createRequest;
158
+ let createResponse;
159
+ try {
160
+ const httpMocks = await import("node-mocks-http");
161
+ createRequest = httpMocks.createRequest;
162
+ createResponse = httpMocks.createResponse;
163
+ } catch (error) {
164
+ console.error(
165
+ "[WIDGETS] node-mocks-http not available. Install connect and node-mocks-http for Vite middleware support."
166
+ );
167
+ throw error;
168
+ }
169
+ let normalizedPath = middlewarePath;
170
+ if (normalizedPath.endsWith("*")) {
171
+ normalizedPath = normalizedPath.slice(0, -1);
172
+ }
173
+ if (normalizedPath.endsWith("/")) {
174
+ normalizedPath = normalizedPath.slice(0, -1);
175
+ }
176
+ const honoMiddleware = /* @__PURE__ */ __name(async (c, next) => {
177
+ const request = c.req.raw;
178
+ const parsedURL = new URL(request.url, "http://localhost");
179
+ const query = {};
180
+ for (const [key, value] of parsedURL.searchParams.entries()) {
181
+ query[key] = value;
182
+ }
183
+ let middlewarePathname = parsedURL.pathname;
184
+ if (normalizedPath && middlewarePathname.startsWith(normalizedPath)) {
185
+ middlewarePathname = middlewarePathname.substring(normalizedPath.length);
186
+ if (middlewarePathname === "") {
187
+ middlewarePathname = "/";
188
+ } else if (!middlewarePathname.startsWith("/")) {
189
+ middlewarePathname = "/" + middlewarePathname;
190
+ }
191
+ }
192
+ const mockRequest = createRequest({
193
+ method: request.method.toUpperCase(),
194
+ url: middlewarePathname + parsedURL.search,
195
+ headers: Object.fromEntries(request.headers.entries()),
196
+ query,
197
+ ...request.body && { body: request.body }
198
+ });
199
+ const mockResponse = createResponse();
200
+ let responseResolved = false;
201
+ const res = await new Promise((resolve) => {
202
+ const originalEnd = mockResponse.end.bind(mockResponse);
203
+ mockResponse.end = (...args) => {
204
+ const result = originalEnd(...args);
205
+ if (!responseResolved && mockResponse.writableEnded) {
206
+ responseResolved = true;
207
+ const statusCode = mockResponse.statusCode;
208
+ const noBodyStatuses = [204, 304];
209
+ const responseBody = noBodyStatuses.includes(statusCode) ? null : mockResponse._getData() || mockResponse._getBuffer() || null;
210
+ const connectResponse = new Response(responseBody, {
211
+ status: statusCode,
212
+ statusText: mockResponse.statusMessage,
213
+ headers: mockResponse.getHeaders()
214
+ });
215
+ resolve(connectResponse);
216
+ }
217
+ return result;
218
+ };
219
+ connectMiddleware(mockRequest, mockResponse, () => {
220
+ if (!responseResolved && !mockResponse.writableEnded) {
221
+ responseResolved = true;
222
+ const statusCode = mockResponse.statusCode;
223
+ const noBodyStatuses = [204, 304];
224
+ const responseBody = noBodyStatuses.includes(statusCode) ? null : mockResponse._getData() || mockResponse._getBuffer() || null;
225
+ const preparedHeaders = c.newResponse(null, 204, {}).headers;
226
+ for (const key of [...preparedHeaders.keys()]) {
227
+ if (preparedHeaders.has(key)) {
228
+ c.header(key, void 0);
229
+ }
230
+ if (c.res && c.res.headers.has(key)) {
231
+ c.res.headers.delete(key);
232
+ }
233
+ }
234
+ const connectHeaders = mockResponse.getHeaders();
235
+ for (const [key, value] of Object.entries(connectHeaders)) {
236
+ if (value !== void 0) {
237
+ c.header(
238
+ key,
239
+ Array.isArray(value) ? value.join(", ") : String(value)
240
+ );
241
+ }
242
+ }
243
+ c.status(statusCode);
244
+ if (noBodyStatuses.includes(statusCode)) {
245
+ resolve(c.newResponse(null, statusCode));
246
+ } else if (responseBody) {
247
+ resolve(c.body(responseBody));
248
+ } else {
249
+ resolve(void 0);
250
+ }
251
+ }
252
+ });
253
+ });
254
+ if (res) {
255
+ c.res = res;
256
+ return res;
257
+ }
258
+ await next();
259
+ }, "honoMiddleware");
260
+ return honoMiddleware;
261
+ }
262
+ __name(adaptConnectMiddleware, "adaptConnectMiddleware");
263
+
264
+ // src/server/logging.ts
265
+ async function requestLogger(c, next) {
266
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().substring(11, 23);
267
+ const method = c.req.method;
268
+ const url = c.req.url;
269
+ let body = null;
270
+ if (method === "POST" && url.includes("/mcp")) {
271
+ try {
272
+ const clonedRequest = c.req.raw.clone();
273
+ body = await clonedRequest.json().catch(() => null);
274
+ } catch {
275
+ }
276
+ }
277
+ await next();
278
+ const statusCode = c.res.status;
279
+ let statusColor = "";
280
+ if (statusCode >= 200 && statusCode < 300) {
281
+ statusColor = "\x1B[32m";
282
+ } else if (statusCode >= 300 && statusCode < 400) {
283
+ statusColor = "\x1B[33m";
284
+ } else if (statusCode >= 400 && statusCode < 500) {
285
+ statusColor = "\x1B[31m";
286
+ } else if (statusCode >= 500) {
287
+ statusColor = "\x1B[35m";
288
+ }
289
+ let logMessage = `[${timestamp}] ${method} \x1B[1m${new URL(url).pathname}\x1B[0m`;
290
+ if (method === "POST" && url.includes("/mcp") && body?.method) {
291
+ logMessage += ` \x1B[1m[${body.method}]\x1B[0m`;
292
+ }
293
+ logMessage += ` ${statusColor}${statusCode}\x1B[0m`;
294
+ console.log(logMessage);
295
+ }
296
+ __name(requestLogger, "requestLogger");
297
+
154
298
  // src/server/mcp-server.ts
155
- import { createServer } from "vite";
156
299
  var TMP_MCP_USE_DIR = ".mcp-use";
300
+ var isDeno = typeof globalThis.Deno !== "undefined";
301
+ function getEnv(key) {
302
+ if (isDeno) {
303
+ return globalThis.Deno.env.get(key);
304
+ }
305
+ return process.env[key];
306
+ }
307
+ __name(getEnv, "getEnv");
308
+ function getCwd() {
309
+ if (isDeno) {
310
+ return globalThis.Deno.cwd();
311
+ }
312
+ return process.cwd();
313
+ }
314
+ __name(getCwd, "getCwd");
315
+ var fsHelpers = {
316
+ async readFileSync(path, encoding = "utf8") {
317
+ if (isDeno) {
318
+ return await globalThis.Deno.readTextFile(path);
319
+ }
320
+ const { readFileSync } = await import("fs");
321
+ const result = readFileSync(path, encoding);
322
+ return typeof result === "string" ? result : result.toString(encoding);
323
+ },
324
+ async readFile(path) {
325
+ if (isDeno) {
326
+ const data = await globalThis.Deno.readFile(path);
327
+ return data.buffer;
328
+ }
329
+ const { readFileSync } = await import("fs");
330
+ const buffer = readFileSync(path);
331
+ return buffer.buffer.slice(
332
+ buffer.byteOffset,
333
+ buffer.byteOffset + buffer.byteLength
334
+ );
335
+ },
336
+ async existsSync(path) {
337
+ if (isDeno) {
338
+ try {
339
+ await globalThis.Deno.stat(path);
340
+ return true;
341
+ } catch {
342
+ return false;
343
+ }
344
+ }
345
+ const { existsSync } = await import("fs");
346
+ return existsSync(path);
347
+ },
348
+ async readdirSync(path) {
349
+ if (isDeno) {
350
+ const entries = [];
351
+ for await (const entry of globalThis.Deno.readDir(path)) {
352
+ entries.push(entry.name);
353
+ }
354
+ return entries;
355
+ }
356
+ const { readdirSync } = await import("fs");
357
+ return readdirSync(path);
358
+ }
359
+ };
360
+ var pathHelpers = {
361
+ join(...paths) {
362
+ if (isDeno) {
363
+ return paths.join("/").replace(/\/+/g, "/");
364
+ }
365
+ return paths.join("/").replace(/\/+/g, "/");
366
+ },
367
+ relative(from, to) {
368
+ const fromParts = from.split("/").filter((p) => p);
369
+ const toParts = to.split("/").filter((p) => p);
370
+ let i = 0;
371
+ while (i < fromParts.length && i < toParts.length && fromParts[i] === toParts[i]) {
372
+ i++;
373
+ }
374
+ const upCount = fromParts.length - i;
375
+ const relativeParts = [...Array(upCount).fill(".."), ...toParts.slice(i)];
376
+ return relativeParts.join("/");
377
+ }
378
+ };
157
379
  var McpServer = class {
158
380
  static {
159
381
  __name(this, "McpServer");
@@ -167,14 +389,14 @@ var McpServer = class {
167
389
  serverHost;
168
390
  serverBaseUrl;
169
391
  /**
170
- * Creates a new MCP server instance with Express integration
392
+ * Creates a new MCP server instance with Hono integration
171
393
  *
172
394
  * Initializes the server with the provided configuration, sets up CORS headers,
173
395
  * configures widget serving routes, and creates a proxy that allows direct
174
- * access to Express methods while preserving MCP server functionality.
396
+ * access to Hono methods while preserving MCP server functionality.
175
397
  *
176
398
  * @param config - Server configuration including name, version, and description
177
- * @returns A proxied McpServer instance that supports both MCP and Express methods
399
+ * @returns A proxied McpServer instance that supports both MCP and Hono methods
178
400
  */
179
401
  constructor(config) {
180
402
  this.config = config;
@@ -184,13 +406,13 @@ var McpServer = class {
184
406
  name: config.name,
185
407
  version: config.version
186
408
  });
187
- this.app = express();
188
- this.app.use(express.json());
409
+ this.app = new Hono();
189
410
  this.app.use(
411
+ "*",
190
412
  cors({
191
413
  origin: "*",
192
- methods: ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"],
193
- allowedHeaders: [
414
+ allowMethods: ["GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS"],
415
+ allowHeaders: [
194
416
  "Content-Type",
195
417
  "Accept",
196
418
  "Authorization",
@@ -201,9 +423,55 @@ var McpServer = class {
201
423
  ]
202
424
  })
203
425
  );
204
- this.app.use(requestLogger);
426
+ this.app.use("*", requestLogger);
205
427
  return new Proxy(this, {
206
428
  get(target, prop) {
429
+ if (prop === "use") {
430
+ return (...args) => {
431
+ const hasPath = typeof args[0] === "string";
432
+ const path = hasPath ? args[0] : "*";
433
+ const handlers = hasPath ? args.slice(1) : args;
434
+ const adaptedHandlers = handlers.map((handler) => {
435
+ if (isExpressMiddleware(handler)) {
436
+ return { __isExpressMiddleware: true, handler, path };
437
+ }
438
+ return handler;
439
+ });
440
+ const hasExpressMiddleware = adaptedHandlers.some(
441
+ (h) => h.__isExpressMiddleware
442
+ );
443
+ if (hasExpressMiddleware) {
444
+ Promise.all(
445
+ adaptedHandlers.map(async (h) => {
446
+ if (h.__isExpressMiddleware) {
447
+ const adapted = await adaptConnectMiddleware(
448
+ h.handler,
449
+ h.path
450
+ );
451
+ if (hasPath) {
452
+ target.app.use(path, adapted);
453
+ } else {
454
+ target.app.use(adapted);
455
+ }
456
+ } else {
457
+ if (hasPath) {
458
+ target.app.use(path, h);
459
+ } else {
460
+ target.app.use(h);
461
+ }
462
+ }
463
+ })
464
+ ).catch((err) => {
465
+ console.error(
466
+ "[MIDDLEWARE] Failed to adapt Express middleware:",
467
+ err
468
+ );
469
+ });
470
+ return target;
471
+ }
472
+ return target.app.use(...args);
473
+ };
474
+ }
207
475
  if (prop in target) {
208
476
  return target[prop];
209
477
  }
@@ -737,7 +1005,7 @@ var McpServer = class {
737
1005
  * @returns true if in production mode, false otherwise
738
1006
  */
739
1007
  isProductionMode() {
740
- return process.env.NODE_ENV === "production";
1008
+ return getEnv("NODE_ENV") === "production";
741
1009
  }
742
1010
  /**
743
1011
  * Read build manifest file
@@ -745,14 +1013,14 @@ var McpServer = class {
745
1013
  * @private
746
1014
  * @returns Build manifest or null if not found
747
1015
  */
748
- readBuildManifest() {
1016
+ async readBuildManifest() {
749
1017
  try {
750
- const manifestPath = join(
751
- process.cwd(),
1018
+ const manifestPath = pathHelpers.join(
1019
+ getCwd(),
752
1020
  "dist",
753
- ".mcp-use-manifest.json"
1021
+ "mcp-use.json"
754
1022
  );
755
- const content = readFileSync(manifestPath, "utf8");
1023
+ const content = await fsHelpers.readFileSync(manifestPath, "utf8");
756
1024
  return JSON.parse(content);
757
1025
  } catch {
758
1026
  return null;
@@ -770,9 +1038,11 @@ var McpServer = class {
770
1038
  * @returns Promise that resolves when all widgets are mounted
771
1039
  */
772
1040
  async mountWidgets(options) {
773
- if (this.isProductionMode()) {
1041
+ if (this.isProductionMode() || isDeno) {
1042
+ console.log("[WIDGETS] Mounting widgets in production mode");
774
1043
  await this.mountWidgetsProduction(options);
775
1044
  } else {
1045
+ console.log("[WIDGETS] Mounting widgets in development mode");
776
1046
  await this.mountWidgetsDev(options);
777
1047
  }
778
1048
  }
@@ -793,7 +1063,7 @@ var McpServer = class {
793
1063
  const { promises: fs } = await import("fs");
794
1064
  const baseRoute = options?.baseRoute || "/mcp-use/widgets";
795
1065
  const resourcesDir = options?.resourcesDir || "resources";
796
- const srcDir = join(process.cwd(), resourcesDir);
1066
+ const srcDir = pathHelpers.join(getCwd(), resourcesDir);
797
1067
  try {
798
1068
  await fs.access(srcDir);
799
1069
  } catch (error) {
@@ -805,7 +1075,7 @@ var McpServer = class {
805
1075
  let entries = [];
806
1076
  try {
807
1077
  const files = await fs.readdir(srcDir);
808
- entries = files.filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => join(srcDir, f));
1078
+ entries = files.filter((f) => f.endsWith(".tsx") || f.endsWith(".ts")).map((f) => pathHelpers.join(srcDir, f));
809
1079
  } catch (error) {
810
1080
  console.log(`[WIDGETS] No widgets found in ${resourcesDir}/ directory`);
811
1081
  return;
@@ -814,12 +1084,32 @@ var McpServer = class {
814
1084
  console.log(`[WIDGETS] No widgets found in ${resourcesDir}/ directory`);
815
1085
  return;
816
1086
  }
817
- const tempDir = join(process.cwd(), TMP_MCP_USE_DIR);
1087
+ const tempDir = pathHelpers.join(getCwd(), TMP_MCP_USE_DIR);
818
1088
  await fs.mkdir(tempDir, { recursive: true }).catch(() => {
819
1089
  });
820
- const react = (await import("@vitejs/plugin-react")).default;
821
- const tailwindcss = (await import("@tailwindcss/vite")).default;
822
- console.log(react, tailwindcss);
1090
+ let createServer;
1091
+ let react;
1092
+ let tailwindcss;
1093
+ try {
1094
+ const viteModule = await new Function('return import("vite")')();
1095
+ createServer = viteModule.createServer;
1096
+ const reactModule = await new Function(
1097
+ 'return import("@vitejs/plugin-react")'
1098
+ )();
1099
+ react = reactModule.default;
1100
+ const tailwindModule = await new Function(
1101
+ 'return import("@tailwindcss/vite")'
1102
+ )();
1103
+ tailwindcss = tailwindModule.default;
1104
+ } catch (error) {
1105
+ console.error(
1106
+ "[WIDGETS] Dev dependencies not available. Install vite, @vitejs/plugin-react, and @tailwindcss/vite for widget development."
1107
+ );
1108
+ console.error(
1109
+ "[WIDGETS] For production, use 'mcp-use build' to pre-build widgets."
1110
+ );
1111
+ return;
1112
+ }
823
1113
  const widgets = entries.map((entry) => {
824
1114
  const baseName = entry.split("/").pop()?.replace(/\.tsx?$/, "") || "widget";
825
1115
  const widgetName = baseName;
@@ -830,20 +1120,20 @@ var McpServer = class {
830
1120
  };
831
1121
  });
832
1122
  for (const widget of widgets) {
833
- const widgetTempDir = join(tempDir, widget.name);
1123
+ const widgetTempDir = pathHelpers.join(tempDir, widget.name);
834
1124
  await fs.mkdir(widgetTempDir, { recursive: true });
835
- const resourcesPath = join(process.cwd(), resourcesDir);
836
- const { relative } = await import("path");
837
- const relativeResourcesPath = relative(
838
- widgetTempDir,
839
- resourcesPath
840
- ).replace(/\\/g, "/");
1125
+ const resourcesPath = pathHelpers.join(getCwd(), resourcesDir);
1126
+ const relativeResourcesPath = pathHelpers.relative(widgetTempDir, resourcesPath).replace(/\\/g, "/");
841
1127
  const cssContent = `@import "tailwindcss";
842
1128
 
843
1129
  /* Configure Tailwind to scan the resources directory */
844
1130
  @source "${relativeResourcesPath}";
845
1131
  `;
846
- await fs.writeFile(join(widgetTempDir, "styles.css"), cssContent, "utf8");
1132
+ await fs.writeFile(
1133
+ pathHelpers.join(widgetTempDir, "styles.css"),
1134
+ cssContent,
1135
+ "utf8"
1136
+ );
847
1137
  const entryContent = `import React from 'react'
848
1138
  import { createRoot } from 'react-dom/client'
849
1139
  import './styles.css'
@@ -868,12 +1158,12 @@ if (container && Component) {
868
1158
  </body>
869
1159
  </html>`;
870
1160
  await fs.writeFile(
871
- join(widgetTempDir, "entry.tsx"),
1161
+ pathHelpers.join(widgetTempDir, "entry.tsx"),
872
1162
  entryContent,
873
1163
  "utf8"
874
1164
  );
875
1165
  await fs.writeFile(
876
- join(widgetTempDir, "index.html"),
1166
+ pathHelpers.join(widgetTempDir, "index.html"),
877
1167
  htmlContent,
878
1168
  "utf8"
879
1169
  );
@@ -888,7 +1178,7 @@ if (container && Component) {
888
1178
  plugins: [tailwindcss(), react()],
889
1179
  resolve: {
890
1180
  alias: {
891
- "@": join(process.cwd(), resourcesDir)
1181
+ "@": pathHelpers.join(getCwd(), resourcesDir)
892
1182
  }
893
1183
  },
894
1184
  server: {
@@ -896,22 +1186,38 @@ if (container && Component) {
896
1186
  origin: serverOrigin
897
1187
  }
898
1188
  });
899
- this.app.use(baseRoute, (req, res, next) => {
900
- const urlPath = req.url || "";
901
- const [pathname, queryString] = urlPath.split("?");
902
- const widgetMatch = pathname.match(/^\/([^/]+)/);
1189
+ this.app.use(`${baseRoute}/*`, async (c, next) => {
1190
+ const url = new URL(c.req.url);
1191
+ const pathname = url.pathname;
1192
+ const widgetMatch = pathname.replace(baseRoute, "").match(/^\/([^/]+)/);
903
1193
  if (widgetMatch) {
904
1194
  const widgetName = widgetMatch[1];
905
1195
  const widget = widgets.find((w) => w.name === widgetName);
906
1196
  if (widget) {
907
- if (pathname === `/${widgetName}` || pathname === `/${widgetName}/`) {
908
- req.url = `/${widgetName}/index.html${queryString ? "?" + queryString : ""}`;
1197
+ const relativePath = pathname.replace(baseRoute, "");
1198
+ if (relativePath === `/${widgetName}` || relativePath === `/${widgetName}/`) {
1199
+ const newUrl = new URL(c.req.url);
1200
+ newUrl.pathname = `${baseRoute}/${widgetName}/index.html`;
1201
+ const newRequest = new Request(newUrl.toString(), c.req.raw);
1202
+ Object.defineProperty(c, "req", {
1203
+ value: {
1204
+ ...c.req,
1205
+ url: newUrl.toString(),
1206
+ raw: newRequest
1207
+ },
1208
+ writable: false,
1209
+ configurable: true
1210
+ });
909
1211
  }
910
1212
  }
911
1213
  }
912
- next();
1214
+ await next();
913
1215
  });
914
- this.app.use(baseRoute, viteServer.middlewares);
1216
+ const viteMiddleware = await adaptConnectMiddleware(
1217
+ viteServer.middlewares,
1218
+ `${baseRoute}/*`
1219
+ );
1220
+ this.app.use(`${baseRoute}/*`, viteMiddleware);
915
1221
  widgets.forEach((widget) => {
916
1222
  console.log(
917
1223
  `[WIDGET] ${widget.name} mounted at ${baseRoute}/${widget.name}`
@@ -947,8 +1253,11 @@ if (container && Component) {
947
1253
  console.log("[WIDGET dev] Metadata:", metadata);
948
1254
  let html = "";
949
1255
  try {
950
- html = readFileSync(join(tempDir, widget.name, "index.html"), "utf8");
951
- const mcpUrl = process.env.MCP_URL || "/";
1256
+ html = await fsHelpers.readFileSync(
1257
+ pathHelpers.join(tempDir, widget.name, "index.html"),
1258
+ "utf8"
1259
+ );
1260
+ const mcpUrl = getEnv("MCP_URL") || "/";
952
1261
  if (mcpUrl && html) {
953
1262
  const htmlWithoutComments = html.replace(/<!--[\s\S]*?-->/g, "");
954
1263
  const baseTagRegex = /<base\s+[^>]*\/?>/i;
@@ -1048,22 +1357,46 @@ if (container && Component) {
1048
1357
  */
1049
1358
  async mountWidgetsProduction(options) {
1050
1359
  const baseRoute = options?.baseRoute || "/mcp-use/widgets";
1051
- const widgetsDir = join(process.cwd(), "dist", "resources", "widgets");
1052
- if (!existsSync(widgetsDir)) {
1360
+ const widgetsDir = pathHelpers.join(
1361
+ getCwd(),
1362
+ "dist",
1363
+ "resources",
1364
+ "widgets"
1365
+ );
1366
+ console.log("widgetsDir", widgetsDir);
1367
+ this.setupWidgetRoutes();
1368
+ const manifestPath = pathHelpers.join(getCwd(), "dist", "mcp-use.json");
1369
+ let widgets = [];
1370
+ try {
1371
+ const manifestContent = await fsHelpers.readFileSync(manifestPath, "utf8");
1372
+ const manifest = JSON.parse(manifestContent);
1373
+ if (manifest.widgets && Array.isArray(manifest.widgets)) {
1374
+ widgets = manifest.widgets;
1375
+ console.log(`[WIDGETS] Loaded ${widgets.length} widget(s) from manifest`);
1376
+ } else {
1377
+ console.log("[WIDGETS] No widgets array found in manifest");
1378
+ }
1379
+ } catch (error) {
1053
1380
  console.log(
1054
- "[WIDGETS] No dist/resources/widgets/ directory found - skipping widget serving"
1381
+ "[WIDGETS] Could not read manifest file, falling back to directory listing:",
1382
+ error
1055
1383
  );
1056
- return;
1384
+ try {
1385
+ const allEntries = await fsHelpers.readdirSync(widgetsDir);
1386
+ for (const name of allEntries) {
1387
+ const widgetPath = pathHelpers.join(widgetsDir, name);
1388
+ const indexPath = pathHelpers.join(widgetPath, "index.html");
1389
+ if (await fsHelpers.existsSync(indexPath)) {
1390
+ widgets.push(name);
1391
+ }
1392
+ }
1393
+ } catch (dirError) {
1394
+ console.log("[WIDGETS] Directory listing also failed:", dirError);
1395
+ }
1057
1396
  }
1058
- this.setupWidgetRoutes();
1059
- const widgets = readdirSync(widgetsDir).filter((name) => {
1060
- const widgetPath = join(widgetsDir, name);
1061
- const indexPath = join(widgetPath, "index.html");
1062
- return existsSync(indexPath);
1063
- });
1064
1397
  if (widgets.length === 0) {
1065
1398
  console.log(
1066
- "[WIDGETS] No built widgets found in dist/resources/widgets/"
1399
+ "[WIDGETS] No built widgets found"
1067
1400
  );
1068
1401
  return;
1069
1402
  }
@@ -1071,13 +1404,13 @@ if (container && Component) {
1071
1404
  `[WIDGETS] Serving ${widgets.length} pre-built widget(s) from dist/resources/widgets/`
1072
1405
  );
1073
1406
  for (const widgetName of widgets) {
1074
- const widgetPath = join(widgetsDir, widgetName);
1075
- const indexPath = join(widgetPath, "index.html");
1076
- const metadataPath = join(widgetPath, "metadata.json");
1407
+ const widgetPath = pathHelpers.join(widgetsDir, widgetName);
1408
+ const indexPath = pathHelpers.join(widgetPath, "index.html");
1409
+ const metadataPath = pathHelpers.join(widgetPath, "metadata.json");
1077
1410
  let html = "";
1078
1411
  try {
1079
- html = readFileSync(indexPath, "utf8");
1080
- const mcpUrl = process.env.MCP_URL || "/";
1412
+ html = await fsHelpers.readFileSync(indexPath, "utf8");
1413
+ const mcpUrl = getEnv("MCP_URL") || "/";
1081
1414
  if (mcpUrl && html) {
1082
1415
  const htmlWithoutComments = html.replace(/<!--[\s\S]*?-->/g, "");
1083
1416
  const baseTagRegex = /<base\s+[^>]*\/?>/i;
@@ -1124,7 +1457,10 @@ if (container && Component) {
1124
1457
  let props = {};
1125
1458
  let description = `Widget: ${widgetName}`;
1126
1459
  try {
1127
- const metadataContent = readFileSync(metadataPath, "utf8");
1460
+ const metadataContent = await fsHelpers.readFileSync(
1461
+ metadataPath,
1462
+ "utf8"
1463
+ );
1128
1464
  metadata = JSON.parse(metadataContent);
1129
1465
  if (metadata.description) {
1130
1466
  description = metadata.description;
@@ -1207,47 +1543,182 @@ if (container && Component) {
1207
1543
  if (this.mcpMounted) return;
1208
1544
  const { StreamableHTTPServerTransport } = await import("@modelcontextprotocol/sdk/server/streamableHttp.js");
1209
1545
  const endpoint = "/mcp";
1210
- this.app.post(endpoint, express.json(), async (req, res) => {
1546
+ const createExpressLikeObjects = /* @__PURE__ */ __name((c) => {
1547
+ const req = c.req.raw;
1548
+ const responseBody = [];
1549
+ let statusCode = 200;
1550
+ const headers = {};
1551
+ let ended = false;
1552
+ let headersSent = false;
1553
+ const expressReq = {
1554
+ ...req,
1555
+ url: new URL(req.url).pathname + new URL(req.url).search,
1556
+ originalUrl: req.url,
1557
+ baseUrl: "",
1558
+ path: new URL(req.url).pathname,
1559
+ query: Object.fromEntries(new URL(req.url).searchParams),
1560
+ params: {},
1561
+ body: {},
1562
+ headers: Object.fromEntries(req.headers.entries()),
1563
+ method: req.method
1564
+ };
1565
+ const expressRes = {
1566
+ statusCode: 200,
1567
+ headersSent: false,
1568
+ status: /* @__PURE__ */ __name((code) => {
1569
+ statusCode = code;
1570
+ expressRes.statusCode = code;
1571
+ return expressRes;
1572
+ }, "status"),
1573
+ setHeader: /* @__PURE__ */ __name((name, value) => {
1574
+ if (!headersSent) {
1575
+ headers[name] = Array.isArray(value) ? value.join(", ") : value;
1576
+ }
1577
+ }, "setHeader"),
1578
+ getHeader: /* @__PURE__ */ __name((name) => headers[name], "getHeader"),
1579
+ write: /* @__PURE__ */ __name((chunk, encoding, callback) => {
1580
+ if (!ended) {
1581
+ const data = typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
1582
+ responseBody.push(data);
1583
+ }
1584
+ if (typeof encoding === "function") {
1585
+ encoding();
1586
+ } else if (callback) {
1587
+ callback();
1588
+ }
1589
+ return true;
1590
+ }, "write"),
1591
+ end: /* @__PURE__ */ __name((chunk, encoding, callback) => {
1592
+ if (chunk && !ended) {
1593
+ const data = typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
1594
+ responseBody.push(data);
1595
+ }
1596
+ ended = true;
1597
+ if (typeof encoding === "function") {
1598
+ encoding();
1599
+ } else if (callback) {
1600
+ callback();
1601
+ }
1602
+ }, "end"),
1603
+ on: /* @__PURE__ */ __name((event, handler) => {
1604
+ if (event === "close") {
1605
+ expressRes._closeHandler = handler;
1606
+ }
1607
+ }, "on"),
1608
+ once: /* @__PURE__ */ __name(() => {
1609
+ }, "once"),
1610
+ removeListener: /* @__PURE__ */ __name(() => {
1611
+ }, "removeListener"),
1612
+ writeHead: /* @__PURE__ */ __name((code, _headers) => {
1613
+ statusCode = code;
1614
+ expressRes.statusCode = code;
1615
+ headersSent = true;
1616
+ if (_headers) {
1617
+ Object.assign(headers, _headers);
1618
+ }
1619
+ return expressRes;
1620
+ }, "writeHead"),
1621
+ flushHeaders: /* @__PURE__ */ __name(() => {
1622
+ headersSent = true;
1623
+ }, "flushHeaders"),
1624
+ send: /* @__PURE__ */ __name((body) => {
1625
+ if (!ended) {
1626
+ expressRes.write(body);
1627
+ expressRes.end();
1628
+ }
1629
+ }, "send")
1630
+ };
1631
+ return {
1632
+ expressReq,
1633
+ expressRes,
1634
+ getResponse: /* @__PURE__ */ __name(() => {
1635
+ if (ended) {
1636
+ if (responseBody.length > 0) {
1637
+ const body = isDeno ? Buffer.concat(responseBody) : Buffer.concat(responseBody);
1638
+ return new Response(body, {
1639
+ status: statusCode,
1640
+ headers
1641
+ });
1642
+ } else {
1643
+ return new Response(null, {
1644
+ status: statusCode,
1645
+ headers
1646
+ });
1647
+ }
1648
+ }
1649
+ return null;
1650
+ }, "getResponse")
1651
+ };
1652
+ }, "createExpressLikeObjects");
1653
+ this.app.post(endpoint, async (c) => {
1654
+ const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
1655
+ try {
1656
+ expressReq.body = await c.req.json();
1657
+ } catch {
1658
+ expressReq.body = {};
1659
+ }
1211
1660
  const transport = new StreamableHTTPServerTransport({
1212
1661
  sessionIdGenerator: void 0,
1213
1662
  enableJsonResponse: true
1214
1663
  });
1215
- res.on("close", () => {
1216
- transport.close();
1217
- });
1664
+ if (expressRes._closeHandler) {
1665
+ c.req.raw.signal?.addEventListener("abort", () => {
1666
+ transport.close();
1667
+ });
1668
+ }
1218
1669
  await this.server.connect(transport);
1219
- await transport.handleRequest(req, res, req.body);
1670
+ await transport.handleRequest(expressReq, expressRes, expressReq.body);
1671
+ await new Promise((resolve) => setTimeout(resolve, 10));
1672
+ const response = getResponse();
1673
+ if (response) {
1674
+ return response;
1675
+ }
1676
+ return c.text("", 200);
1220
1677
  });
1221
- this.app.get(endpoint, async (req, res) => {
1678
+ this.app.get(endpoint, async (c) => {
1679
+ const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
1222
1680
  const transport = new StreamableHTTPServerTransport({
1223
1681
  sessionIdGenerator: void 0,
1224
1682
  enableJsonResponse: true
1225
1683
  });
1226
- res.on("close", () => {
1684
+ c.req.raw.signal?.addEventListener("abort", () => {
1227
1685
  transport.close();
1228
1686
  });
1229
1687
  await this.server.connect(transport);
1230
- await transport.handleRequest(req, res);
1688
+ await transport.handleRequest(expressReq, expressRes);
1689
+ await new Promise((resolve) => setTimeout(resolve, 10));
1690
+ const response = getResponse();
1691
+ if (response) {
1692
+ return response;
1693
+ }
1694
+ return c.text("", 200);
1231
1695
  });
1232
- this.app.delete(endpoint, async (req, res) => {
1696
+ this.app.delete(endpoint, async (c) => {
1697
+ const { expressReq, expressRes, getResponse } = createExpressLikeObjects(c);
1233
1698
  const transport = new StreamableHTTPServerTransport({
1234
1699
  sessionIdGenerator: void 0,
1235
1700
  enableJsonResponse: true
1236
1701
  });
1237
- res.on("close", () => {
1702
+ c.req.raw.signal?.addEventListener("abort", () => {
1238
1703
  transport.close();
1239
1704
  });
1240
1705
  await this.server.connect(transport);
1241
- await transport.handleRequest(req, res);
1706
+ await transport.handleRequest(expressReq, expressRes);
1707
+ await new Promise((resolve) => setTimeout(resolve, 10));
1708
+ const response = getResponse();
1709
+ if (response) {
1710
+ return response;
1711
+ }
1712
+ return c.text("", 200);
1242
1713
  });
1243
1714
  this.mcpMounted = true;
1244
1715
  console.log(`[MCP] Server mounted at ${endpoint}`);
1245
1716
  }
1246
1717
  /**
1247
- * Start the Express server with MCP endpoints
1718
+ * Start the Hono server with MCP endpoints
1248
1719
  *
1249
1720
  * Initiates the server startup process by mounting MCP endpoints, configuring
1250
- * the inspector UI (if available), and starting the Express server to listen
1721
+ * the inspector UI (if available), and starting the server to listen
1251
1722
  * for incoming connections. This is the main entry point for running the server.
1252
1723
  *
1253
1724
  * The server will be accessible at the specified port with MCP endpoints at /mcp
@@ -1265,24 +1736,125 @@ if (container && Component) {
1265
1736
  * ```
1266
1737
  */
1267
1738
  async listen(port) {
1268
- this.serverPort = port || (process.env.PORT ? parseInt(process.env.PORT, 10) : 3001);
1269
- if (process.env.HOST) {
1270
- this.serverHost = process.env.HOST;
1739
+ const portEnv = getEnv("PORT");
1740
+ this.serverPort = port || (portEnv ? parseInt(portEnv, 10) : 3001);
1741
+ const hostEnv = getEnv("HOST");
1742
+ if (hostEnv) {
1743
+ this.serverHost = hostEnv;
1271
1744
  }
1272
1745
  await this.mountWidgets({
1273
1746
  baseRoute: "/mcp-use/widgets",
1274
1747
  resourcesDir: "resources"
1275
1748
  });
1276
1749
  await this.mountMcp();
1277
- this.mountInspector();
1278
- this.app.listen(this.serverPort, () => {
1750
+ await this.mountInspector();
1751
+ if (isDeno) {
1752
+ globalThis.Deno.serve(
1753
+ { port: this.serverPort, hostname: this.serverHost },
1754
+ this.app.fetch
1755
+ );
1279
1756
  console.log(
1280
1757
  `[SERVER] Listening on http://${this.serverHost}:${this.serverPort}`
1281
1758
  );
1282
1759
  console.log(
1283
1760
  `[MCP] Endpoints: http://${this.serverHost}:${this.serverPort}/mcp`
1284
1761
  );
1762
+ } else {
1763
+ const { serve } = await import("@hono/node-server");
1764
+ serve(
1765
+ {
1766
+ fetch: this.app.fetch,
1767
+ port: this.serverPort,
1768
+ hostname: this.serverHost
1769
+ },
1770
+ (_info) => {
1771
+ console.log(
1772
+ `[SERVER] Listening on http://${this.serverHost}:${this.serverPort}`
1773
+ );
1774
+ console.log(
1775
+ `[MCP] Endpoints: http://${this.serverHost}:${this.serverPort}/mcp`
1776
+ );
1777
+ }
1778
+ );
1779
+ }
1780
+ }
1781
+ /**
1782
+ * Get the fetch handler for the server after mounting all endpoints
1783
+ *
1784
+ * This method prepares the server by mounting MCP endpoints, widgets, and inspector
1785
+ * (if available), then returns the fetch handler. This is useful for integrating
1786
+ * with external server frameworks like Supabase Edge Functions, Cloudflare Workers,
1787
+ * or other platforms that handle the server lifecycle themselves.
1788
+ *
1789
+ * Unlike `listen()`, this method does not start a server - it only prepares the
1790
+ * routes and returns the handler function that can be used with external servers.
1791
+ *
1792
+ * @param options - Optional configuration for the handler
1793
+ * @param options.provider - Platform provider (e.g., 'supabase') to handle platform-specific path rewriting
1794
+ * @returns Promise that resolves to the fetch handler function
1795
+ *
1796
+ * @example
1797
+ * ```typescript
1798
+ * // For Supabase Edge Functions (handles path rewriting automatically)
1799
+ * const server = createMCPServer('my-server');
1800
+ * server.tool({ ... });
1801
+ * const handler = await server.getHandler({ provider: 'supabase' });
1802
+ * Deno.serve(handler);
1803
+ * ```
1804
+ *
1805
+ * @example
1806
+ * ```typescript
1807
+ * // For Cloudflare Workers
1808
+ * const server = createMCPServer('my-server');
1809
+ * server.tool({ ... });
1810
+ * const handler = await server.getHandler();
1811
+ * export default { fetch: handler };
1812
+ * ```
1813
+ */
1814
+ async getHandler(options) {
1815
+ console.log("[MCP] Mounting widgets");
1816
+ await this.mountWidgets({
1817
+ baseRoute: "/mcp-use/widgets",
1818
+ resourcesDir: "resources"
1285
1819
  });
1820
+ console.log("[MCP] Mounted widgets");
1821
+ await this.mountMcp();
1822
+ console.log("[MCP] Mounted MCP");
1823
+ console.log("[MCP] Mounting inspector");
1824
+ await this.mountInspector();
1825
+ console.log("[MCP] Mounted inspector");
1826
+ const fetchHandler = this.app.fetch.bind(this.app);
1827
+ if (options?.provider === "supabase") {
1828
+ return async (req) => {
1829
+ const url = new URL(req.url);
1830
+ const pathname = url.pathname;
1831
+ let newPathname = pathname;
1832
+ const functionsMatch = pathname.match(
1833
+ /^\/functions\/v1\/[^/]+(\/.*)?$/
1834
+ );
1835
+ if (functionsMatch) {
1836
+ newPathname = functionsMatch[1] || "/";
1837
+ } else {
1838
+ const functionNameMatch = pathname.match(/^\/([^/]+)(\/.*)?$/);
1839
+ if (functionNameMatch && functionNameMatch[2]) {
1840
+ newPathname = functionNameMatch[2] || "/";
1841
+ }
1842
+ }
1843
+ const newUrl = new URL(newPathname + url.search, url.origin);
1844
+ const newReq = new Request(newUrl, {
1845
+ method: req.method,
1846
+ headers: req.headers,
1847
+ body: req.body,
1848
+ redirect: req.redirect
1849
+ });
1850
+ const result = await fetchHandler(newReq);
1851
+ return result;
1852
+ };
1853
+ }
1854
+ return async (req) => {
1855
+ const result = await fetchHandler(req);
1856
+ return result;
1857
+ };
1286
1858
  }
1287
1859
  /**
1288
1860
  * Mount MCP Inspector UI at /inspector
@@ -1306,10 +1878,10 @@ if (container && Component) {
1306
1878
  * - Server continues to function normally
1307
1879
  * - No inspector UI available
1308
1880
  */
1309
- mountInspector() {
1881
+ async mountInspector() {
1310
1882
  if (this.inspectorMounted) return;
1311
1883
  if (this.isProductionMode()) {
1312
- const manifest = this.readBuildManifest();
1884
+ const manifest = await this.readBuildManifest();
1313
1885
  if (!manifest?.includeInspector) {
1314
1886
  console.log(
1315
1887
  "[INSPECTOR] Skipped in production (use --with-inspector flag during build)"
@@ -1317,19 +1889,20 @@ if (container && Component) {
1317
1889
  return;
1318
1890
  }
1319
1891
  }
1320
- import("@mcp-use/inspector").then(({ mountInspector }) => {
1892
+ try {
1893
+ const { mountInspector } = await import("@mcp-use/inspector");
1321
1894
  mountInspector(this.app);
1322
1895
  this.inspectorMounted = true;
1323
1896
  console.log(
1324
1897
  `[INSPECTOR] UI available at http://${this.serverHost}:${this.serverPort}/inspector`
1325
1898
  );
1326
- }).catch(() => {
1327
- });
1899
+ } catch {
1900
+ }
1328
1901
  }
1329
1902
  /**
1330
1903
  * Setup default widget serving routes
1331
1904
  *
1332
- * Configures Express routes to serve MCP UI widgets and their static assets.
1905
+ * Configures Hono routes to serve MCP UI widgets and their static assets.
1333
1906
  * Widgets are served from the dist/resources/widgets directory and can
1334
1907
  * be accessed via HTTP endpoints for embedding in web applications.
1335
1908
  *
@@ -1348,11 +1921,11 @@ if (container && Component) {
1348
1921
  * - http://localhost:3001/mcp-use/widgets/assets/script.js (auto-discovered)
1349
1922
  */
1350
1923
  setupWidgetRoutes() {
1351
- this.app.get("/mcp-use/widgets/:widget/assets/*", (req, res, next) => {
1352
- const widget = req.params.widget;
1353
- const assetFile = req.params[0];
1354
- const assetPath = join(
1355
- process.cwd(),
1924
+ this.app.get("/mcp-use/widgets/:widget/assets/*", async (c) => {
1925
+ const widget = c.req.param("widget");
1926
+ const assetFile = c.req.path.split("/assets/")[1];
1927
+ const assetPath = pathHelpers.join(
1928
+ getCwd(),
1356
1929
  "dist",
1357
1930
  "resources",
1358
1931
  "widgets",
@@ -1360,48 +1933,82 @@ if (container && Component) {
1360
1933
  "assets",
1361
1934
  assetFile
1362
1935
  );
1363
- res.sendFile(assetPath, (err) => err ? next() : void 0);
1936
+ try {
1937
+ if (await fsHelpers.existsSync(assetPath)) {
1938
+ const content = await fsHelpers.readFile(assetPath);
1939
+ const ext = assetFile.split(".").pop()?.toLowerCase();
1940
+ const contentType = ext === "js" ? "application/javascript" : ext === "css" ? "text/css" : ext === "png" ? "image/png" : ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "svg" ? "image/svg+xml" : "application/octet-stream";
1941
+ return new Response(content, {
1942
+ status: 200,
1943
+ headers: { "Content-Type": contentType }
1944
+ });
1945
+ }
1946
+ return c.notFound();
1947
+ } catch {
1948
+ return c.notFound();
1949
+ }
1364
1950
  });
1365
- this.app.get("/mcp-use/widgets/assets/*", (req, res, next) => {
1366
- const assetFile = req.params[0];
1367
- const widgetsDir = join(process.cwd(), "dist", "resources", "widgets");
1951
+ this.app.get("/mcp-use/widgets/assets/*", async (c) => {
1952
+ const assetFile = c.req.path.split("/assets/")[1];
1953
+ const widgetsDir = pathHelpers.join(
1954
+ getCwd(),
1955
+ "dist",
1956
+ "resources",
1957
+ "widgets"
1958
+ );
1368
1959
  try {
1369
- const widgets = readdirSync(widgetsDir);
1960
+ const widgets = await fsHelpers.readdirSync(widgetsDir);
1370
1961
  for (const widget of widgets) {
1371
- const assetPath = join(widgetsDir, widget, "assets", assetFile);
1372
- if (existsSync(assetPath)) {
1373
- return res.sendFile(assetPath);
1962
+ const assetPath = pathHelpers.join(
1963
+ widgetsDir,
1964
+ widget,
1965
+ "assets",
1966
+ assetFile
1967
+ );
1968
+ if (await fsHelpers.existsSync(assetPath)) {
1969
+ const content = await fsHelpers.readFile(assetPath);
1970
+ const ext = assetFile.split(".").pop()?.toLowerCase();
1971
+ const contentType = ext === "js" ? "application/javascript" : ext === "css" ? "text/css" : ext === "png" ? "image/png" : ext === "jpg" || ext === "jpeg" ? "image/jpeg" : ext === "svg" ? "image/svg+xml" : "application/octet-stream";
1972
+ return new Response(content, {
1973
+ status: 200,
1974
+ headers: { "Content-Type": contentType }
1975
+ });
1374
1976
  }
1375
1977
  }
1376
- next();
1978
+ return c.notFound();
1377
1979
  } catch {
1378
- next();
1980
+ return c.notFound();
1379
1981
  }
1380
1982
  });
1381
- this.app.get("/mcp-use/widgets/:widget", (req, res, next) => {
1382
- const filePath = join(
1383
- process.cwd(),
1983
+ this.app.get("/mcp-use/widgets/:widget", async (c) => {
1984
+ const widget = c.req.param("widget");
1985
+ const filePath = pathHelpers.join(
1986
+ getCwd(),
1384
1987
  "dist",
1385
1988
  "resources",
1386
1989
  "widgets",
1387
- req.params.widget,
1990
+ widget,
1388
1991
  "index.html"
1389
1992
  );
1390
- let html = readFileSync(filePath, "utf8");
1391
- html = html.replace(
1392
- /src="\/mcp-use\/widgets\/([^"]+)"/g,
1393
- `src="${this.serverBaseUrl}/mcp-use/widgets/$1"`
1394
- );
1395
- html = html.replace(
1396
- /href="\/mcp-use\/widgets\/([^"]+)"/g,
1397
- `href="${this.serverBaseUrl}/mcp-use/widgets/$1"`
1398
- );
1399
- html = html.replace(
1400
- /<head[^>]*>/i,
1401
- `<head>
1402
- <script>window.__getFile = (filename) => { return "${this.serverBaseUrl}/mcp-use/widgets/${req.params.widget}/"+filename }</script>`
1403
- );
1404
- res.send(html);
1993
+ try {
1994
+ let html = await fsHelpers.readFileSync(filePath, "utf8");
1995
+ html = html.replace(
1996
+ /src="\/mcp-use\/widgets\/([^"]+)"/g,
1997
+ `src="${this.serverBaseUrl}/mcp-use/widgets/$1"`
1998
+ );
1999
+ html = html.replace(
2000
+ /href="\/mcp-use\/widgets\/([^"]+)"/g,
2001
+ `href="${this.serverBaseUrl}/mcp-use/widgets/$1"`
2002
+ );
2003
+ html = html.replace(
2004
+ /<head[^>]*>/i,
2005
+ `<head>
2006
+ <script>window.__getFile = (filename) => { return "${this.serverBaseUrl}/mcp-use/widgets/${widget}/"+filename }</script>`
2007
+ );
2008
+ return c.html(html);
2009
+ } catch {
2010
+ return c.notFound();
2011
+ }
1405
2012
  });
1406
2013
  }
1407
2014
  /**
@@ -1595,10 +2202,13 @@ function createMCPServer(name, config = {}) {
1595
2202
  }
1596
2203
  __name(createMCPServer, "createMCPServer");
1597
2204
  export {
2205
+ adaptConnectMiddleware,
2206
+ adaptMiddleware,
1598
2207
  buildWidgetUrl,
1599
2208
  createExternalUrlResource,
1600
2209
  createMCPServer,
1601
2210
  createRawHtmlResource,
1602
2211
  createRemoteDomResource,
1603
- createUIResourceFromDefinition
2212
+ createUIResourceFromDefinition,
2213
+ isExpressMiddleware
1604
2214
  };