@mcpjam/inspector 0.8.2 → 0.9.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.
Files changed (180) hide show
  1. package/README.md +24 -6
  2. package/bin/start.js +78 -66
  3. package/dist/client/assets/index-C4nE74q5.css +1 -0
  4. package/dist/client/assets/index-CcfG-2LO.js +357 -0
  5. package/dist/client/assets/index-CcfG-2LO.js.map +1 -0
  6. package/dist/client/catalyst.png +0 -0
  7. package/dist/client/index.html +14 -0
  8. package/dist/main/main.cjs +1330 -0
  9. package/dist/preload/preload.js +26 -0
  10. package/dist/renderer/assets/index-CYiU4_x2.css +1 -0
  11. package/dist/renderer/assets/index-woGCpEdp.js +356 -0
  12. package/dist/renderer/catalyst.png +0 -0
  13. package/dist/renderer/demo_1.png +0 -0
  14. package/dist/renderer/demo_2.png +0 -0
  15. package/dist/renderer/demo_3.png +0 -0
  16. package/dist/renderer/file.svg +1 -0
  17. package/dist/renderer/globe.svg +1 -0
  18. package/dist/renderer/index.html +14 -0
  19. package/dist/renderer/mcp.svg +1 -0
  20. package/dist/renderer/mcp_jam.svg +12 -0
  21. package/dist/renderer/mcp_jam_dark.png +0 -0
  22. package/dist/renderer/mcp_jam_light.png +0 -0
  23. package/dist/renderer/next.svg +1 -0
  24. package/dist/renderer/vercel.svg +1 -0
  25. package/dist/renderer/window.svg +1 -0
  26. package/dist/server/index.js +1101 -0
  27. package/dist/server/index.js.map +1 -0
  28. package/package.json +32 -17
  29. package/.next/BUILD_ID +0 -1
  30. package/.next/app-build-manifest.json +0 -89
  31. package/.next/app-path-routes-manifest.json +0 -13
  32. package/.next/build-manifest.json +0 -33
  33. package/.next/cache/.previewinfo +0 -1
  34. package/.next/cache/.rscinfo +0 -1
  35. package/.next/cache/.tsbuildinfo +0 -1
  36. package/.next/cache/eslint/.cache_1pr0xfn +0 -1
  37. package/.next/cache/webpack/client-production/0.pack +0 -0
  38. package/.next/cache/webpack/client-production/index.pack +0 -0
  39. package/.next/cache/webpack/edge-server-production/0.pack +0 -0
  40. package/.next/cache/webpack/edge-server-production/index.pack +0 -0
  41. package/.next/cache/webpack/server-production/0.pack +0 -0
  42. package/.next/cache/webpack/server-production/index.pack +0 -0
  43. package/.next/diagnostics/build-diagnostics.json +0 -6
  44. package/.next/diagnostics/framework.json +0 -1
  45. package/.next/export-marker.json +0 -6
  46. package/.next/images-manifest.json +0 -57
  47. package/.next/next-minimal-server.js.nft.json +0 -1
  48. package/.next/next-server.js.nft.json +0 -1
  49. package/.next/package.json +0 -1
  50. package/.next/prerender-manifest.json +0 -41
  51. package/.next/react-loadable-manifest.json +0 -1
  52. package/.next/required-server-files.json +0 -318
  53. package/.next/routes-manifest.json +0 -65
  54. package/.next/server/app/_not-found/page.js +0 -2
  55. package/.next/server/app/_not-found/page.js.nft.json +0 -1
  56. package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  57. package/.next/server/app/api/mcp/chat/route.js +0 -45
  58. package/.next/server/app/api/mcp/chat/route.js.nft.json +0 -1
  59. package/.next/server/app/api/mcp/chat/route_client-reference-manifest.js +0 -1
  60. package/.next/server/app/api/mcp/connect/route.js +0 -1
  61. package/.next/server/app/api/mcp/connect/route.js.nft.json +0 -1
  62. package/.next/server/app/api/mcp/connect/route_client-reference-manifest.js +0 -1
  63. package/.next/server/app/api/mcp/prompts/get/route.js +0 -1
  64. package/.next/server/app/api/mcp/prompts/get/route.js.nft.json +0 -1
  65. package/.next/server/app/api/mcp/prompts/get/route_client-reference-manifest.js +0 -1
  66. package/.next/server/app/api/mcp/prompts/list/route.js +0 -1
  67. package/.next/server/app/api/mcp/prompts/list/route.js.nft.json +0 -1
  68. package/.next/server/app/api/mcp/prompts/list/route_client-reference-manifest.js +0 -1
  69. package/.next/server/app/api/mcp/resources/list/route.js +0 -1
  70. package/.next/server/app/api/mcp/resources/list/route.js.nft.json +0 -1
  71. package/.next/server/app/api/mcp/resources/list/route_client-reference-manifest.js +0 -1
  72. package/.next/server/app/api/mcp/resources/read/route.js +0 -1
  73. package/.next/server/app/api/mcp/resources/read/route.js.nft.json +0 -1
  74. package/.next/server/app/api/mcp/resources/read/route_client-reference-manifest.js +0 -1
  75. package/.next/server/app/api/mcp/tools/route.js +0 -21
  76. package/.next/server/app/api/mcp/tools/route.js.nft.json +0 -1
  77. package/.next/server/app/api/mcp/tools/route_client-reference-manifest.js +0 -1
  78. package/.next/server/app/favicon.ico/route.js +0 -1
  79. package/.next/server/app/favicon.ico/route.js.nft.json +0 -1
  80. package/.next/server/app/favicon.ico.body +0 -0
  81. package/.next/server/app/favicon.ico.meta +0 -1
  82. package/.next/server/app/oauth/callback/page.js +0 -2
  83. package/.next/server/app/oauth/callback/page.js.nft.json +0 -1
  84. package/.next/server/app/oauth/callback/page_client-reference-manifest.js +0 -1
  85. package/.next/server/app/page.js +0 -16
  86. package/.next/server/app/page.js.nft.json +0 -1
  87. package/.next/server/app/page_client-reference-manifest.js +0 -1
  88. package/.next/server/app-paths-manifest.json +0 -13
  89. package/.next/server/chunks/175.js +0 -8
  90. package/.next/server/chunks/260.js +0 -82
  91. package/.next/server/chunks/546.js +0 -1
  92. package/.next/server/chunks/548.js +0 -6
  93. package/.next/server/chunks/55.js +0 -1
  94. package/.next/server/chunks/985.js +0 -22
  95. package/.next/server/functions-config-manifest.json +0 -4
  96. package/.next/server/interception-route-rewrite-manifest.js +0 -1
  97. package/.next/server/middleware-build-manifest.js +0 -1
  98. package/.next/server/middleware-manifest.json +0 -6
  99. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  100. package/.next/server/next-font-manifest.js +0 -1
  101. package/.next/server/next-font-manifest.json +0 -1
  102. package/.next/server/pages/500.html +0 -1
  103. package/.next/server/pages/_app.js +0 -1
  104. package/.next/server/pages/_app.js.nft.json +0 -1
  105. package/.next/server/pages/_document.js +0 -1
  106. package/.next/server/pages/_document.js.nft.json +0 -1
  107. package/.next/server/pages/_error.js +0 -19
  108. package/.next/server/pages/_error.js.nft.json +0 -1
  109. package/.next/server/pages-manifest.json +0 -5
  110. package/.next/server/server-reference-manifest.js +0 -1
  111. package/.next/server/server-reference-manifest.json +0 -1
  112. package/.next/server/webpack-runtime.js +0 -1
  113. package/.next/static/SigynMKeJ0KJs0Nc9i0E-/_buildManifest.js +0 -1
  114. package/.next/static/SigynMKeJ0KJs0Nc9i0E-/_ssgManifest.js +0 -1
  115. package/.next/static/chunks/214-cc4c35d88f2695ed.js +0 -1
  116. package/.next/static/chunks/4bd1b696-cf72ae8a39fa05aa.js +0 -1
  117. package/.next/static/chunks/574-9365237f47ed3a68.js +0 -1
  118. package/.next/static/chunks/866-04c19dda4c52f2bf.js +0 -1
  119. package/.next/static/chunks/964-eda38e26c0391a47.js +0 -1
  120. package/.next/static/chunks/app/_not-found/page-8601c49989b0be94.js +0 -1
  121. package/.next/static/chunks/app/api/mcp/chat/route-0341498a8bf5f2da.js +0 -1
  122. package/.next/static/chunks/app/api/mcp/connect/route-0341498a8bf5f2da.js +0 -1
  123. package/.next/static/chunks/app/api/mcp/prompts/get/route-0341498a8bf5f2da.js +0 -1
  124. package/.next/static/chunks/app/api/mcp/prompts/list/route-0341498a8bf5f2da.js +0 -1
  125. package/.next/static/chunks/app/api/mcp/resources/list/route-0341498a8bf5f2da.js +0 -1
  126. package/.next/static/chunks/app/api/mcp/resources/read/route-0341498a8bf5f2da.js +0 -1
  127. package/.next/static/chunks/app/api/mcp/tools/route-0341498a8bf5f2da.js +0 -1
  128. package/.next/static/chunks/app/layout-9e8115d4bf656fa0.js +0 -1
  129. package/.next/static/chunks/app/oauth/callback/page-cf6cb1ac31175f40.js +0 -1
  130. package/.next/static/chunks/app/page-b0e3ed6257734413.js +0 -1
  131. package/.next/static/chunks/framework-7c95b8e5103c9e90.js +0 -1
  132. package/.next/static/chunks/main-app-4e9e28316818cdde.js +0 -1
  133. package/.next/static/chunks/main-bbdafee21a7bd1d6.js +0 -1
  134. package/.next/static/chunks/pages/_app-0a0020ddd67f79cf.js +0 -1
  135. package/.next/static/chunks/pages/_error-03529f2c21436739.js +0 -1
  136. package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  137. package/.next/static/chunks/webpack-cdfccaf38062dd25.js +0 -1
  138. package/.next/static/css/1e852d83e9c1d0c6.css +0 -1
  139. package/.next/static/css/f30152c0704fba31.css +0 -1
  140. package/.next/static/css/fe751fdbe975e9ca.css +0 -1
  141. package/.next/static/media/569ce4b8f30dc480-s.p.woff2 +0 -0
  142. package/.next/static/media/747892c23ea88013-s.woff2 +0 -0
  143. package/.next/static/media/8d697b304b401681-s.woff2 +0 -0
  144. package/.next/static/media/93f479601ee12b01-s.p.woff2 +0 -0
  145. package/.next/static/media/9610d9e46709d722-s.woff2 +0 -0
  146. package/.next/static/media/ba015fad6dcf6784-s.woff2 +0 -0
  147. package/.next/trace +0 -35
  148. package/.next/types/app/api/mcp/chat/route.ts +0 -347
  149. package/.next/types/app/api/mcp/connect/route.ts +0 -347
  150. package/.next/types/app/api/mcp/prompts/get/route.ts +0 -347
  151. package/.next/types/app/api/mcp/prompts/list/route.ts +0 -347
  152. package/.next/types/app/api/mcp/resources/list/route.ts +0 -347
  153. package/.next/types/app/api/mcp/resources/read/route.ts +0 -347
  154. package/.next/types/app/api/mcp/tools/route.ts +0 -347
  155. package/.next/types/app/layout.ts +0 -84
  156. package/.next/types/app/oauth/callback/page.ts +0 -84
  157. package/.next/types/app/page.ts +0 -84
  158. package/.next/types/cache-life.d.ts +0 -141
  159. package/.next/types/package.json +0 -1
  160. package/next.config.ts +0 -7
  161. /package/{public → dist/client}/claude_logo.png +0 -0
  162. /package/{public → dist/client}/demo_1.png +0 -0
  163. /package/{public → dist/client}/demo_2.png +0 -0
  164. /package/{public → dist/client}/demo_3.png +0 -0
  165. /package/{public → dist/client}/file.svg +0 -0
  166. /package/{public → dist/client}/globe.svg +0 -0
  167. /package/{public → dist/client}/mcp.svg +0 -0
  168. /package/{public → dist/client}/mcp_jam.svg +0 -0
  169. /package/{public → dist/client}/mcp_jam_dark.png +0 -0
  170. /package/{public → dist/client}/mcp_jam_light.png +0 -0
  171. /package/{public → dist/client}/next.svg +0 -0
  172. /package/{public → dist/client}/ollama_dark.png +0 -0
  173. /package/{public → dist/client}/ollama_logo.svg +0 -0
  174. /package/{public → dist/client}/openai_logo.png +0 -0
  175. /package/{public → dist/client}/vercel.svg +0 -0
  176. /package/{public → dist/client}/window.svg +0 -0
  177. /package/{.next/static/media/claude_logo.d33b25b0.png → dist/renderer/claude_logo.png} +0 -0
  178. /package/{.next/static/media/ollama_dark.9af45ac0.png → dist/renderer/ollama_dark.png} +0 -0
  179. /package/{.next/static/media/ollama_logo.9f08a95b.svg → dist/renderer/ollama_logo.svg} +0 -0
  180. /package/{.next/static/media/openai_logo.3f83154a.png → dist/renderer/openai_logo.png} +0 -0
@@ -0,0 +1,1101 @@
1
+ // index.ts
2
+ import { serve } from "@hono/node-server";
3
+ import { Hono as Hono8 } from "hono";
4
+ import { cors } from "hono/cors";
5
+ import { logger } from "hono/logger";
6
+ import { serveStatic } from "@hono/node-server/serve-static";
7
+ import { readFileSync } from "fs";
8
+ import { join } from "path";
9
+
10
+ // routes/mcp/index.ts
11
+ import { Hono as Hono7 } from "hono";
12
+
13
+ // routes/mcp/connect.ts
14
+ import { Hono } from "hono";
15
+
16
+ // utils/mcp-utils.ts
17
+ import { MCPClient } from "@mastra/mcp";
18
+ function validateServerConfig(serverConfig) {
19
+ if (!serverConfig) {
20
+ return {
21
+ success: false,
22
+ error: {
23
+ message: "Server configuration is required",
24
+ status: 400
25
+ }
26
+ };
27
+ }
28
+ const config = { ...serverConfig };
29
+ if (config.url) {
30
+ try {
31
+ if (typeof config.url === "string") {
32
+ config.url = new URL(config.url);
33
+ } else if (typeof config.url === "object" && !config.url.href) {
34
+ return {
35
+ success: false,
36
+ error: {
37
+ message: "Invalid URL configuration",
38
+ status: 400
39
+ }
40
+ };
41
+ }
42
+ if (config.oauth?.access_token) {
43
+ const authHeaders = {
44
+ Authorization: `Bearer ${config.oauth.access_token}`,
45
+ ...config.requestInit?.headers || {}
46
+ };
47
+ config.requestInit = {
48
+ ...config.requestInit,
49
+ headers: authHeaders
50
+ };
51
+ config.eventSourceInit = {
52
+ fetch(input, init) {
53
+ const headers = new Headers(init?.headers || {});
54
+ headers.set(
55
+ "Authorization",
56
+ `Bearer ${config.oauth.access_token}`
57
+ );
58
+ if (config.requestInit?.headers) {
59
+ const requestHeaders = new Headers(config.requestInit.headers);
60
+ requestHeaders.forEach((value, key) => {
61
+ if (key.toLowerCase() !== "authorization") {
62
+ headers.set(key, value);
63
+ }
64
+ });
65
+ }
66
+ return fetch(input, {
67
+ ...init,
68
+ headers
69
+ });
70
+ }
71
+ };
72
+ } else if (config.requestInit?.headers) {
73
+ config.eventSourceInit = {
74
+ fetch(input, init) {
75
+ const headers = new Headers(init?.headers || {});
76
+ const requestHeaders = new Headers(config.requestInit.headers);
77
+ requestHeaders.forEach((value, key) => {
78
+ headers.set(key, value);
79
+ });
80
+ return fetch(input, {
81
+ ...init,
82
+ headers
83
+ });
84
+ }
85
+ };
86
+ }
87
+ } catch (error) {
88
+ return {
89
+ success: false,
90
+ error: {
91
+ message: `Invalid URL format: ${error}`,
92
+ status: 400
93
+ }
94
+ };
95
+ }
96
+ }
97
+ return {
98
+ success: true,
99
+ config
100
+ };
101
+ }
102
+ function createMCPClient(config, id) {
103
+ return new MCPClient({
104
+ id,
105
+ servers: {
106
+ server: config
107
+ }
108
+ });
109
+ }
110
+ var validateMultipleServerConfigs = (serverConfigs) => {
111
+ if (!serverConfigs || Object.keys(serverConfigs).length === 0) {
112
+ return {
113
+ success: false,
114
+ error: {
115
+ message: "At least one server configuration is required",
116
+ status: 400
117
+ }
118
+ };
119
+ }
120
+ const validConfigs = {};
121
+ const errors = {};
122
+ let hasErrors = false;
123
+ for (const [serverName, serverConfig] of Object.entries(serverConfigs)) {
124
+ const validationResult = validateServerConfig(serverConfig);
125
+ if (validationResult.success && validationResult.config) {
126
+ validConfigs[serverName] = validationResult.config;
127
+ } else {
128
+ hasErrors = true;
129
+ let errorMessage = "Configuration validation failed";
130
+ if (validationResult.error) {
131
+ errorMessage = validationResult.error.message;
132
+ }
133
+ errors[serverName] = errorMessage;
134
+ }
135
+ }
136
+ if (!hasErrors) {
137
+ return {
138
+ success: true,
139
+ validConfigs
140
+ };
141
+ }
142
+ if (Object.keys(validConfigs).length > 0) {
143
+ return {
144
+ success: false,
145
+ validConfigs,
146
+ errors
147
+ };
148
+ }
149
+ return {
150
+ success: false,
151
+ errors,
152
+ error: {
153
+ message: "All server configurations failed validation",
154
+ status: 400
155
+ }
156
+ };
157
+ };
158
+ function createMCPClientWithMultipleConnections(serverConfigs) {
159
+ const normalizedConfigs = {};
160
+ for (const [serverName, config] of Object.entries(serverConfigs)) {
161
+ const normalizedName = normalizeServerConfigName(serverName);
162
+ normalizedConfigs[normalizedName] = config;
163
+ }
164
+ return new MCPClient({
165
+ id: `chat-${Date.now()}`,
166
+ servers: normalizedConfigs
167
+ });
168
+ }
169
+ function normalizeServerConfigName(serverName) {
170
+ return serverName.toLowerCase().replace(/[\s\-]+/g, "_").replace(/[^a-z0-9_]/g, "");
171
+ }
172
+
173
+ // routes/mcp/connect.ts
174
+ var connect = new Hono();
175
+ connect.post("/", async (c) => {
176
+ try {
177
+ const { serverConfig } = await c.req.json();
178
+ const validation = validateServerConfig(serverConfig);
179
+ if (!validation.success) {
180
+ const error = validation.error;
181
+ return c.json(
182
+ {
183
+ success: false,
184
+ error: error.message
185
+ },
186
+ error.status
187
+ );
188
+ }
189
+ let client;
190
+ try {
191
+ client = createMCPClient(validation.config, `test-${Date.now()}`);
192
+ } catch (error) {
193
+ return c.json(
194
+ {
195
+ success: false,
196
+ error: `Failed to create a MCP client. Please double check your server configuration: ${JSON.stringify(serverConfig)}`,
197
+ details: error instanceof Error ? error.message : "Unknown error"
198
+ },
199
+ 500
200
+ );
201
+ }
202
+ try {
203
+ await client.getTools();
204
+ await client.disconnect();
205
+ return c.json({
206
+ success: true
207
+ });
208
+ } catch (error) {
209
+ return c.json(
210
+ {
211
+ success: false,
212
+ error: `MCP configuration is invalid. Please double check your server configuration: ${JSON.stringify(serverConfig)}`,
213
+ details: error instanceof Error ? error.message : "Unknown error"
214
+ },
215
+ 500
216
+ );
217
+ }
218
+ } catch (error) {
219
+ return c.json(
220
+ {
221
+ success: false,
222
+ error: "Failed to parse request body",
223
+ details: error instanceof Error ? error.message : "Unknown error"
224
+ },
225
+ 400
226
+ );
227
+ }
228
+ });
229
+ var connect_default = connect;
230
+
231
+ // routes/mcp/tools.ts
232
+ import { Hono as Hono2 } from "hono";
233
+ import { zodToJsonSchema } from "zod-to-json-schema";
234
+ var tools = new Hono2();
235
+ var pendingElicitations = /* @__PURE__ */ new Map();
236
+ tools.post("/", async (c) => {
237
+ let client = null;
238
+ let encoder = null;
239
+ let streamController = null;
240
+ let action;
241
+ let toolName;
242
+ try {
243
+ const requestData = await c.req.json();
244
+ action = requestData.action;
245
+ toolName = requestData.toolName;
246
+ const { serverConfig, parameters, requestId, response } = requestData;
247
+ if (!action || !["list", "execute", "respond"].includes(action)) {
248
+ return c.json(
249
+ {
250
+ success: false,
251
+ error: "Action must be 'list', 'execute', or 'respond'"
252
+ },
253
+ 400
254
+ );
255
+ }
256
+ if (action === "respond") {
257
+ if (!requestId) {
258
+ return c.json(
259
+ {
260
+ success: false,
261
+ error: "requestId is required for respond action"
262
+ },
263
+ 400
264
+ );
265
+ }
266
+ const pending = pendingElicitations.get(requestId);
267
+ if (!pending) {
268
+ return c.json(
269
+ {
270
+ success: false,
271
+ error: "No pending elicitation found for this requestId"
272
+ },
273
+ 404
274
+ );
275
+ }
276
+ pending.resolve(response);
277
+ pendingElicitations.delete(requestId);
278
+ return c.json({ success: true });
279
+ }
280
+ const validation = validateServerConfig(serverConfig);
281
+ if (!validation.success) {
282
+ return c.json(
283
+ { success: false, error: validation.error.message },
284
+ validation.error.status
285
+ );
286
+ }
287
+ encoder = new TextEncoder();
288
+ const readableStream = new ReadableStream({
289
+ async start(controller) {
290
+ streamController = controller;
291
+ try {
292
+ const clientId = `tools-${action}-${Date.now()}`;
293
+ client = createMCPClient(validation.config, clientId);
294
+ if (action === "list") {
295
+ controller.enqueue(
296
+ encoder.encode(
297
+ `data: ${JSON.stringify({
298
+ type: "tools_loading",
299
+ message: "Fetching tools from server..."
300
+ })}
301
+
302
+ `
303
+ )
304
+ );
305
+ const tools2 = await client.getTools();
306
+ const toolsWithJsonSchema = Object.fromEntries(
307
+ Object.entries(tools2).map(([toolName2, tool]) => {
308
+ return [
309
+ toolName2,
310
+ {
311
+ ...tool,
312
+ inputSchema: zodToJsonSchema(
313
+ tool.inputSchema
314
+ )
315
+ }
316
+ ];
317
+ })
318
+ );
319
+ controller.enqueue(
320
+ encoder.encode(
321
+ `data: ${JSON.stringify({
322
+ type: "tools_list",
323
+ tools: toolsWithJsonSchema
324
+ })}
325
+
326
+ `
327
+ )
328
+ );
329
+ } else if (action === "execute") {
330
+ if (!toolName) {
331
+ controller.enqueue(
332
+ encoder.encode(
333
+ `data: ${JSON.stringify({
334
+ type: "tool_error",
335
+ error: "Tool name is required for execution"
336
+ })}
337
+
338
+ `
339
+ )
340
+ );
341
+ return;
342
+ }
343
+ controller.enqueue(
344
+ encoder.encode(
345
+ `data: ${JSON.stringify({
346
+ type: "tool_executing",
347
+ toolName,
348
+ parameters: parameters || {},
349
+ message: "Executing tool..."
350
+ })}
351
+
352
+ `
353
+ )
354
+ );
355
+ const tools2 = await client.getTools();
356
+ const tool = tools2[toolName];
357
+ if (!tool) {
358
+ controller.enqueue(
359
+ encoder.encode(
360
+ `data: ${JSON.stringify({
361
+ type: "tool_error",
362
+ error: `Tool '${toolName}' not found`
363
+ })}
364
+
365
+ `
366
+ )
367
+ );
368
+ return;
369
+ }
370
+ const toolArgs = parameters && typeof parameters === "object" ? parameters : {};
371
+ const elicitationHandler = async (elicitationRequest) => {
372
+ const requestId2 = `elicit_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
373
+ if (streamController && encoder) {
374
+ streamController.enqueue(
375
+ encoder.encode(
376
+ `data: ${JSON.stringify({
377
+ type: "elicitation_request",
378
+ requestId: requestId2,
379
+ message: elicitationRequest.message,
380
+ schema: elicitationRequest.requestedSchema,
381
+ timestamp: /* @__PURE__ */ new Date()
382
+ })}
383
+
384
+ `
385
+ )
386
+ );
387
+ }
388
+ return new Promise((resolve, reject) => {
389
+ pendingElicitations.set(requestId2, { resolve, reject });
390
+ setTimeout(() => {
391
+ if (pendingElicitations.has(requestId2)) {
392
+ pendingElicitations.delete(requestId2);
393
+ reject(new Error("Elicitation timeout"));
394
+ }
395
+ }, 3e5);
396
+ });
397
+ };
398
+ if (client.elicitation && client.elicitation.onRequest) {
399
+ const serverName = "server";
400
+ client.elicitation.onRequest(serverName, elicitationHandler);
401
+ }
402
+ const result = await tool.execute({
403
+ context: toolArgs
404
+ });
405
+ controller.enqueue(
406
+ encoder.encode(
407
+ `data: ${JSON.stringify({
408
+ type: "tool_result",
409
+ toolName,
410
+ result
411
+ })}
412
+
413
+ `
414
+ )
415
+ );
416
+ controller.enqueue(
417
+ encoder.encode(
418
+ `data: ${JSON.stringify({
419
+ type: "elicitation_complete",
420
+ toolName
421
+ })}
422
+
423
+ `
424
+ )
425
+ );
426
+ }
427
+ controller.enqueue(encoder.encode(`data: [DONE]
428
+
429
+ `));
430
+ } catch (error) {
431
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
432
+ controller.enqueue(
433
+ encoder.encode(
434
+ `data: ${JSON.stringify({
435
+ type: "tool_error",
436
+ error: errorMsg
437
+ })}
438
+
439
+ `
440
+ )
441
+ );
442
+ } finally {
443
+ if (client) {
444
+ await client.disconnect();
445
+ }
446
+ controller.close();
447
+ }
448
+ }
449
+ });
450
+ return new Response(readableStream, {
451
+ headers: {
452
+ "Content-Type": "text/event-stream",
453
+ "Cache-Control": "no-cache",
454
+ Connection: "keep-alive"
455
+ }
456
+ });
457
+ } catch (error) {
458
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
459
+ if (client) {
460
+ try {
461
+ await client.disconnect();
462
+ } catch (cleanupError) {
463
+ }
464
+ }
465
+ return c.json(
466
+ {
467
+ success: false,
468
+ error: errorMsg
469
+ },
470
+ 500
471
+ );
472
+ }
473
+ });
474
+ var tools_default = tools;
475
+
476
+ // routes/mcp/resources.ts
477
+ import { Hono as Hono3 } from "hono";
478
+ var resources = new Hono3();
479
+ resources.post("/list", async (c) => {
480
+ try {
481
+ const { serverConfig } = await c.req.json();
482
+ const validation = validateServerConfig(serverConfig);
483
+ if (!validation.success) {
484
+ return c.json(
485
+ { success: false, error: validation.error.message },
486
+ validation.error.status
487
+ );
488
+ }
489
+ const client = createMCPClient(
490
+ validation.config,
491
+ `resources-list-${Date.now()}`
492
+ );
493
+ try {
494
+ const resources2 = await client.resources.list();
495
+ await client.disconnect();
496
+ return c.json({ resources: resources2 });
497
+ } catch (error) {
498
+ await client.disconnect();
499
+ throw error;
500
+ }
501
+ } catch (error) {
502
+ console.error("Error fetching resources:", error);
503
+ return c.json(
504
+ {
505
+ success: false,
506
+ error: error instanceof Error ? error.message : "Unknown error"
507
+ },
508
+ 500
509
+ );
510
+ }
511
+ });
512
+ resources.post("/read", async (c) => {
513
+ try {
514
+ const { serverConfig, uri } = await c.req.json();
515
+ const validation = validateServerConfig(serverConfig);
516
+ if (!validation.success) {
517
+ return c.json(
518
+ { success: false, error: validation.error.message },
519
+ validation.error.status
520
+ );
521
+ }
522
+ if (!uri) {
523
+ return c.json(
524
+ {
525
+ success: false,
526
+ error: "Resource URI is required"
527
+ },
528
+ 400
529
+ );
530
+ }
531
+ const client = createMCPClient(
532
+ validation.config,
533
+ `resources-read-${Date.now()}`
534
+ );
535
+ try {
536
+ const content = await client.resources.read("server", uri);
537
+ await client.disconnect();
538
+ return c.json({ content });
539
+ } catch (error) {
540
+ await client.disconnect();
541
+ throw error;
542
+ }
543
+ } catch (error) {
544
+ console.error("Error reading resource:", error);
545
+ return c.json(
546
+ {
547
+ success: false,
548
+ error: error instanceof Error ? error.message : "Unknown error"
549
+ },
550
+ 500
551
+ );
552
+ }
553
+ });
554
+ var resources_default = resources;
555
+
556
+ // routes/mcp/prompts.ts
557
+ import { Hono as Hono4 } from "hono";
558
+ var prompts = new Hono4();
559
+ prompts.post("/list", async (c) => {
560
+ try {
561
+ const { serverConfig } = await c.req.json();
562
+ const validation = validateServerConfig(serverConfig);
563
+ if (!validation.success) {
564
+ return c.json(
565
+ { success: false, error: validation.error.message },
566
+ validation.error.status
567
+ );
568
+ }
569
+ const client = createMCPClient(
570
+ validation.config,
571
+ `prompts-list-${Date.now()}`
572
+ );
573
+ try {
574
+ const prompts2 = await client.prompts.list();
575
+ await client.disconnect();
576
+ return c.json({ prompts: prompts2 });
577
+ } catch (error) {
578
+ await client.disconnect();
579
+ throw error;
580
+ }
581
+ } catch (error) {
582
+ console.error("Error fetching prompts:", error);
583
+ return c.json(
584
+ {
585
+ success: false,
586
+ error: error instanceof Error ? error.message : "Unknown error"
587
+ },
588
+ 500
589
+ );
590
+ }
591
+ });
592
+ prompts.post("/get", async (c) => {
593
+ try {
594
+ const { serverConfig, name, args } = await c.req.json();
595
+ const validation = validateServerConfig(serverConfig);
596
+ if (!validation.success) {
597
+ return c.json(
598
+ { success: false, error: validation.error.message },
599
+ validation.error.status
600
+ );
601
+ }
602
+ if (!name) {
603
+ return c.json(
604
+ {
605
+ success: false,
606
+ error: "Prompt name is required"
607
+ },
608
+ 400
609
+ );
610
+ }
611
+ const client = createMCPClient(
612
+ validation.config,
613
+ `prompts-get-${Date.now()}`
614
+ );
615
+ try {
616
+ const content = await client.prompts.get({
617
+ serverName: "server",
618
+ name,
619
+ args: args || {}
620
+ });
621
+ await client.disconnect();
622
+ return c.json({ content });
623
+ } catch (error) {
624
+ await client.disconnect();
625
+ throw error;
626
+ }
627
+ } catch (error) {
628
+ console.error("Error getting prompt:", error);
629
+ return c.json(
630
+ {
631
+ success: false,
632
+ error: error instanceof Error ? error.message : "Unknown error"
633
+ },
634
+ 500
635
+ );
636
+ }
637
+ });
638
+ var prompts_default = prompts;
639
+
640
+ // routes/mcp/chat.ts
641
+ import { Hono as Hono5 } from "hono";
642
+ import { Agent } from "@mastra/core/agent";
643
+ import { createAnthropic } from "@ai-sdk/anthropic";
644
+ import { createOpenAI } from "@ai-sdk/openai";
645
+ import { createOllama } from "ollama-ai-provider";
646
+ import { MCPClient as MCPClient2 } from "@mastra/mcp";
647
+ var chat = new Hono5();
648
+ var pendingElicitations2 = /* @__PURE__ */ new Map();
649
+ chat.post("/", async (c) => {
650
+ let client = null;
651
+ try {
652
+ const requestData = await c.req.json();
653
+ const {
654
+ serverConfigs,
655
+ model,
656
+ apiKey,
657
+ systemPrompt,
658
+ messages,
659
+ ollamaBaseUrl,
660
+ action,
661
+ requestId,
662
+ response
663
+ } = requestData;
664
+ if (action === "elicitation_response") {
665
+ if (!requestId) {
666
+ return c.json(
667
+ {
668
+ success: false,
669
+ error: "requestId is required for elicitation_response action"
670
+ },
671
+ 400
672
+ );
673
+ }
674
+ const pending = pendingElicitations2.get(requestId);
675
+ if (!pending) {
676
+ return c.json(
677
+ {
678
+ success: false,
679
+ error: "No pending elicitation found for this requestId"
680
+ },
681
+ 404
682
+ );
683
+ }
684
+ pending.resolve(response);
685
+ pendingElicitations2.delete(requestId);
686
+ return c.json({ success: true });
687
+ }
688
+ if (!model || !model.id || !apiKey || !messages) {
689
+ return c.json(
690
+ {
691
+ success: false,
692
+ error: "model (with id), apiKey, and messages are required"
693
+ },
694
+ 400
695
+ );
696
+ }
697
+ if (serverConfigs && Object.keys(serverConfigs).length > 0) {
698
+ const validation = validateMultipleServerConfigs(serverConfigs);
699
+ if (!validation.success) {
700
+ return c.json(
701
+ {
702
+ success: false,
703
+ error: validation.error.message,
704
+ details: validation.errors
705
+ },
706
+ validation.error.status
707
+ );
708
+ }
709
+ client = createMCPClientWithMultipleConnections(validation.validConfigs);
710
+ } else {
711
+ client = new MCPClient2({
712
+ id: `chat-${Date.now()}`,
713
+ servers: {}
714
+ });
715
+ }
716
+ const tools2 = await client.getTools();
717
+ const llmModel = getLlmModel(model, apiKey, ollamaBaseUrl);
718
+ let toolCallId = 0;
719
+ let streamController = null;
720
+ let encoder = null;
721
+ const elicitationHandler = async (elicitationRequest) => {
722
+ const requestId2 = `elicit_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`;
723
+ if (streamController && encoder) {
724
+ streamController.enqueue(
725
+ encoder.encode(
726
+ `data: ${JSON.stringify({
727
+ type: "elicitation_request",
728
+ requestId: requestId2,
729
+ message: elicitationRequest.message,
730
+ schema: elicitationRequest.requestedSchema,
731
+ timestamp: /* @__PURE__ */ new Date()
732
+ })}
733
+
734
+ `
735
+ )
736
+ );
737
+ }
738
+ return new Promise((resolve, reject) => {
739
+ pendingElicitations2.set(requestId2, { resolve, reject });
740
+ setTimeout(() => {
741
+ if (pendingElicitations2.has(requestId2)) {
742
+ pendingElicitations2.delete(requestId2);
743
+ reject(new Error("Elicitation timeout"));
744
+ }
745
+ }, 3e5);
746
+ });
747
+ };
748
+ if (client.elicitation && client.elicitation.onRequest && serverConfigs) {
749
+ for (const serverName of Object.keys(serverConfigs)) {
750
+ const normalizedName = serverName.toLowerCase().replace(/[\s\-]+/g, "_").replace(/[^a-z0-9_]/g, "");
751
+ client.elicitation.onRequest(normalizedName, elicitationHandler);
752
+ }
753
+ }
754
+ const originalTools = tools2 && Object.keys(tools2).length > 0 ? tools2 : {};
755
+ const wrappedTools = {};
756
+ for (const [name, tool] of Object.entries(originalTools)) {
757
+ wrappedTools[name] = {
758
+ ...tool,
759
+ execute: async (params) => {
760
+ const currentToolCallId = ++toolCallId;
761
+ if (streamController && encoder) {
762
+ streamController.enqueue(
763
+ encoder.encode(
764
+ `data: ${JSON.stringify({
765
+ type: "tool_call",
766
+ toolCall: {
767
+ id: currentToolCallId,
768
+ name,
769
+ parameters: params,
770
+ timestamp: /* @__PURE__ */ new Date(),
771
+ status: "executing"
772
+ }
773
+ })}
774
+
775
+ `
776
+ )
777
+ );
778
+ }
779
+ try {
780
+ const result = await tool.execute(params);
781
+ if (streamController && encoder) {
782
+ streamController.enqueue(
783
+ encoder.encode(
784
+ `data: ${JSON.stringify({
785
+ type: "tool_result",
786
+ toolResult: {
787
+ id: currentToolCallId,
788
+ toolCallId: currentToolCallId,
789
+ result,
790
+ timestamp: /* @__PURE__ */ new Date()
791
+ }
792
+ })}
793
+
794
+ `
795
+ )
796
+ );
797
+ }
798
+ return result;
799
+ } catch (error) {
800
+ if (streamController && encoder) {
801
+ streamController.enqueue(
802
+ encoder.encode(
803
+ `data: ${JSON.stringify({
804
+ type: "tool_result",
805
+ toolResult: {
806
+ id: currentToolCallId,
807
+ toolCallId: currentToolCallId,
808
+ error: error instanceof Error ? error.message : String(error),
809
+ timestamp: /* @__PURE__ */ new Date()
810
+ }
811
+ })}
812
+
813
+ `
814
+ )
815
+ );
816
+ }
817
+ throw error;
818
+ }
819
+ }
820
+ };
821
+ }
822
+ const agent = new Agent({
823
+ name: "MCP Chat Agent",
824
+ instructions: systemPrompt || "You are a helpful assistant with access to MCP tools.",
825
+ model: llmModel,
826
+ tools: Object.keys(wrappedTools).length > 0 ? wrappedTools : void 0
827
+ });
828
+ const formattedMessages = messages.map((msg) => ({
829
+ role: msg.role,
830
+ content: msg.content
831
+ }));
832
+ const stream = await agent.stream(formattedMessages, {
833
+ maxSteps: 10
834
+ // Allow up to 10 steps for tool usage
835
+ });
836
+ encoder = new TextEncoder();
837
+ const readableStream = new ReadableStream({
838
+ async start(controller) {
839
+ streamController = controller;
840
+ try {
841
+ let hasContent = false;
842
+ for await (const chunk of stream.textStream) {
843
+ if (chunk && chunk.trim()) {
844
+ hasContent = true;
845
+ controller.enqueue(
846
+ encoder.encode(
847
+ `data: ${JSON.stringify({ type: "text", content: chunk })}
848
+
849
+ `
850
+ )
851
+ );
852
+ }
853
+ }
854
+ if (!hasContent) {
855
+ controller.enqueue(
856
+ encoder.encode(
857
+ `data: ${JSON.stringify({ type: "text", content: "I apologize, but I couldn't generate a response. Please try again." })}
858
+
859
+ `
860
+ )
861
+ );
862
+ }
863
+ controller.enqueue(
864
+ encoder.encode(
865
+ `data: ${JSON.stringify({
866
+ type: "elicitation_complete"
867
+ })}
868
+
869
+ `
870
+ )
871
+ );
872
+ controller.enqueue(encoder.encode(`data: [DONE]
873
+
874
+ `));
875
+ } catch (error) {
876
+ console.error("Streaming error:", error);
877
+ controller.enqueue(
878
+ encoder.encode(
879
+ `data: ${JSON.stringify({
880
+ type: "error",
881
+ error: error instanceof Error ? error.message : "Unknown error"
882
+ })}
883
+
884
+ `
885
+ )
886
+ );
887
+ } finally {
888
+ if (client) {
889
+ try {
890
+ await client.disconnect();
891
+ } catch (cleanupError) {
892
+ console.warn(
893
+ "Error cleaning up MCP client after streaming:",
894
+ cleanupError
895
+ );
896
+ }
897
+ }
898
+ controller.close();
899
+ }
900
+ }
901
+ });
902
+ return new Response(readableStream, {
903
+ headers: {
904
+ "Content-Type": "text/event-stream",
905
+ "Cache-Control": "no-cache",
906
+ Connection: "keep-alive"
907
+ }
908
+ });
909
+ } catch (error) {
910
+ console.error("Error in chat API:", error);
911
+ if (client) {
912
+ try {
913
+ await client.disconnect();
914
+ } catch (cleanupError) {
915
+ console.warn("Error cleaning up MCP client after error:", cleanupError);
916
+ }
917
+ }
918
+ return c.json(
919
+ {
920
+ success: false,
921
+ error: error instanceof Error ? error.message : "Unknown error"
922
+ },
923
+ 500
924
+ );
925
+ }
926
+ });
927
+ var getLlmModel = (modelDefinition, apiKey, ollamaBaseUrl) => {
928
+ if (!modelDefinition || !modelDefinition.id || !modelDefinition.provider) {
929
+ throw new Error(
930
+ `Invalid model definition: ${JSON.stringify(modelDefinition)}`
931
+ );
932
+ }
933
+ switch (modelDefinition.provider) {
934
+ case "anthropic":
935
+ return createAnthropic({ apiKey })(modelDefinition.id);
936
+ case "openai":
937
+ return createOpenAI({ apiKey })(modelDefinition.id);
938
+ case "ollama":
939
+ const baseUrl = ollamaBaseUrl || "http://localhost:11434";
940
+ return createOllama({
941
+ baseURL: `${baseUrl}/api`
942
+ // Configurable Ollama API endpoint
943
+ })(modelDefinition.id, {
944
+ simulateStreaming: true
945
+ // Enable streaming for Ollama models
946
+ });
947
+ default:
948
+ throw new Error(
949
+ `Unsupported provider: ${modelDefinition.provider} for model: ${modelDefinition.id}`
950
+ );
951
+ }
952
+ };
953
+ var chat_default = chat;
954
+
955
+ // routes/mcp/oauth.ts
956
+ import { Hono as Hono6 } from "hono";
957
+ var oauth = new Hono6();
958
+ oauth.get("/metadata", async (c) => {
959
+ try {
960
+ const url = c.req.query("url");
961
+ if (!url) {
962
+ return c.json({ error: "Missing url parameter" }, 400);
963
+ }
964
+ let metadataUrl;
965
+ try {
966
+ metadataUrl = new URL(url);
967
+ if (metadataUrl.protocol !== "https:") {
968
+ return c.json({ error: "Only HTTPS URLs are allowed" }, 400);
969
+ }
970
+ } catch (error) {
971
+ return c.json({ error: "Invalid URL format" }, 400);
972
+ }
973
+ const response = await fetch(metadataUrl.toString(), {
974
+ method: "GET",
975
+ headers: {
976
+ Accept: "application/json",
977
+ "User-Agent": "MCP-Inspector/1.0"
978
+ }
979
+ });
980
+ if (!response.ok) {
981
+ return c.json(
982
+ {
983
+ error: `Failed to fetch OAuth metadata: ${response.status} ${response.statusText}`
984
+ },
985
+ response.status
986
+ );
987
+ }
988
+ const metadata = await response.json();
989
+ return c.json(metadata);
990
+ } catch (error) {
991
+ console.error("OAuth metadata proxy error:", error);
992
+ return c.json(
993
+ {
994
+ error: error instanceof Error ? error.message : "Unknown error occurred"
995
+ },
996
+ 500
997
+ );
998
+ }
999
+ });
1000
+ var oauth_default = oauth;
1001
+
1002
+ // routes/mcp/index.ts
1003
+ var mcp = new Hono7();
1004
+ mcp.get("/health", (c) => {
1005
+ return c.json({
1006
+ service: "MCP API",
1007
+ status: "ready",
1008
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1009
+ });
1010
+ });
1011
+ mcp.route("/chat", chat_default);
1012
+ mcp.route("/connect", connect_default);
1013
+ mcp.route("/tools", tools_default);
1014
+ mcp.route("/resources", resources_default);
1015
+ mcp.route("/prompts", prompts_default);
1016
+ mcp.route("/oauth", oauth_default);
1017
+ var mcp_default = mcp;
1018
+
1019
+ // index.ts
1020
+ function logBox(content, title) {
1021
+ const lines = content.split("\n");
1022
+ const maxLength = Math.max(...lines.map((line) => line.length));
1023
+ const width = maxLength + 4;
1024
+ console.log("\u250C" + "\u2500".repeat(width) + "\u2510");
1025
+ if (title) {
1026
+ const titlePadding = Math.floor((width - title.length - 2) / 2);
1027
+ console.log(
1028
+ "\u2502" + " ".repeat(titlePadding) + title + " ".repeat(width - title.length - titlePadding) + "\u2502"
1029
+ );
1030
+ console.log("\u251C" + "\u2500".repeat(width) + "\u2524");
1031
+ }
1032
+ lines.forEach((line) => {
1033
+ const padding = width - line.length - 2;
1034
+ console.log("\u2502 " + line + " ".repeat(padding) + " \u2502");
1035
+ });
1036
+ console.log("\u2514" + "\u2500".repeat(width) + "\u2518");
1037
+ }
1038
+ var app = new Hono8();
1039
+ app.use("*", logger());
1040
+ var serverPort = process.env.PORT || "3001";
1041
+ var corsOrigins = [
1042
+ `http://localhost:${serverPort}`,
1043
+ "http://localhost:3000",
1044
+ // Keep for development
1045
+ "http://localhost:3001"
1046
+ // Keep for development
1047
+ ];
1048
+ app.use(
1049
+ "*",
1050
+ cors({
1051
+ origin: corsOrigins,
1052
+ credentials: true
1053
+ })
1054
+ );
1055
+ app.route("/api/mcp", mcp_default);
1056
+ app.get("/health", (c) => {
1057
+ return c.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
1058
+ });
1059
+ if (process.env.NODE_ENV === "production") {
1060
+ app.use("/*", serveStatic({ root: "./dist/client" }));
1061
+ app.get("*", async (c) => {
1062
+ const path = c.req.path;
1063
+ if (path.startsWith("/api/")) {
1064
+ return c.notFound();
1065
+ }
1066
+ const indexPath = join(process.cwd(), "dist", "client", "index.html");
1067
+ const htmlContent = readFileSync(indexPath, "utf-8");
1068
+ return c.html(htmlContent);
1069
+ });
1070
+ } else {
1071
+ app.get("/", (c) => {
1072
+ return c.json({
1073
+ message: "MCP Inspector API Server",
1074
+ environment: "development",
1075
+ frontend: `http://localhost:${serverPort}`
1076
+ });
1077
+ });
1078
+ }
1079
+ var port = parseInt(process.env.PORT || "3001");
1080
+ logBox(`http://localhost:${port}`, "\u{1F680} Inspector Launched");
1081
+ var server = serve({
1082
+ fetch: app.fetch,
1083
+ port,
1084
+ hostname: "0.0.0.0"
1085
+ // Bind to all interfaces for Docker
1086
+ });
1087
+ process.on("SIGINT", () => {
1088
+ console.log("\n\u{1F6D1} Shutting down gracefully...");
1089
+ server.close();
1090
+ process.exit(0);
1091
+ });
1092
+ process.on("SIGTERM", () => {
1093
+ console.log("\n\u{1F6D1} Shutting down gracefully...");
1094
+ server.close();
1095
+ process.exit(0);
1096
+ });
1097
+ var index_default = app;
1098
+ export {
1099
+ index_default as default
1100
+ };
1101
+ //# sourceMappingURL=index.js.map