@modelcontextprotocol/inspector 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -30,7 +30,7 @@ npx @modelcontextprotocol/inspector -e KEY=value -e KEY2=$VALUE2 node build/inde
30
30
  npx @modelcontextprotocol/inspector -e KEY=$VALUE -- node build/index.js -e server-flag
31
31
  ```
32
32
 
33
- The inspector runs both a client UI (default port 5173) and an MCP proxy server (default port 3000). Open the client UI in your browser to use the inspector. You can customize the ports if needed:
33
+ The inspector runs both an MCP Inspector (MCPI) client UI (default port 6274) and an MCP Proxy (MCPP) server (default port 6277). Open the MCPI client UI in your browser to use the inspector. (These ports are derived from the T9 dialpad mapping of MCPI and MCPP respectively, as a mnemonic). You can customize the ports if needed:
34
34
 
35
35
  ```bash
36
36
  CLIENT_PORT=8080 SERVER_PORT=9000 npx @modelcontextprotocol/inspector node build/index.js
@@ -42,6 +42,18 @@ For more details on ways to use the inspector, see the [Inspector section of the
42
42
 
43
43
  The inspector supports bearer token authentication for SSE connections. Enter your token in the UI when connecting to an MCP server, and it will be sent in the Authorization header.
44
44
 
45
+ ### Security Considerations
46
+
47
+ The MCP Inspector includes a proxy server that can run and communicate with local MCP processes. The proxy server should not be exposed to untrusted networks as it has permissions to spawn local processes and can connect to any specified MCP server.
48
+
49
+ ### Configuration
50
+
51
+ The MCP Inspector supports the following configuration settings. To change them click on the `Configuration` button in the MCP Inspector UI :
52
+
53
+ | Name | Purpose | Default Value |
54
+ | -------------------------- | ----------------------------------------------------------------------------------------- | ------------- |
55
+ | MCP_SERVER_REQUEST_TIMEOUT | Maximum time in milliseconds to wait for a response from the MCP server before timing out | 10000 |
56
+
45
57
  ### From this repository
46
58
 
47
59
  If you're working on the inspector itself:
package/bin/cli.js CHANGED
@@ -7,7 +7,7 @@ import { fileURLToPath } from "url";
7
7
  const __dirname = dirname(fileURLToPath(import.meta.url));
8
8
 
9
9
  function delay(ms) {
10
- return new Promise((resolve) => setTimeout(resolve, ms));
10
+ return new Promise((resolve) => setTimeout(resolve, ms, true));
11
11
  }
12
12
 
13
13
  async function main() {
@@ -27,9 +27,15 @@ async function main() {
27
27
  }
28
28
 
29
29
  if (parsingFlags && arg === "-e" && i + 1 < args.length) {
30
- const [key, value] = args[++i].split("=");
31
- if (key && value) {
30
+ const envVar = args[++i];
31
+ const equalsIndex = envVar.indexOf("=");
32
+
33
+ if (equalsIndex !== -1) {
34
+ const key = envVar.substring(0, equalsIndex);
35
+ const value = envVar.substring(equalsIndex + 1);
32
36
  envVars[key] = value;
37
+ } else {
38
+ envVars[envVar] = "";
33
39
  }
34
40
  } else if (!command) {
35
41
  command = arg;
@@ -55,8 +61,8 @@ async function main() {
55
61
  "cli.js",
56
62
  );
57
63
 
58
- const CLIENT_PORT = process.env.CLIENT_PORT ?? "5173";
59
- const SERVER_PORT = process.env.SERVER_PORT ?? "3000";
64
+ const CLIENT_PORT = process.env.CLIENT_PORT ?? "6274";
65
+ const SERVER_PORT = process.env.SERVER_PORT ?? "6277";
60
66
 
61
67
  console.log("Starting MCP inspector...");
62
68
 
@@ -67,42 +73,40 @@ async function main() {
67
73
  cancelled = true;
68
74
  abort.abort();
69
75
  });
70
-
71
- const server = spawnPromise(
72
- "node",
73
- [
74
- inspectorServerPath,
75
- ...(command ? [`--env`, command] : []),
76
- ...(mcpServerArgs ? [`--args=${mcpServerArgs.join(" ")}`] : []),
77
- ],
78
- {
79
- env: {
80
- ...process.env,
81
- PORT: SERVER_PORT,
82
- MCP_ENV_VARS: JSON.stringify(envVars),
83
- },
84
- signal: abort.signal,
85
- echoOutput: true,
86
- },
87
- );
88
-
89
- const client = spawnPromise("node", [inspectorClientPath], {
90
- env: { ...process.env, PORT: CLIENT_PORT },
91
- signal: abort.signal,
92
- echoOutput: true,
93
- });
94
-
95
- // Make sure our server/client didn't immediately fail
96
- await Promise.any([server, client, delay(2 * 1000)]);
97
- const portParam = SERVER_PORT === "3000" ? "" : `?proxyPort=${SERVER_PORT}`;
98
- console.log(
99
- `\n🔍 MCP Inspector is up and running at http://localhost:${CLIENT_PORT}${portParam} 🚀`,
100
- );
101
-
76
+ let server, serverOk;
102
77
  try {
103
- await Promise.any([server, client]);
104
- } catch (e) {
105
- if (!cancelled || process.env.DEBUG) throw e;
78
+ server = spawnPromise(
79
+ "node",
80
+ [
81
+ inspectorServerPath,
82
+ ...(command ? [`--env`, command] : []),
83
+ ...(mcpServerArgs ? [`--args=${mcpServerArgs.join(" ")}`] : []),
84
+ ],
85
+ {
86
+ env: {
87
+ ...process.env,
88
+ PORT: SERVER_PORT,
89
+ MCP_ENV_VARS: JSON.stringify(envVars),
90
+ },
91
+ signal: abort.signal,
92
+ echoOutput: true,
93
+ },
94
+ );
95
+
96
+ // Make sure server started before starting client
97
+ serverOk = await Promise.race([server, delay(2 * 1000)]);
98
+ } catch (error) {}
99
+
100
+ if (serverOk) {
101
+ try {
102
+ await spawnPromise("node", [inspectorClientPath], {
103
+ env: { ...process.env, PORT: CLIENT_PORT },
104
+ signal: abort.signal,
105
+ echoOutput: true,
106
+ });
107
+ } catch (e) {
108
+ if (!cancelled || process.env.DEBUG) throw e;
109
+ }
106
110
  }
107
111
 
108
112
  return 0;
package/client/bin/cli.js CHANGED
@@ -15,5 +15,19 @@ const server = http.createServer((request, response) => {
15
15
  });
16
16
  });
17
17
 
18
- const port = process.env.PORT || 5173;
19
- server.listen(port, () => {});
18
+ const port = process.env.PORT || 6274;
19
+ server.on("listening", () => {
20
+ console.log(
21
+ `🔍 MCP Inspector is up and running at http://127.0.0.1:${port} 🚀`,
22
+ );
23
+ });
24
+ server.on("error", (err) => {
25
+ if (err.message.includes(`EADDRINUSE`)) {
26
+ console.error(
27
+ `❌ MCP Inspector PORT IS IN USE at http://127.0.0.1:${port} ❌ `,
28
+ );
29
+ } else {
30
+ throw err;
31
+ }
32
+ });
33
+ server.listen(port);
@@ -1,4 +1,4 @@
1
- import { r as reactExports, j as jsxRuntimeExports, S as SESSION_KEYS, a as auth, b as authProvider } from "./index-BK1TrpAN.js";
1
+ import { r as reactExports, j as jsxRuntimeExports, S as SESSION_KEYS, a as auth, b as authProvider } from "./index-DrNN0pLZ.js";
2
2
  const OAuthCallback = () => {
3
3
  const hasProcessedRef = reactExports.useRef(false);
4
4
  reactExports.useEffect(() => {
@@ -1443,6 +1443,12 @@ video {
1443
1443
  white-space: nowrap;
1444
1444
  border-width: 0;
1445
1445
  }
1446
+ .visible {
1447
+ visibility: visible;
1448
+ }
1449
+ .collapse {
1450
+ visibility: collapse;
1451
+ }
1446
1452
  .fixed {
1447
1453
  position: fixed;
1448
1454
  }
@@ -1511,9 +1517,15 @@ video {
1511
1517
  .ml-2 {
1512
1518
  margin-left: 0.5rem;
1513
1519
  }
1520
+ .ml-4 {
1521
+ margin-left: 1rem;
1522
+ }
1514
1523
  .ml-auto {
1515
1524
  margin-left: auto;
1516
1525
  }
1526
+ .mr-1 {
1527
+ margin-right: 0.25rem;
1528
+ }
1517
1529
  .mr-2 {
1518
1530
  margin-right: 0.5rem;
1519
1531
  }
@@ -1559,9 +1571,6 @@ video {
1559
1571
  .h-4 {
1560
1572
  height: 1rem;
1561
1573
  }
1562
- .h-64 {
1563
- height: 16rem;
1564
- }
1565
1574
  .h-8 {
1566
1575
  height: 2rem;
1567
1576
  }
@@ -1586,9 +1595,6 @@ video {
1586
1595
  .h-screen {
1587
1596
  height: 100vh;
1588
1597
  }
1589
- .max-h-64 {
1590
- max-height: 16rem;
1591
- }
1592
1598
  .max-h-80 {
1593
1599
  max-height: 20rem;
1594
1600
  }
@@ -1755,8 +1761,8 @@ video {
1755
1761
  .whitespace-pre-wrap {
1756
1762
  white-space: pre-wrap;
1757
1763
  }
1758
- .break-words {
1759
- overflow-wrap: break-word;
1764
+ .break-all {
1765
+ word-break: break-all;
1760
1766
  }
1761
1767
  .rounded {
1762
1768
  border-radius: 0.25rem;
@@ -1779,6 +1785,9 @@ video {
1779
1785
  .border-b {
1780
1786
  border-bottom-width: 1px;
1781
1787
  }
1788
+ .border-l {
1789
+ border-left-width: 1px;
1790
+ }
1782
1791
  .border-r {
1783
1792
  border-right-width: 1px;
1784
1793
  }
@@ -1964,6 +1973,10 @@ video {
1964
1973
  .tracking-widest {
1965
1974
  letter-spacing: 0.1em;
1966
1975
  }
1976
+ .text-amber-600 {
1977
+ --tw-text-opacity: 1;
1978
+ color: rgb(217 119 6 / var(--tw-text-opacity, 1));
1979
+ }
1967
1980
  .text-blue-500 {
1968
1981
  --tw-text-opacity: 1;
1969
1982
  color: rgb(59 130 246 / var(--tw-text-opacity, 1));
@@ -2004,10 +2017,6 @@ video {
2004
2017
  --tw-text-opacity: 1;
2005
2018
  color: rgb(55 65 81 / var(--tw-text-opacity, 1));
2006
2019
  }
2007
- .text-gray-800 {
2008
- --tw-text-opacity: 1;
2009
- color: rgb(31 41 55 / var(--tw-text-opacity, 1));
2010
- }
2011
2020
  .text-gray-900 {
2012
2021
  --tw-text-opacity: 1;
2013
2022
  color: rgb(17 24 39 / var(--tw-text-opacity, 1));
@@ -2109,6 +2118,9 @@ video {
2109
2118
  .duration-200 {
2110
2119
  transition-duration: 200ms;
2111
2120
  }
2121
+ .duration-300 {
2122
+ transition-duration: 300ms;
2123
+ }
2112
2124
  @keyframes enter {
2113
2125
 
2114
2126
  from {
@@ -2126,6 +2138,9 @@ video {
2126
2138
  .duration-200 {
2127
2139
  animation-duration: 200ms;
2128
2140
  }
2141
+ .duration-300 {
2142
+ animation-duration: 300ms;
2143
+ }
2129
2144
 
2130
2145
  :root {
2131
2146
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
@@ -2249,6 +2264,14 @@ button[role="checkbox"] {
2249
2264
  background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
2250
2265
  }
2251
2266
 
2267
+ .hover\:bg-gray-800\/10:hover {
2268
+ background-color: rgb(31 41 55 / 0.1);
2269
+ }
2270
+
2271
+ .hover\:bg-gray-800\/20:hover {
2272
+ background-color: rgb(31 41 55 / 0.2);
2273
+ }
2274
+
2252
2275
  .hover\:bg-primary\/90:hover {
2253
2276
  background-color: hsl(var(--primary) / 0.9);
2254
2277
  }
@@ -2344,6 +2367,16 @@ button[role="checkbox"] {
2344
2367
  opacity: 0.5;
2345
2368
  }
2346
2369
 
2370
+ .group:hover .group-hover\:text-gray-400 {
2371
+ --tw-text-opacity: 1;
2372
+ color: rgb(156 163 175 / var(--tw-text-opacity, 1));
2373
+ }
2374
+
2375
+ .group:hover .group-hover\:text-green-500 {
2376
+ --tw-text-opacity: 1;
2377
+ color: rgb(34 197 94 / var(--tw-text-opacity, 1));
2378
+ }
2379
+
2347
2380
  .peer:disabled ~ .peer-disabled\:cursor-not-allowed {
2348
2381
  cursor: not-allowed;
2349
2382
  }
@@ -2523,6 +2556,11 @@ button[role="checkbox"] {
2523
2556
  color: rgb(209 213 219 / var(--tw-text-opacity, 1));
2524
2557
  }
2525
2558
 
2559
+ .dark\:text-gray-400:is(.dark *) {
2560
+ --tw-text-opacity: 1;
2561
+ color: rgb(156 163 175 / var(--tw-text-opacity, 1));
2562
+ }
2563
+
2526
2564
  .dark\:text-white:is(.dark *) {
2527
2565
  --tw-text-opacity: 1;
2528
2566
  color: rgb(255 255 255 / var(--tw-text-opacity, 1));
@@ -2533,6 +2571,15 @@ button[role="checkbox"] {
2533
2571
  background-color: rgb(55 65 81 / var(--tw-bg-opacity, 1));
2534
2572
  }
2535
2573
 
2574
+ .dark\:hover\:bg-gray-800\/20:hover:is(.dark *) {
2575
+ background-color: rgb(31 41 55 / 0.2);
2576
+ }
2577
+
2578
+ .group:hover .dark\:group-hover\:text-gray-100:is(.dark *) {
2579
+ --tw-text-opacity: 1;
2580
+ color: rgb(243 244 246 / var(--tw-text-opacity, 1));
2581
+ }
2582
+
2536
2583
  @media (min-width: 640px) {
2537
2584
 
2538
2585
  .sm\:flex-row {