@mcp-use/inspector 0.3.3 → 0.3.6

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.
@@ -1,153 +1,196 @@
1
- import { exec } from 'node:child_process';
2
- import { existsSync } from 'node:fs';
3
- import { dirname, join } from 'node:path';
4
- import { fileURLToPath } from 'node:url';
5
- import { promisify } from 'node:util';
6
- import { serve } from '@hono/node-server';
7
- import { Hono } from 'hono';
8
- import { cors } from 'hono/cors';
9
- import { logger } from 'hono/logger';
10
- import faviconProxy from './favicon-proxy.js';
11
- import { MCPInspector } from './mcp-inspector.js';
12
- const __filename = fileURLToPath(import.meta.url);
13
- const __dirname = dirname(__filename);
14
- const execAsync = promisify(exec);
15
- // Check if a specific port is available
1
+ import {
2
+ MCPInspector
3
+ } from "./chunk-LLCPK3RJ.js";
4
+ import {
5
+ checkClientFiles,
6
+ getClientDistPath,
7
+ getContentType,
8
+ handleChatRequest
9
+ } from "./chunk-KT6SE3BW.js";
10
+ import "./chunk-PKBMQBKP.js";
11
+
12
+ // src/server/server.ts
13
+ import { exec } from "child_process";
14
+ import { existsSync } from "fs";
15
+ import { join } from "path";
16
+ import { promisify } from "util";
17
+ import { serve } from "@hono/node-server";
18
+ import { Hono } from "hono";
19
+ import { cors } from "hono/cors";
20
+ import { logger } from "hono/logger";
21
+ var execAsync = promisify(exec);
16
22
  async function isPortAvailable(port) {
17
- const net = await import('node:net');
18
- return new Promise((resolve) => {
19
- const server = net.createServer();
20
- server.listen(port, () => {
21
- server.close(() => resolve(true));
22
- });
23
- server.on('error', () => resolve(false));
23
+ const net = await import("net");
24
+ return new Promise((resolve) => {
25
+ const server = net.createServer();
26
+ server.listen(port, () => {
27
+ server.close(() => resolve(true));
24
28
  });
29
+ server.on("error", () => resolve(false));
30
+ });
25
31
  }
26
- const app = new Hono();
27
- // Middleware
28
- app.use('*', cors());
29
- app.use('*', logger());
30
- // Mount favicon proxy
31
- app.route('/api/favicon', faviconProxy);
32
- // Health check
33
- app.get('/health', (c) => {
34
- return c.json({ status: 'ok', timestamp: new Date().toISOString() });
32
+ var app = new Hono();
33
+ app.use("*", cors());
34
+ app.use("*", logger());
35
+ app.get("/health", (c) => {
36
+ return c.json({ status: "ok", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
35
37
  });
36
- // MCP Inspector routes
37
- const mcpInspector = new MCPInspector();
38
- // List available MCP servers
39
- app.get('/api/servers', async (c) => {
40
- try {
41
- const servers = await mcpInspector.listServers();
42
- return c.json({ servers });
43
- }
44
- catch {
45
- return c.json({ error: 'Failed to list servers' }, 500);
46
- }
38
+ var mcpInspector = new MCPInspector();
39
+ app.get("/api/servers", async (c) => {
40
+ try {
41
+ const servers = await mcpInspector.listServers();
42
+ return c.json({ servers });
43
+ } catch {
44
+ return c.json({ error: "Failed to list servers" }, 500);
45
+ }
47
46
  });
48
- // Connect to an MCP server
49
- app.post('/api/servers/connect', async (c) => {
50
- try {
51
- const { url, command } = await c.req.json();
52
- const server = await mcpInspector.connectToServer(url, command);
53
- return c.json({ server });
54
- }
55
- catch {
56
- return c.json({ error: 'Failed to connect to server' }, 500);
57
- }
47
+ app.post("/api/servers/connect", async (c) => {
48
+ try {
49
+ const { url, command } = await c.req.json();
50
+ const server = await mcpInspector.connectToServer(url, command);
51
+ return c.json({ server });
52
+ } catch {
53
+ return c.json({ error: "Failed to connect to server" }, 500);
54
+ }
58
55
  });
59
- // Get server details
60
- app.get('/api/servers/:id', async (c) => {
61
- try {
62
- const id = c.req.param('id');
63
- const server = await mcpInspector.getServer(id);
64
- if (!server) {
65
- return c.json({ error: 'Server not found' }, 404);
66
- }
67
- return c.json({ server });
68
- }
69
- catch {
70
- return c.json({ error: 'Failed to get server details' }, 500);
56
+ app.get("/api/servers/:id", async (c) => {
57
+ try {
58
+ const id = c.req.param("id");
59
+ const server = await mcpInspector.getServer(id);
60
+ if (!server) {
61
+ return c.json({ error: "Server not found" }, 404);
71
62
  }
63
+ return c.json({ server });
64
+ } catch {
65
+ return c.json({ error: "Failed to get server details" }, 500);
66
+ }
72
67
  });
73
- // Execute a tool on a server
74
- app.post('/api/servers/:id/tools/:toolName/execute', async (c) => {
75
- try {
76
- const id = c.req.param('id');
77
- const toolName = c.req.param('toolName');
78
- const input = await c.req.json();
79
- const result = await mcpInspector.executeTool(id, toolName, input);
80
- return c.json({ result });
81
- }
82
- catch {
83
- return c.json({ error: 'Failed to execute tool' }, 500);
84
- }
68
+ app.post("/api/servers/:id/tools/:toolName/execute", async (c) => {
69
+ try {
70
+ const id = c.req.param("id");
71
+ const toolName = c.req.param("toolName");
72
+ const input = await c.req.json();
73
+ const result = await mcpInspector.executeTool(id, toolName, input);
74
+ return c.json({ result });
75
+ } catch {
76
+ return c.json({ error: "Failed to execute tool" }, 500);
77
+ }
85
78
  });
86
- // Get server tools
87
- app.get('/api/servers/:id/tools', async (c) => {
88
- try {
89
- const id = c.req.param('id');
90
- const tools = await mcpInspector.getServerTools(id);
91
- return c.json({ tools });
92
- }
93
- catch {
94
- return c.json({ error: 'Failed to get server tools' }, 500);
95
- }
79
+ app.get("/api/servers/:id/tools", async (c) => {
80
+ try {
81
+ const id = c.req.param("id");
82
+ const tools = await mcpInspector.getServerTools(id);
83
+ return c.json({ tools });
84
+ } catch {
85
+ return c.json({ error: "Failed to get server tools" }, 500);
86
+ }
96
87
  });
97
- // Get server resources
98
- app.get('/api/servers/:id/resources', async (c) => {
99
- try {
100
- const id = c.req.param('id');
101
- const resources = await mcpInspector.getServerResources(id);
102
- return c.json({ resources });
88
+ app.get("/api/servers/:id/resources", async (c) => {
89
+ try {
90
+ const id = c.req.param("id");
91
+ const resources = await mcpInspector.getServerResources(id);
92
+ return c.json({ resources });
93
+ } catch {
94
+ return c.json({ error: "Failed to get server resources" }, 500);
95
+ }
96
+ });
97
+ app.delete("/api/servers/:id", async (c) => {
98
+ try {
99
+ const id = c.req.param("id");
100
+ await mcpInspector.disconnectServer(id);
101
+ return c.json({ success: true });
102
+ } catch {
103
+ return c.json({ error: "Failed to disconnect server" }, 500);
104
+ }
105
+ });
106
+ app.post("/inspector/api/chat", async (c) => {
107
+ try {
108
+ const requestBody = await c.req.json();
109
+ const result = await handleChatRequest(requestBody);
110
+ return c.json(result);
111
+ } catch (error) {
112
+ console.error("Chat API error:", error);
113
+ return c.json({
114
+ error: error instanceof Error ? error.message : "Failed to process chat request"
115
+ }, 500);
116
+ }
117
+ });
118
+ app.all("/inspector/api/proxy/*", async (c) => {
119
+ try {
120
+ const targetUrl = c.req.header("X-Target-URL");
121
+ const proxyToken = c.req.header("X-Proxy-Token");
122
+ if (!targetUrl) {
123
+ return c.json({ error: "X-Target-URL header is required" }, 400);
103
124
  }
104
- catch {
105
- return c.json({ error: 'Failed to get server resources' }, 500);
125
+ if (proxyToken && proxyToken !== "c96aeb0c195aa9c7d3846b90aec9bc5fcdd5df97b3049aaede8f5dd1a15d2d87") {
126
+ return c.json({ error: "Invalid proxy token" }, 401);
106
127
  }
107
- });
108
- // Disconnect from a server
109
- app.delete('/api/servers/:id', async (c) => {
110
- try {
111
- const id = c.req.param('id');
112
- await mcpInspector.disconnectServer(id);
113
- return c.json({ success: true });
128
+ const method = c.req.method;
129
+ const headers = {};
130
+ const requestHeaders = c.req.header();
131
+ for (const [key, value] of Object.entries(requestHeaders)) {
132
+ if (!key.toLowerCase().startsWith("x-proxy-") && !key.toLowerCase().startsWith("x-target-") && key.toLowerCase() !== "host") {
133
+ headers[key] = value;
134
+ }
114
135
  }
115
- catch {
116
- return c.json({ error: 'Failed to disconnect server' }, 500);
136
+ try {
137
+ const targetUrlObj = new URL(targetUrl);
138
+ headers.Host = targetUrlObj.host;
139
+ } catch {
140
+ return c.json({ error: "Invalid target URL" }, 400);
117
141
  }
142
+ const body = method !== "GET" && method !== "HEAD" ? await c.req.arrayBuffer() : void 0;
143
+ const response = await fetch(targetUrl, {
144
+ method,
145
+ headers,
146
+ body: body ? new Uint8Array(body) : void 0
147
+ });
148
+ const responseHeaders = {};
149
+ response.headers.forEach((value, key) => {
150
+ responseHeaders[key] = value;
151
+ });
152
+ return new Response(response.body, {
153
+ status: response.status,
154
+ statusText: response.statusText,
155
+ headers: responseHeaders
156
+ });
157
+ } catch (error) {
158
+ console.error("Proxy error:", error);
159
+ return c.json({
160
+ error: error instanceof Error ? error.message : "Failed to proxy request"
161
+ }, 500);
162
+ }
163
+ });
164
+ app.get("/inspector/config.json", (c) => {
165
+ return c.json({
166
+ autoConnectUrl: null
167
+ });
118
168
  });
119
- // Check if we're in development mode (Vite dev server running)
120
- const isDev = process.env.NODE_ENV === 'development' || process.env.VITE_DEV === 'true';
121
- // Serve static assets from the built client
122
- const clientDistPath = join(__dirname, '../../dist/client');
169
+ var isDev = process.env.NODE_ENV === "development" || process.env.VITE_DEV === "true";
170
+ var clientDistPath = getClientDistPath();
123
171
  if (isDev) {
124
- // Development mode: proxy client requests to Vite dev server
125
- console.warn('🔧 Development mode: Proxying client requests to Vite dev server');
126
- // Proxy all non-API requests to Vite dev server
127
- app.get('*', async (c) => {
128
- const path = c.req.path;
129
- // Skip API routes
130
- if (path.startsWith('/api/')) {
131
- return c.notFound();
132
- }
133
- try {
134
- // Vite dev server should be running on port 3000
135
- const viteUrl = `http://localhost:3000${path}`;
136
- const response = await fetch(viteUrl, {
137
- signal: AbortSignal.timeout(1000), // 1 second timeout
138
- });
139
- if (response.ok) {
140
- const content = await response.text();
141
- const contentType = response.headers.get('content-type') || 'text/html';
142
- c.header('Content-Type', contentType);
143
- return c.html(content);
144
- }
145
- }
146
- catch (error) {
147
- console.warn(`Failed to proxy to Vite dev server: ${error}`);
148
- }
149
- // Fallback HTML if Vite dev server is not running
150
- return c.html(`
172
+ console.warn("\u{1F527} Development mode: Proxying client requests to Vite dev server");
173
+ app.get("*", async (c) => {
174
+ const path = c.req.path;
175
+ if (path.startsWith("/api/") || path.startsWith("/inspector/api/") || path === "/inspector/config.json") {
176
+ return c.notFound();
177
+ }
178
+ try {
179
+ const viteUrl = `http://localhost:3000${path}`;
180
+ const response = await fetch(viteUrl, {
181
+ signal: AbortSignal.timeout(1e3)
182
+ // 1 second timeout
183
+ });
184
+ if (response.ok) {
185
+ const content = await response.text();
186
+ const contentType = response.headers.get("content-type") || "text/html";
187
+ c.header("Content-Type", contentType);
188
+ return c.html(content);
189
+ }
190
+ } catch (error) {
191
+ console.warn(`Failed to proxy to Vite dev server: ${error}`);
192
+ }
193
+ return c.html(`
151
194
  <!DOCTYPE html>
152
195
  <html>
153
196
  <head>
@@ -161,42 +204,29 @@ if (isDev) {
161
204
  </body>
162
205
  </html>
163
206
  `);
164
- });
165
- }
166
- else if (existsSync(clientDistPath)) {
167
- // Production mode: serve static assets from built client
168
- // Serve static assets from /inspector/assets/* (matching Vite's base path)
169
- app.get('/inspector/assets/*', async (c) => {
170
- const path = c.req.path.replace('/inspector/assets/', 'assets/');
171
- const fullPath = join(clientDistPath, path);
172
- if (existsSync(fullPath)) {
173
- const content = await import('node:fs').then(fs => fs.readFileSync(fullPath));
174
- // Set appropriate content type based on file extension
175
- if (path.endsWith('.js')) {
176
- c.header('Content-Type', 'application/javascript');
177
- }
178
- else if (path.endsWith('.css')) {
179
- c.header('Content-Type', 'text/css');
180
- }
181
- else if (path.endsWith('.svg')) {
182
- c.header('Content-Type', 'image/svg+xml');
183
- }
184
- return c.body(content);
185
- }
186
- return c.notFound();
187
- });
188
- // Redirect root path to /inspector
189
- app.get('/', (c) => {
190
- return c.redirect('/inspector');
191
- });
192
- // Serve the main HTML file for /inspector and all other routes (SPA routing)
193
- app.get('*', (c) => {
194
- const indexPath = join(clientDistPath, 'index.html');
195
- if (existsSync(indexPath)) {
196
- const content = import('node:fs').then(fs => fs.readFileSync(indexPath, 'utf-8'));
197
- return c.html(content);
198
- }
199
- return c.html(`
207
+ });
208
+ } else if (checkClientFiles(clientDistPath)) {
209
+ app.get("/inspector/assets/*", async (c) => {
210
+ const path = c.req.path.replace("/inspector/assets/", "assets/");
211
+ const fullPath = join(clientDistPath, path);
212
+ if (existsSync(fullPath)) {
213
+ const content = await import("fs").then((fs) => fs.readFileSync(fullPath));
214
+ const contentType = getContentType(fullPath);
215
+ c.header("Content-Type", contentType);
216
+ return c.body(content);
217
+ }
218
+ return c.notFound();
219
+ });
220
+ app.get("/", (c) => {
221
+ return c.redirect("/inspector");
222
+ });
223
+ app.get("*", (c) => {
224
+ const indexPath = join(clientDistPath, "index.html");
225
+ if (existsSync(indexPath)) {
226
+ const content = import("fs").then((fs) => fs.readFileSync(indexPath, "utf-8"));
227
+ return c.html(content);
228
+ }
229
+ return c.html(`
200
230
  <!DOCTYPE html>
201
231
  <html>
202
232
  <head>
@@ -209,14 +239,12 @@ else if (existsSync(clientDistPath)) {
209
239
  </body>
210
240
  </html>
211
241
  `);
212
- });
213
- }
214
- else {
215
- console.warn(`⚠️ MCP Inspector client files not found at ${clientDistPath}`);
216
- console.warn(` Run 'yarn build' in the inspector package to build the UI`);
217
- // Fallback for when client is not built
218
- app.get('*', (c) => {
219
- return c.html(`
242
+ });
243
+ } else {
244
+ console.warn(`\u26A0\uFE0F MCP Inspector client files not found at ${clientDistPath}`);
245
+ console.warn(` Run 'yarn build' in the inspector package to build the UI`);
246
+ app.get("*", (c) => {
247
+ return c.html(`
220
248
  <!DOCTYPE html>
221
249
  <html>
222
250
  <head>
@@ -229,66 +257,59 @@ else {
229
257
  </body>
230
258
  </html>
231
259
  `);
232
- });
260
+ });
233
261
  }
234
- // Start the server
235
262
  async function startServer() {
236
- try {
237
- // In development mode, use port 3001 for API server
238
- // In production/standalone mode, try 3001 first, then 3002 as fallback
239
- const isDev = process.env.NODE_ENV === 'development' || process.env.VITE_DEV === 'true';
240
- let port = 3001;
241
- const available = await isPortAvailable(port);
242
- if (!available) {
243
- if (isDev) {
244
- console.error(`❌ Port ${port} is not available. Please stop the process using this port and try again.`);
245
- process.exit(1);
246
- }
247
- else {
248
- // In standalone mode, try fallback port
249
- const fallbackPort = 3002;
250
- console.warn(`⚠️ Port ${port} is not available, trying ${fallbackPort}`);
251
- const fallbackAvailable = await isPortAvailable(fallbackPort);
252
- if (!fallbackAvailable) {
253
- console.error(`❌ Neither port ${port} nor ${fallbackPort} is available. Please stop the processes using these ports and try again.`);
254
- process.exit(1);
255
- }
256
- port = fallbackPort;
257
- }
258
- }
259
- serve({
260
- fetch: app.fetch,
261
- port,
262
- });
263
- if (isDev) {
264
- console.warn(`🚀 MCP Inspector API server running on http://localhost:${port}`);
265
- console.warn(`🌐 Vite dev server should be running on http://localhost:3000`);
266
- }
267
- else {
268
- console.warn(`🚀 MCP Inspector running on http://localhost:${port}`);
269
- }
270
- // Auto-open browser in development
271
- if (process.env.NODE_ENV !== 'production') {
272
- try {
273
- const command = process.platform === 'win32' ? 'start' : process.platform === 'darwin' ? 'open' : 'xdg-open';
274
- const url = isDev ? 'http://localhost:3000' : `http://localhost:${port}`;
275
- await execAsync(`${command} ${url}`);
276
- console.warn(`🌐 Browser opened automatically`);
277
- }
278
- catch {
279
- const url = isDev ? 'http://localhost:3000' : `http://localhost:${port}`;
280
- console.warn(`🌐 Please open ${url} in your browser`);
281
- }
263
+ try {
264
+ const isDev2 = process.env.NODE_ENV === "development" || process.env.VITE_DEV === "true";
265
+ let port = 3001;
266
+ const available = await isPortAvailable(port);
267
+ if (!available) {
268
+ if (isDev2) {
269
+ console.error(`\u274C Port ${port} is not available. Please stop the process using this port and try again.`);
270
+ process.exit(1);
271
+ } else {
272
+ const fallbackPort = 3002;
273
+ console.warn(`\u26A0\uFE0F Port ${port} is not available, trying ${fallbackPort}`);
274
+ const fallbackAvailable = await isPortAvailable(fallbackPort);
275
+ if (!fallbackAvailable) {
276
+ console.error(`\u274C Neither port ${port} nor ${fallbackPort} is available. Please stop the processes using these ports and try again.`);
277
+ process.exit(1);
282
278
  }
283
- return { port, fetch: app.fetch };
279
+ port = fallbackPort;
280
+ }
284
281
  }
285
- catch (error) {
286
- console.error('Failed to start server:', error);
287
- process.exit(1);
282
+ serve({
283
+ fetch: app.fetch,
284
+ port
285
+ });
286
+ if (isDev2) {
287
+ console.warn(`\u{1F680} MCP Inspector API server running on http://localhost:${port}`);
288
+ console.warn(`\u{1F310} Vite dev server should be running on http://localhost:3000`);
289
+ } else {
290
+ console.warn(`\u{1F680} MCP Inspector running on http://localhost:${port}`);
291
+ }
292
+ if (process.env.NODE_ENV !== "production") {
293
+ try {
294
+ const command = process.platform === "win32" ? "start" : process.platform === "darwin" ? "open" : "xdg-open";
295
+ const url = isDev2 ? "http://localhost:3000" : `http://localhost:${port}`;
296
+ await execAsync(`${command} ${url}`);
297
+ console.warn(`\u{1F310} Browser opened automatically`);
298
+ } catch {
299
+ const url = isDev2 ? "http://localhost:3000" : `http://localhost:${port}`;
300
+ console.warn(`\u{1F310} Please open ${url} in your browser`);
301
+ }
288
302
  }
303
+ return { port, fetch: app.fetch };
304
+ } catch (error) {
305
+ console.error("Failed to start server:", error);
306
+ process.exit(1);
307
+ }
289
308
  }
290
- // Start the server if this file is run directly
291
309
  if (import.meta.url === `file://${process.argv[1]}`) {
292
- startServer();
310
+ startServer();
293
311
  }
294
- export default { startServer };
312
+ var server_default = { startServer };
313
+ export {
314
+ server_default as default
315
+ };
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Shared utilities for MCP Inspector server functionality
3
+ */
4
+ /**
5
+ * Handle chat API request with MCP agent
6
+ */
7
+ export declare function handleChatRequest(requestBody: {
8
+ mcpServerUrl: string;
9
+ llmConfig: any;
10
+ authConfig?: any;
11
+ messages: any[];
12
+ }): Promise<{
13
+ content: string;
14
+ toolCalls: any[];
15
+ }>;
16
+ /**
17
+ * Get content type for static assets
18
+ */
19
+ export declare function getContentType(filePath: string): string;
20
+ /**
21
+ * Check if client files exist
22
+ */
23
+ export declare function checkClientFiles(clientDistPath: string): boolean;
24
+ /**
25
+ * Get client dist path
26
+ */
27
+ export declare function getClientDistPath(): string;
28
+ //# sourceMappingURL=shared-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-utils.d.ts","sourceRoot":"","sources":["../../src/server/shared-utils.ts"],"names":[],"mappings":"AAKA;;GAEG;AAGH;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE;IACnD,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,GAAG,CAAA;IACd,UAAU,CAAC,EAAE,GAAG,CAAA;IAChB,QAAQ,EAAE,GAAG,EAAE,CAAA;CAChB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,CA+HjD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CA4BvD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C"}
@@ -0,0 +1,13 @@
1
+ import {
2
+ checkClientFiles,
3
+ getClientDistPath,
4
+ getContentType,
5
+ handleChatRequest
6
+ } from "./chunk-KT6SE3BW.js";
7
+ import "./chunk-PKBMQBKP.js";
8
+ export {
9
+ checkClientFiles,
10
+ getClientDistPath,
11
+ getContentType,
12
+ handleChatRequest
13
+ };