@modelcontextprotocol/inspector 1.0.1 → 2.0.0-rc.2

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 (48) hide show
  1. package/README.md +199 -361
  2. package/clients/cli/build/index.js +13218 -0
  3. package/clients/launcher/build/index.js +90 -0
  4. package/clients/launcher/build/parse-launcher-argv.js +29 -0
  5. package/clients/tui/build/chunk-MCKGQKYU.js +15 -0
  6. package/clients/tui/build/index.js +14573 -0
  7. package/clients/tui/build/undici-HXPKCIY3.js +25789 -0
  8. package/clients/web/build/chunk-MCKGQKYU.js +15 -0
  9. package/clients/web/build/index.js +4322 -0
  10. package/clients/web/build/undici-HXPKCIY3.js +25789 -0
  11. package/clients/web/dist/assets/css-DfBGKsUM.js +1 -0
  12. package/clients/web/dist/assets/index-Cbtmmw0V.js +300 -0
  13. package/clients/web/dist/assets/index-CiUpWldH.css +1 -0
  14. package/clients/web/dist/assets/json-rfaH9Mx5.js +1 -0
  15. package/clients/web/dist/assets/markdown-PVXc4EJ0.js +1 -0
  16. package/clients/web/dist/assets/markup-Bk4keGDK.js +1 -0
  17. package/clients/web/dist/assets/markup-DPsXihXF.js +1 -0
  18. package/clients/web/dist/assets/prism-light-B8tIwqDr.js +6 -0
  19. package/clients/web/dist/assets/tomorrow-COrD2Qnh.js +1 -0
  20. package/clients/web/dist/assets/yaml-B78V9E0m.js +1 -0
  21. package/clients/web/dist/icons.svg +24 -0
  22. package/clients/web/dist/index.html +17 -0
  23. package/package.json +96 -80
  24. package/scripts/install-clients.mjs +65 -0
  25. package/LICENSE +0 -216
  26. package/cli/build/cli.js +0 -290
  27. package/cli/build/client/connection.js +0 -38
  28. package/cli/build/client/index.js +0 -6
  29. package/cli/build/client/prompts.js +0 -43
  30. package/cli/build/client/resources.js +0 -36
  31. package/cli/build/client/tools.js +0 -87
  32. package/cli/build/client/types.js +0 -1
  33. package/cli/build/error-handler.js +0 -18
  34. package/cli/build/index.js +0 -257
  35. package/cli/build/transport.js +0 -65
  36. package/cli/build/utils/awaitable-log.js +0 -7
  37. package/client/bin/client.js +0 -62
  38. package/client/bin/start.js +0 -355
  39. package/client/dist/assets/OAuthCallback-DKaW5Tk8.js +0 -55
  40. package/client/dist/assets/OAuthDebugCallback-Bx3X7Zkh.js +0 -64
  41. package/client/dist/assets/index-CH-qD91V.js +0 -67487
  42. package/client/dist/assets/index-DXy0twoH.css +0 -2786
  43. package/client/dist/index.html +0 -14
  44. package/server/build/index.js +0 -889
  45. package/server/build/mcpProxy.js +0 -121
  46. package/server/build/static/sandbox_proxy.html +0 -197
  47. package/server/static/sandbox_proxy.html +0 -197
  48. /package/{client/dist/mcp.svg → clients/web/dist/assets/MCP-CWGQJYyH.svg} +0 -0
package/cli/build/cli.js DELETED
@@ -1,290 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Command } from "commander";
3
- import fs from "node:fs";
4
- import path from "node:path";
5
- import { dirname, resolve } from "path";
6
- import { spawnPromise } from "spawn-rx";
7
- import { fileURLToPath } from "url";
8
- const __dirname = dirname(fileURLToPath(import.meta.url));
9
- /**
10
- * v1 deprecation notice. Written to stderr, never stdout: `--cli` mode emits
11
- * JSON on stdout and callers pipe it, so a banner there would corrupt output.
12
- */
13
- const DEPRECATION_NOTICE = [
14
- "⚠️ @modelcontextprotocol/inspector v1 is deprecated.",
15
- " Upgrade: npx @modelcontextprotocol/inspector@latest",
16
- " v1 receives security fixes only.",
17
- ].join("\n");
18
- function printDeprecationNotice() {
19
- console.error(`\n${DEPRECATION_NOTICE}\n`);
20
- }
21
- function handleError(error) {
22
- let message;
23
- if (error instanceof Error) {
24
- message = error.message;
25
- }
26
- else if (typeof error === "string") {
27
- message = error;
28
- }
29
- else {
30
- message = "Unknown error";
31
- }
32
- console.error(message);
33
- process.exit(1);
34
- }
35
- function delay(ms) {
36
- return new Promise((resolve) => setTimeout(resolve, ms, true));
37
- }
38
- async function runWebClient(args) {
39
- // Path to the client entry point
40
- const inspectorClientPath = resolve(__dirname, "../../", "client", "bin", "start.js");
41
- const abort = new AbortController();
42
- let cancelled = false;
43
- process.on("SIGINT", () => {
44
- cancelled = true;
45
- abort.abort();
46
- });
47
- // Build arguments to pass to start.js
48
- const startArgs = [];
49
- // Pass environment variables
50
- for (const [key, value] of Object.entries(args.envArgs)) {
51
- startArgs.push("-e", `${key}=${value}`);
52
- }
53
- // Pass transport type if specified
54
- if (args.transport) {
55
- startArgs.push("--transport", args.transport);
56
- }
57
- // Pass server URL if specified
58
- if (args.serverUrl) {
59
- startArgs.push("--server-url", args.serverUrl);
60
- }
61
- // Pass command and args (using -- to separate them)
62
- if (args.command) {
63
- startArgs.push("--", args.command, ...args.args);
64
- }
65
- try {
66
- await spawnPromise("node", [inspectorClientPath, ...startArgs], {
67
- signal: abort.signal,
68
- echoOutput: true,
69
- // pipe the stdout through here, prevents issues with buffering and
70
- // dropping the end of console.out after 8192 chars due to node
71
- // closing the stdout pipe before the output has finished flushing
72
- stdio: "inherit",
73
- });
74
- }
75
- catch (e) {
76
- if (!cancelled || process.env.DEBUG)
77
- throw e;
78
- }
79
- }
80
- async function runCli(args) {
81
- const projectRoot = resolve(__dirname, "..");
82
- const cliPath = resolve(projectRoot, "build", "index.js");
83
- const abort = new AbortController();
84
- let cancelled = false;
85
- process.on("SIGINT", () => {
86
- cancelled = true;
87
- abort.abort();
88
- });
89
- try {
90
- // Build CLI arguments
91
- const cliArgs = [cliPath];
92
- // Add target URL/command first
93
- cliArgs.push(args.command, ...args.args);
94
- // Add transport flag if specified
95
- if (args.transport && args.transport !== "stdio") {
96
- // Convert streamable-http back to http for CLI mode
97
- const cliTransport = args.transport === "streamable-http" ? "http" : args.transport;
98
- cliArgs.push("--transport", cliTransport);
99
- }
100
- // Add headers if specified
101
- if (args.headers) {
102
- for (const [key, value] of Object.entries(args.headers)) {
103
- cliArgs.push("--header", `${key}: ${value}`);
104
- }
105
- }
106
- await spawnPromise("node", cliArgs, {
107
- env: { ...process.env, ...args.envArgs },
108
- signal: abort.signal,
109
- echoOutput: true,
110
- // pipe the stdout through here, prevents issues with buffering and
111
- // dropping the end of console.out after 8192 chars due to node
112
- // closing the stdout pipe before the output has finished flushing
113
- stdio: "inherit",
114
- });
115
- }
116
- catch (e) {
117
- if (!cancelled || process.env.DEBUG) {
118
- throw e;
119
- }
120
- }
121
- }
122
- function loadConfigFile(configPath, serverName) {
123
- try {
124
- const resolvedConfigPath = path.isAbsolute(configPath)
125
- ? configPath
126
- : path.resolve(process.cwd(), configPath);
127
- if (!fs.existsSync(resolvedConfigPath)) {
128
- throw new Error(`Config file not found: ${resolvedConfigPath}`);
129
- }
130
- const configContent = fs.readFileSync(resolvedConfigPath, "utf8");
131
- const parsedConfig = JSON.parse(configContent);
132
- if (!parsedConfig.mcpServers || !parsedConfig.mcpServers[serverName]) {
133
- const availableServers = Object.keys(parsedConfig.mcpServers || {}).join(", ");
134
- throw new Error(`Server '${serverName}' not found in config file. Available servers: ${availableServers}`);
135
- }
136
- const serverConfig = parsedConfig.mcpServers[serverName];
137
- return serverConfig;
138
- }
139
- catch (err) {
140
- if (err instanceof SyntaxError) {
141
- throw new Error(`Invalid JSON in config file: ${err.message}`);
142
- }
143
- throw err;
144
- }
145
- }
146
- function parseKeyValuePair(value, previous = {}) {
147
- const parts = value.split("=");
148
- const key = parts[0];
149
- const val = parts.slice(1).join("=");
150
- if (val === undefined || val === "") {
151
- throw new Error(`Invalid parameter format: ${value}. Use key=value format.`);
152
- }
153
- return { ...previous, [key]: val };
154
- }
155
- function parseHeaderPair(value, previous = {}) {
156
- const colonIndex = value.indexOf(":");
157
- if (colonIndex === -1) {
158
- throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
159
- }
160
- const key = value.slice(0, colonIndex).trim();
161
- const val = value.slice(colonIndex + 1).trim();
162
- if (key === "" || val === "") {
163
- throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
164
- }
165
- return { ...previous, [key]: val };
166
- }
167
- function parseArgs() {
168
- const program = new Command();
169
- const argSeparatorIndex = process.argv.indexOf("--");
170
- let preArgs = process.argv;
171
- let postArgs = [];
172
- if (argSeparatorIndex !== -1) {
173
- preArgs = process.argv.slice(0, argSeparatorIndex);
174
- postArgs = process.argv.slice(argSeparatorIndex + 1);
175
- }
176
- program
177
- .name("inspector-bin")
178
- .allowExcessArguments()
179
- .allowUnknownOption()
180
- .option("-e <env>", "environment variables in KEY=VALUE format", parseKeyValuePair, {})
181
- .option("--config <path>", "config file path")
182
- .option("--server <n>", "server name from config file")
183
- .option("--cli", "enable CLI mode")
184
- .option("--transport <type>", "transport type (stdio, sse, http)")
185
- .option("--server-url <url>", "server URL for SSE/HTTP transport")
186
- .option("--header <headers...>", 'HTTP headers as "HeaderName: Value" pairs (for HTTP/SSE transports)', parseHeaderPair, {});
187
- // Parse only the arguments before --
188
- program.parse(preArgs);
189
- const options = program.opts();
190
- const remainingArgs = program.args;
191
- // Add back any arguments that came after --
192
- const finalArgs = [...remainingArgs, ...postArgs];
193
- // Validate config and server options
194
- if (!options.config && options.server) {
195
- throw new Error("--server requires --config to be specified");
196
- }
197
- // If config is provided without server, try to auto-select
198
- if (options.config && !options.server) {
199
- const configContent = fs.readFileSync(path.isAbsolute(options.config)
200
- ? options.config
201
- : path.resolve(process.cwd(), options.config), "utf8");
202
- const parsedConfig = JSON.parse(configContent);
203
- const servers = Object.keys(parsedConfig.mcpServers || {});
204
- if (servers.length === 1) {
205
- // Use the only server if there's just one
206
- options.server = servers[0];
207
- }
208
- else if (servers.length === 0) {
209
- throw new Error("No servers found in config file");
210
- }
211
- else {
212
- // Multiple servers, require explicit selection
213
- throw new Error(`Multiple servers found in config file. Please specify one with --server.\nAvailable servers: ${servers.join(", ")}`);
214
- }
215
- }
216
- // If config file is specified, load and use the options from the file. We must merge the args
217
- // from the command line and the file together, or we will miss the method options (--method,
218
- // etc.)
219
- if (options.config && options.server) {
220
- const config = loadConfigFile(options.config, options.server);
221
- if (config.type === "stdio") {
222
- return {
223
- command: config.command,
224
- args: [...(config.args || []), ...finalArgs],
225
- envArgs: { ...(config.env || {}), ...(options.e || {}) },
226
- cli: options.cli || false,
227
- transport: "stdio",
228
- headers: options.header,
229
- };
230
- }
231
- else if (config.type === "sse" || config.type === "streamable-http") {
232
- return {
233
- command: config.url,
234
- args: finalArgs,
235
- envArgs: options.e || {},
236
- cli: options.cli || false,
237
- transport: config.type,
238
- serverUrl: config.url,
239
- headers: options.header,
240
- };
241
- }
242
- else {
243
- // Backwards compatibility: if no type field, assume stdio
244
- return {
245
- command: config.command || "",
246
- args: [...(config.args || []), ...finalArgs],
247
- envArgs: { ...(config.env || {}), ...(options.e || {}) },
248
- cli: options.cli || false,
249
- transport: "stdio",
250
- headers: options.header,
251
- };
252
- }
253
- }
254
- // Otherwise use command line arguments
255
- const command = finalArgs[0] || "";
256
- const args = finalArgs.slice(1);
257
- // Map "http" shorthand to "streamable-http"
258
- let transport = options.transport;
259
- if (transport === "http") {
260
- transport = "streamable-http";
261
- }
262
- return {
263
- command,
264
- args,
265
- envArgs: options.e || {},
266
- cli: options.cli || false,
267
- transport: transport,
268
- serverUrl: options.serverUrl,
269
- headers: options.header,
270
- };
271
- }
272
- async function main() {
273
- process.on("uncaughtException", (error) => {
274
- handleError(error);
275
- });
276
- printDeprecationNotice();
277
- try {
278
- const args = parseArgs();
279
- if (args.cli) {
280
- await runCli(args);
281
- }
282
- else {
283
- await runWebClient(args);
284
- }
285
- }
286
- catch (error) {
287
- handleError(error);
288
- }
289
- }
290
- main();
@@ -1,38 +0,0 @@
1
- export const validLogLevels = [
2
- "trace",
3
- "debug",
4
- "info",
5
- "warn",
6
- "error",
7
- ];
8
- export async function connect(client, transport) {
9
- try {
10
- await client.connect(transport);
11
- if (client.getServerCapabilities()?.logging) {
12
- // default logging level is undefined in the spec, but the user of the
13
- // inspector most likely wants debug.
14
- await client.setLoggingLevel("debug");
15
- }
16
- }
17
- catch (error) {
18
- throw new Error(`Failed to connect to MCP server: ${error instanceof Error ? error.message : String(error)}`);
19
- }
20
- }
21
- export async function disconnect(transport) {
22
- try {
23
- await transport.close();
24
- }
25
- catch (error) {
26
- throw new Error(`Failed to disconnect from MCP server: ${error instanceof Error ? error.message : String(error)}`);
27
- }
28
- }
29
- // Set logging level
30
- export async function setLoggingLevel(client, level) {
31
- try {
32
- const response = await client.setLoggingLevel(level);
33
- return response;
34
- }
35
- catch (error) {
36
- throw new Error(`Failed to set logging level: ${error instanceof Error ? error.message : String(error)}`);
37
- }
38
- }
@@ -1,6 +0,0 @@
1
- // Re-export everything from the client modules
2
- export * from "./connection.js";
3
- export * from "./prompts.js";
4
- export * from "./resources.js";
5
- export * from "./tools.js";
6
- export * from "./types.js";
@@ -1,43 +0,0 @@
1
- // List available prompts
2
- export async function listPrompts(client, metadata) {
3
- try {
4
- const params = metadata && Object.keys(metadata).length > 0 ? { _meta: metadata } : {};
5
- const response = await client.listPrompts(params);
6
- return response;
7
- }
8
- catch (error) {
9
- throw new Error(`Failed to list prompts: ${error instanceof Error ? error.message : String(error)}`);
10
- }
11
- }
12
- // Get a prompt
13
- export async function getPrompt(client, name, args, metadata) {
14
- try {
15
- // Convert all arguments to strings for prompt arguments
16
- const stringArgs = {};
17
- if (args) {
18
- for (const [key, value] of Object.entries(args)) {
19
- if (typeof value === "string") {
20
- stringArgs[key] = value;
21
- }
22
- else if (value === null || value === undefined) {
23
- stringArgs[key] = String(value);
24
- }
25
- else {
26
- stringArgs[key] = JSON.stringify(value);
27
- }
28
- }
29
- }
30
- const params = {
31
- name,
32
- arguments: stringArgs,
33
- };
34
- if (metadata && Object.keys(metadata).length > 0) {
35
- params._meta = metadata;
36
- }
37
- const response = await client.getPrompt(params);
38
- return response;
39
- }
40
- catch (error) {
41
- throw new Error(`Failed to get prompt: ${error instanceof Error ? error.message : String(error)}`);
42
- }
43
- }
@@ -1,36 +0,0 @@
1
- // List available resources
2
- export async function listResources(client, metadata) {
3
- try {
4
- const params = metadata && Object.keys(metadata).length > 0 ? { _meta: metadata } : {};
5
- const response = await client.listResources(params);
6
- return response;
7
- }
8
- catch (error) {
9
- throw new Error(`Failed to list resources: ${error instanceof Error ? error.message : String(error)}`);
10
- }
11
- }
12
- // Read a resource
13
- export async function readResource(client, uri, metadata) {
14
- try {
15
- const params = { uri };
16
- if (metadata && Object.keys(metadata).length > 0) {
17
- params._meta = metadata;
18
- }
19
- const response = await client.readResource(params);
20
- return response;
21
- }
22
- catch (error) {
23
- throw new Error(`Failed to read resource ${uri}: ${error instanceof Error ? error.message : String(error)}`);
24
- }
25
- }
26
- // List resource templates
27
- export async function listResourceTemplates(client, metadata) {
28
- try {
29
- const params = metadata && Object.keys(metadata).length > 0 ? { _meta: metadata } : {};
30
- const response = await client.listResourceTemplates(params);
31
- return response;
32
- }
33
- catch (error) {
34
- throw new Error(`Failed to list resource templates: ${error instanceof Error ? error.message : String(error)}`);
35
- }
36
- }
@@ -1,87 +0,0 @@
1
- export async function listTools(client, metadata) {
2
- try {
3
- const params = metadata && Object.keys(metadata).length > 0 ? { _meta: metadata } : {};
4
- const response = await client.listTools(params);
5
- return response;
6
- }
7
- catch (error) {
8
- throw new Error(`Failed to list tools: ${error instanceof Error ? error.message : String(error)}`);
9
- }
10
- }
11
- function convertParameterValue(value, schema) {
12
- if (!value) {
13
- return value;
14
- }
15
- if (schema.type === "number" || schema.type === "integer") {
16
- return Number(value);
17
- }
18
- if (schema.type === "boolean") {
19
- return value.toLowerCase() === "true";
20
- }
21
- if (schema.type === "object" || schema.type === "array") {
22
- try {
23
- return JSON.parse(value);
24
- }
25
- catch (error) {
26
- return value;
27
- }
28
- }
29
- return value;
30
- }
31
- function convertParameters(tool, params) {
32
- const result = {};
33
- const properties = tool.inputSchema.properties || {};
34
- for (const [key, value] of Object.entries(params)) {
35
- const paramSchema = properties[key];
36
- if (paramSchema) {
37
- result[key] = convertParameterValue(value, paramSchema);
38
- }
39
- else {
40
- // If no schema is found for this parameter, keep it as string
41
- result[key] = value;
42
- }
43
- }
44
- return result;
45
- }
46
- export async function callTool(client, name, args, generalMetadata, toolSpecificMetadata) {
47
- try {
48
- const toolsResponse = await listTools(client, generalMetadata);
49
- const tools = toolsResponse.tools;
50
- const tool = tools.find((t) => t.name === name);
51
- let convertedArgs = args;
52
- if (tool) {
53
- // Convert parameters based on the tool's schema, but only for string values
54
- // since we now accept pre-parsed values from the CLI
55
- const stringArgs = {};
56
- for (const [key, value] of Object.entries(args)) {
57
- if (typeof value === "string") {
58
- stringArgs[key] = value;
59
- }
60
- }
61
- if (Object.keys(stringArgs).length > 0) {
62
- const convertedStringArgs = convertParameters(tool, stringArgs);
63
- convertedArgs = { ...args, ...convertedStringArgs };
64
- }
65
- }
66
- // Merge general metadata with tool-specific metadata
67
- // Tool-specific metadata takes precedence over general metadata
68
- let mergedMetadata;
69
- if (generalMetadata || toolSpecificMetadata) {
70
- mergedMetadata = {
71
- ...(generalMetadata || {}),
72
- ...(toolSpecificMetadata || {}),
73
- };
74
- }
75
- const response = await client.callTool({
76
- name: name,
77
- arguments: convertedArgs,
78
- _meta: mergedMetadata && Object.keys(mergedMetadata).length > 0
79
- ? mergedMetadata
80
- : undefined,
81
- });
82
- return response;
83
- }
84
- catch (error) {
85
- throw new Error(`Failed to call tool ${name}: ${error instanceof Error ? error.message : String(error)}`);
86
- }
87
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,18 +0,0 @@
1
- function formatError(error) {
2
- let message;
3
- if (error instanceof Error) {
4
- message = error.message;
5
- }
6
- else if (typeof error === "string") {
7
- message = error;
8
- }
9
- else {
10
- message = "Unknown error";
11
- }
12
- return message;
13
- }
14
- export function handleError(error) {
15
- const errorMessage = formatError(error);
16
- console.error(errorMessage);
17
- process.exit(1);
18
- }