@modelcontextprotocol/inspector 1.0.1 → 2.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -1,257 +0,0 @@
1
- #!/usr/bin/env node
2
- import * as fs from "fs";
3
- import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
- import { Command } from "commander";
5
- import { callTool, connect, disconnect, getPrompt, listPrompts, listResources, listResourceTemplates, listTools, readResource, setLoggingLevel, validLogLevels, } from "./client/index.js";
6
- import { handleError } from "./error-handler.js";
7
- import { createTransport } from "./transport.js";
8
- import { awaitableLog } from "./utils/awaitable-log.js";
9
- function createTransportOptions(target, transport, headers) {
10
- if (target.length === 0) {
11
- throw new Error("Target is required. Specify a URL or a command to execute.");
12
- }
13
- const [command, ...commandArgs] = target;
14
- if (!command) {
15
- throw new Error("Command is required.");
16
- }
17
- const isUrl = command.startsWith("http://") || command.startsWith("https://");
18
- if (isUrl && commandArgs.length > 0) {
19
- throw new Error("Arguments cannot be passed to a URL-based MCP server.");
20
- }
21
- let transportType;
22
- if (transport) {
23
- if (!isUrl && transport !== "stdio") {
24
- throw new Error("Only stdio transport can be used with local commands.");
25
- }
26
- if (isUrl && transport === "stdio") {
27
- throw new Error("stdio transport cannot be used with URLs.");
28
- }
29
- transportType = transport;
30
- }
31
- else if (isUrl) {
32
- const url = new URL(command);
33
- if (url.pathname.endsWith("/mcp")) {
34
- transportType = "http";
35
- }
36
- else if (url.pathname.endsWith("/sse")) {
37
- transportType = "sse";
38
- }
39
- else {
40
- transportType = "sse";
41
- }
42
- }
43
- else {
44
- transportType = "stdio";
45
- }
46
- return {
47
- transportType,
48
- command: isUrl ? undefined : command,
49
- args: isUrl ? undefined : commandArgs,
50
- url: isUrl ? command : undefined,
51
- headers,
52
- };
53
- }
54
- async function callMethod(args) {
55
- // Read package.json to get name and version for client identity
56
- const pathA = "../package.json"; // We're in package @modelcontextprotocol/inspector-cli
57
- const pathB = "../../package.json"; // We're in package @modelcontextprotocol/inspector
58
- let packageJson;
59
- let packageJsonData = await import(fs.existsSync(pathA) ? pathA : pathB, {
60
- with: { type: "json" },
61
- });
62
- packageJson = packageJsonData.default;
63
- const transportOptions = createTransportOptions(args.target, args.transport, args.headers);
64
- const transport = createTransport(transportOptions);
65
- const [, name = packageJson.name] = packageJson.name.split("/");
66
- const version = packageJson.version;
67
- const clientIdentity = { name, version };
68
- const client = new Client(clientIdentity);
69
- try {
70
- await connect(client, transport);
71
- let result;
72
- // Tools methods
73
- if (args.method === "tools/list") {
74
- result = await listTools(client, args.metadata);
75
- }
76
- else if (args.method === "tools/call") {
77
- if (!args.toolName) {
78
- throw new Error("Tool name is required for tools/call method. Use --tool-name to specify the tool name.");
79
- }
80
- result = await callTool(client, args.toolName, args.toolArg || {}, args.metadata, args.toolMeta);
81
- }
82
- // Resources methods
83
- else if (args.method === "resources/list") {
84
- result = await listResources(client, args.metadata);
85
- }
86
- else if (args.method === "resources/read") {
87
- if (!args.uri) {
88
- throw new Error("URI is required for resources/read method. Use --uri to specify the resource URI.");
89
- }
90
- result = await readResource(client, args.uri, args.metadata);
91
- }
92
- else if (args.method === "resources/templates/list") {
93
- result = await listResourceTemplates(client, args.metadata);
94
- }
95
- // Prompts methods
96
- else if (args.method === "prompts/list") {
97
- result = await listPrompts(client, args.metadata);
98
- }
99
- else if (args.method === "prompts/get") {
100
- if (!args.promptName) {
101
- throw new Error("Prompt name is required for prompts/get method. Use --prompt-name to specify the prompt name.");
102
- }
103
- result = await getPrompt(client, args.promptName, args.promptArgs || {}, args.metadata);
104
- }
105
- // Logging methods
106
- else if (args.method === "logging/setLevel") {
107
- if (!args.logLevel) {
108
- throw new Error("Log level is required for logging/setLevel method. Use --log-level to specify the log level.");
109
- }
110
- result = await setLoggingLevel(client, args.logLevel);
111
- }
112
- else {
113
- throw new Error(`Unsupported method: ${args.method}. Supported methods include: tools/list, tools/call, resources/list, resources/read, resources/templates/list, prompts/list, prompts/get, logging/setLevel`);
114
- }
115
- await awaitableLog(JSON.stringify(result, null, 2));
116
- }
117
- finally {
118
- try {
119
- await disconnect(transport);
120
- }
121
- catch (disconnectError) {
122
- throw disconnectError;
123
- }
124
- }
125
- }
126
- function parseKeyValuePair(value, previous = {}) {
127
- const parts = value.split("=");
128
- const key = parts[0];
129
- const val = parts.slice(1).join("=");
130
- if (val === undefined || val === "") {
131
- throw new Error(`Invalid parameter format: ${value}. Use key=value format.`);
132
- }
133
- // Try to parse as JSON first
134
- let parsedValue;
135
- try {
136
- parsedValue = JSON.parse(val);
137
- }
138
- catch {
139
- // If JSON parsing fails, keep as string
140
- parsedValue = val;
141
- }
142
- return { ...previous, [key]: parsedValue };
143
- }
144
- function parseHeaderPair(value, previous = {}) {
145
- const colonIndex = value.indexOf(":");
146
- if (colonIndex === -1) {
147
- throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
148
- }
149
- const key = value.slice(0, colonIndex).trim();
150
- const val = value.slice(colonIndex + 1).trim();
151
- if (key === "" || val === "") {
152
- throw new Error(`Invalid header format: ${value}. Use "HeaderName: Value" format.`);
153
- }
154
- return { ...previous, [key]: val };
155
- }
156
- function parseArgs() {
157
- const program = new Command();
158
- // Find if there's a -- in the arguments and split them
159
- const argSeparatorIndex = process.argv.indexOf("--");
160
- let preArgs = process.argv;
161
- let postArgs = [];
162
- if (argSeparatorIndex !== -1) {
163
- preArgs = process.argv.slice(0, argSeparatorIndex);
164
- postArgs = process.argv.slice(argSeparatorIndex + 1);
165
- }
166
- program
167
- .name("inspector-cli")
168
- .allowUnknownOption()
169
- .argument("<target...>", "Command and arguments or URL of the MCP server")
170
- //
171
- // Method selection
172
- //
173
- .option("--method <method>", "Method to invoke")
174
- //
175
- // Tool-related options
176
- //
177
- .option("--tool-name <toolName>", "Tool name (for tools/call method)")
178
- .option("--tool-arg <pairs...>", "Tool argument as key=value pair", parseKeyValuePair, {})
179
- //
180
- // Resource-related options
181
- //
182
- .option("--uri <uri>", "URI of the resource (for resources/read method)")
183
- //
184
- // Prompt-related options
185
- //
186
- .option("--prompt-name <promptName>", "Name of the prompt (for prompts/get method)")
187
- .option("--prompt-args <pairs...>", "Prompt arguments as key=value pairs", parseKeyValuePair, {})
188
- //
189
- // Logging options
190
- //
191
- .option("--log-level <level>", "Logging level (for logging/setLevel method)", (value) => {
192
- if (!validLogLevels.includes(value)) {
193
- throw new Error(`Invalid log level: ${value}. Valid levels are: ${validLogLevels.join(", ")}`);
194
- }
195
- return value;
196
- })
197
- //
198
- // Transport options
199
- //
200
- .option("--transport <type>", "Transport type (sse, http, or stdio). Auto-detected from URL: /mcp → http, /sse → sse, commands → stdio", (value) => {
201
- const validTransports = ["sse", "http", "stdio"];
202
- if (!validTransports.includes(value)) {
203
- throw new Error(`Invalid transport type: ${value}. Valid types are: ${validTransports.join(", ")}`);
204
- }
205
- return value;
206
- })
207
- //
208
- // HTTP headers
209
- //
210
- .option("--header <headers...>", 'HTTP headers as "HeaderName: Value" pairs (for HTTP/SSE transports)', parseHeaderPair, {})
211
- //
212
- // Metadata options
213
- //
214
- .option("--metadata <pairs...>", "General metadata as key=value pairs (applied to all methods)", parseKeyValuePair, {})
215
- .option("--tool-metadata <pairs...>", "Tool-specific metadata as key=value pairs (for tools/call method only)", parseKeyValuePair, {});
216
- // Parse only the arguments before --
217
- program.parse(preArgs);
218
- const options = program.opts();
219
- let remainingArgs = program.args;
220
- // Add back any arguments that came after --
221
- const finalArgs = [...remainingArgs, ...postArgs];
222
- if (!options.method) {
223
- throw new Error("Method is required. Use --method to specify the method to invoke.");
224
- }
225
- return {
226
- target: finalArgs,
227
- ...options,
228
- headers: options.header, // commander.js uses 'header' field, map to 'headers'
229
- metadata: options.metadata
230
- ? Object.fromEntries(Object.entries(options.metadata).map(([key, value]) => [
231
- key,
232
- String(value),
233
- ]))
234
- : undefined,
235
- toolMeta: options.toolMetadata
236
- ? Object.fromEntries(Object.entries(options.toolMetadata).map(([key, value]) => [
237
- key,
238
- String(value),
239
- ]))
240
- : undefined,
241
- };
242
- }
243
- async function main() {
244
- process.on("uncaughtException", (error) => {
245
- handleError(error);
246
- });
247
- try {
248
- const args = parseArgs();
249
- await callMethod(args);
250
- // Explicitly exit to ensure process terminates in CI
251
- process.exit(0);
252
- }
253
- catch (error) {
254
- handleError(error);
255
- }
256
- }
257
- main();
@@ -1,65 +0,0 @@
1
- import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
2
- import { getDefaultEnvironment, StdioClientTransport, } from "@modelcontextprotocol/sdk/client/stdio.js";
3
- import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
- import { findActualExecutable } from "spawn-rx";
5
- function createStdioTransport(options) {
6
- let args = [];
7
- if (options.args !== undefined) {
8
- args = options.args;
9
- }
10
- const processEnv = {};
11
- for (const [key, value] of Object.entries(process.env)) {
12
- if (value !== undefined) {
13
- processEnv[key] = value;
14
- }
15
- }
16
- const defaultEnv = getDefaultEnvironment();
17
- const env = {
18
- ...defaultEnv,
19
- ...processEnv,
20
- };
21
- const { cmd: actualCommand, args: actualArgs } = findActualExecutable(options.command ?? "", args);
22
- return new StdioClientTransport({
23
- command: actualCommand,
24
- args: actualArgs,
25
- env,
26
- stderr: "pipe",
27
- });
28
- }
29
- export function createTransport(options) {
30
- const { transportType } = options;
31
- try {
32
- if (transportType === "stdio") {
33
- return createStdioTransport(options);
34
- }
35
- // If not STDIO, then it must be either SSE or HTTP.
36
- if (!options.url) {
37
- throw new Error("URL must be provided for SSE or HTTP transport types.");
38
- }
39
- const url = new URL(options.url);
40
- if (transportType === "sse") {
41
- const transportOptions = options.headers
42
- ? {
43
- requestInit: {
44
- headers: options.headers,
45
- },
46
- }
47
- : undefined;
48
- return new SSEClientTransport(url, transportOptions);
49
- }
50
- if (transportType === "http") {
51
- const transportOptions = options.headers
52
- ? {
53
- requestInit: {
54
- headers: options.headers,
55
- },
56
- }
57
- : undefined;
58
- return new StreamableHTTPClientTransport(url, transportOptions);
59
- }
60
- throw new Error(`Unsupported transport type: ${transportType}`);
61
- }
62
- catch (error) {
63
- throw new Error(`Failed to create transport: ${error instanceof Error ? error.message : String(error)}`);
64
- }
65
- }
@@ -1,7 +0,0 @@
1
- export function awaitableLog(logValue) {
2
- return new Promise((resolve) => {
3
- process.stdout.write(logValue, () => {
4
- resolve();
5
- });
6
- });
7
- }
@@ -1,62 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import open from "open";
4
- import { join, dirname } from "path";
5
- import { fileURLToPath } from "url";
6
- import handler from "serve-handler";
7
- import http from "http";
8
-
9
- const __dirname = dirname(fileURLToPath(import.meta.url));
10
- const distPath = join(__dirname, "../dist");
11
-
12
- const server = http.createServer((request, response) => {
13
- const handlerOptions = {
14
- public: distPath,
15
- rewrites: [{ source: "/**", destination: "/index.html" }],
16
- headers: [
17
- {
18
- // Ensure index.html is never cached
19
- source: "index.html",
20
- headers: [
21
- {
22
- key: "Cache-Control",
23
- value: "no-cache, no-store, max-age=0",
24
- },
25
- ],
26
- },
27
- {
28
- // Allow long-term caching for hashed assets
29
- source: "assets/**",
30
- headers: [
31
- {
32
- key: "Cache-Control",
33
- value: "public, max-age=31536000, immutable",
34
- },
35
- ],
36
- },
37
- ],
38
- };
39
-
40
- return handler(request, response, handlerOptions);
41
- });
42
-
43
- const port = parseInt(process.env.CLIENT_PORT || "6274", 10);
44
- const host = process.env.HOST || "localhost";
45
- server.on("listening", () => {
46
- const url = process.env.INSPECTOR_URL || `http://${host}:${port}`;
47
- console.log(`\nšŸš€ MCP Inspector is up and running at:\n ${url}\n`);
48
- if (process.env.MCP_AUTO_OPEN_ENABLED !== "false") {
49
- console.log(`🌐 Opening browser...`);
50
- open(url);
51
- }
52
- });
53
- server.on("error", (err) => {
54
- if (err.message.includes(`EADDRINUSE`)) {
55
- console.error(
56
- `āŒ MCP Inspector PORT IS IN USE at http://${host}:${port} āŒ `,
57
- );
58
- } else {
59
- throw err;
60
- }
61
- });
62
- server.listen(port, host);