@mcpjam/inspector 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Anthropic, PBC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,258 @@
1
+ # MCPJam Inspector
2
+
3
+ The MCPJam inspector is a dev tool for testing and debugging MCP servers. The MCPJam inspector is a fork of the mcp-inspector with additional improvements.
4
+
5
+ ## Running the Inspector
6
+
7
+ ### Requirements
8
+
9
+ - Node.js: ^22.7.5
10
+
11
+ ### From an MCP server repository
12
+
13
+ To inspect an MCP server implementation, there's no need to clone this repo. Instead, use `npx`. For example, if your server is built at `build/index.js`:
14
+
15
+ ```bash
16
+ npx @mcpjam/inspector node build/index.js
17
+ ```
18
+
19
+ You can pass both arguments and environment variables to your MCP server. Arguments are passed directly to your server, while environment variables can be set using the `-e` flag:
20
+
21
+ ```bash
22
+ # Pass arguments only
23
+ npx @mcpjam/inspector node build/index.js arg1 arg2
24
+
25
+ # Pass environment variables only
26
+ npx @mcpjam/inspector -e key=value -e key2=$VALUE2 node build/index.js
27
+
28
+ # Pass both environment variables and arguments
29
+ npx @modelcontextprotocol/inspector -e key=value -e key2=$VALUE2 node build/index.js arg1 arg2
30
+
31
+ # Use -- to separate inspector flags from server arguments
32
+ npx @modelcontextprotocol/inspector -e key=$VALUE -- node build/index.js -e server-flag
33
+ ```
34
+
35
+ 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:
36
+
37
+ ```bash
38
+ CLIENT_PORT=8080 SERVER_PORT=9000 npx @modelcontextprotocol/inspector node build/index.js
39
+ ```
40
+
41
+ For more details on ways to use the inspector, see the [Inspector section of the MCP docs site](https://modelcontextprotocol.io/docs/tools/inspector). For help with debugging, see the [Debugging guide](https://modelcontextprotocol.io/docs/tools/debugging).
42
+
43
+ ### Servers File Export
44
+
45
+ The MCP Inspector provides convenient buttons to export server launch configurations for use in clients such as Cursor, Claude Code, or the Inspector's CLI. The file is usually called `mcp.json`.
46
+
47
+ - **Server Entry** - Copies a single server configuration entry to your clipboard. This can be added to your `mcp.json` file inside the `mcpServers` object with your preferred server name.
48
+
49
+ **STDIO transport example:**
50
+
51
+ ```json
52
+ {
53
+ "command": "node",
54
+ "args": ["build/index.js", "--debug"],
55
+ "env": {
56
+ "API_KEY": "your-api-key",
57
+ "DEBUG": "true"
58
+ }
59
+ }
60
+ ```
61
+
62
+ **SSE transport example:**
63
+
64
+ ```json
65
+ {
66
+ "type": "sse",
67
+ "url": "http://localhost:3000/events",
68
+ "note": "For SSE connections, add this URL directly in Client"
69
+ }
70
+ ```
71
+
72
+ - **Servers File** - Copies a complete MCP configuration file structure to your clipboard, with your current server configuration added as `default-server`. This can be saved directly as `mcp.json`.
73
+
74
+ **STDIO transport example:**
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "default-server": {
80
+ "command": "node",
81
+ "args": ["build/index.js", "--debug"],
82
+ "env": {
83
+ "API_KEY": "your-api-key",
84
+ "DEBUG": "true"
85
+ }
86
+ }
87
+ }
88
+ }
89
+ ```
90
+
91
+ **SSE transport example:**
92
+
93
+ ```json
94
+ {
95
+ "mcpServers": {
96
+ "default-server": {
97
+ "type": "sse",
98
+ "url": "http://localhost:3000/events",
99
+ "note": "For SSE connections, add this URL directly in Client"
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ These buttons appear in the Inspector UI after you've configured your server settings, making it easy to save and reuse your configurations.
106
+
107
+ For SSE transport connections, the Inspector provides similar functionality for both buttons. The "Server Entry" button copies the SSE URL configuration that can be added to your existing configuration file, while the "Servers File" button creates a complete configuration file containing the SSE URL for direct use in clients.
108
+
109
+ You can paste the Server Entry into your existing `mcp.json` file under your chosen server name, or use the complete Servers File payload to create a new configuration file.
110
+
111
+ ### Authentication
112
+
113
+ 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. You can override the header name using the input field in the sidebar.
114
+
115
+ ### Security Considerations
116
+
117
+ 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.
118
+
119
+ ### Configuration
120
+
121
+ The MCP Inspector supports the following configuration settings. To change them, click on the `Configuration` button in the MCP Inspector UI:
122
+
123
+ | Setting | Description | Default |
124
+ | --------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------- |
125
+ | `MCP_SERVER_REQUEST_TIMEOUT` | Timeout for requests to the MCP server (ms) | 10000 |
126
+ | `MCP_REQUEST_TIMEOUT_RESET_ON_PROGRESS` | Reset timeout on progress notifications | true |
127
+ | `MCP_REQUEST_MAX_TOTAL_TIMEOUT` | Maximum total timeout for requests sent to the MCP server (ms) (Use with progress notifications) | 60000 |
128
+ | `MCP_PROXY_FULL_ADDRESS` | Set this if you are running the MCP Inspector Proxy on a non-default address. Example: http://10.1.1.22:5577 | "" |
129
+ | `MCP_AUTO_OPEN_ENABLED` | Enable automatic browser opening when inspector starts. Only as environment var, not configurable in browser. | true |
130
+
131
+ These settings can be adjusted in real-time through the UI and will persist across sessions.
132
+
133
+ The inspector also supports configuration files to store settings for different MCP servers. This is useful when working with multiple servers or complex configurations:
134
+
135
+ ```bash
136
+ npx @modelcontextprotocol/inspector --config path/to/config.json --server everything
137
+ ```
138
+
139
+ Example server configuration file:
140
+
141
+ ```json
142
+ {
143
+ "mcpServers": {
144
+ "everything": {
145
+ "command": "npx",
146
+ "args": ["@modelcontextprotocol/server-everything"],
147
+ "env": {
148
+ "hello": "Hello MCP!"
149
+ }
150
+ },
151
+ "my-server": {
152
+ "command": "node",
153
+ "args": ["build/index.js", "arg1", "arg2"],
154
+ "env": {
155
+ "key": "value",
156
+ "key2": "value2"
157
+ }
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ > **Tip:** You can easily generate this configuration format using the **Server Entry** and **Servers File** buttons in the Inspector UI, as described in the Servers File Export section above.
164
+
165
+ You can also set the initial `transport` type, `serverUrl`, `serverCommand`, and `serverArgs` via query params, for example:
166
+
167
+ ```
168
+ http://localhost:6274/?transport=sse&serverUrl=http://localhost:8787/sse
169
+ http://localhost:6274/?transport=streamable-http&serverUrl=http://localhost:8787/mcp
170
+ http://localhost:6274/?transport=stdio&serverCommand=npx&serverArgs=arg1%20arg2
171
+ ```
172
+
173
+ You can also set initial config settings via query params, for example:
174
+
175
+ ```
176
+ http://localhost:6274/?MCP_SERVER_REQUEST_TIMEOUT=10000&MCP_REQUEST_TIMEOUT_RESET_ON_PROGRESS=false&MCP_PROXY_FULL_ADDRESS=http://10.1.1.22:5577
177
+ ```
178
+
179
+ Note that if both the query param and the corresponding localStorage item are set, the query param will take precedence.
180
+
181
+ ### From this repository
182
+
183
+ If you're working on the inspector itself:
184
+
185
+ Development mode:
186
+
187
+ ```bash
188
+ npm run dev
189
+ ```
190
+
191
+ > **Note for Windows users:**
192
+ > On Windows, use the following command instead:
193
+ >
194
+ > ```bash
195
+ > npm run dev:windows
196
+ > ```
197
+
198
+ Production mode:
199
+
200
+ ```bash
201
+ npm run build
202
+ npm start
203
+ ```
204
+
205
+ ### CLI Mode
206
+
207
+ CLI mode enables programmatic interaction with MCP servers from the command line, ideal for scripting, automation, and integration with coding assistants. This creates an efficient feedback loop for MCP server development.
208
+
209
+ ```bash
210
+ npx @modelcontextprotocol/inspector --cli node build/index.js
211
+ ```
212
+
213
+ The CLI mode supports most operations across tools, resources, and prompts. A few examples:
214
+
215
+ ```bash
216
+ # Basic usage
217
+ npx @modelcontextprotocol/inspector --cli node build/index.js
218
+
219
+ # With config file
220
+ npx @modelcontextprotocol/inspector --cli --config path/to/config.json --server myserver
221
+
222
+ # List available tools
223
+ npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
224
+
225
+ # Call a specific tool
226
+ npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/call --tool-name mytool --tool-arg key=value --tool-arg another=value2
227
+
228
+ # List available resources
229
+ npx @modelcontextprotocol/inspector --cli node build/index.js --method resources/list
230
+
231
+ # List available prompts
232
+ npx @modelcontextprotocol/inspector --cli node build/index.js --method prompts/list
233
+
234
+ # Connect to a remote MCP server
235
+ npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com
236
+
237
+ # Call a tool on a remote server
238
+ npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method tools/call --tool-name remotetool --tool-arg param=value
239
+
240
+ # List resources from a remote server
241
+ npx @modelcontextprotocol/inspector --cli https://my-mcp-server.example.com --method resources/list
242
+ ```
243
+
244
+ ### UI Mode vs CLI Mode: When to Use Each
245
+
246
+ | Use Case | UI Mode | CLI Mode |
247
+ | ------------------------ | ------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
248
+ | **Server Development** | Visual interface for interactive testing and debugging during development | Scriptable commands for quick testing and continuous integration; creates feedback loops with AI coding assistants like Cursor for rapid development |
249
+ | **Resource Exploration** | Interactive browser with hierarchical navigation and JSON visualization | Programmatic listing and reading for automation and scripting |
250
+ | **Tool Testing** | Form-based parameter input with real-time response visualization | Command-line tool execution with JSON output for scripting |
251
+ | **Prompt Engineering** | Interactive sampling with streaming responses and visual comparison | Batch processing of prompts with machine-readable output |
252
+ | **Debugging** | Request history, visualized errors, and real-time notifications | Direct JSON output for log analysis and integration with other tools |
253
+ | **Automation** | N/A | Ideal for CI/CD pipelines, batch processing, and integration with coding assistants |
254
+ | **Learning MCP** | Rich visual interface helps new users understand server capabilities | Simplified commands for focused learning of specific endpoints |
255
+
256
+ ## License
257
+
258
+ This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,195 @@
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
+ function handleError(error) {
10
+ let message;
11
+ if (error instanceof Error) {
12
+ message = error.message;
13
+ }
14
+ else if (typeof error === "string") {
15
+ message = error;
16
+ }
17
+ else {
18
+ message = "Unknown error";
19
+ }
20
+ console.error(message);
21
+ process.exit(1);
22
+ }
23
+ function delay(ms) {
24
+ return new Promise((resolve) => setTimeout(resolve, ms, true));
25
+ }
26
+ async function runWebClient(args) {
27
+ const inspectorServerPath = resolve(__dirname, "../../", "server", "build", "index.js");
28
+ // Path to the client entry point
29
+ const inspectorClientPath = resolve(__dirname, "../../", "client", "bin", "client.js");
30
+ const CLIENT_PORT = process.env.CLIENT_PORT ?? "6274";
31
+ const SERVER_PORT = process.env.SERVER_PORT ?? "6277";
32
+ console.log("Starting MCP inspector...");
33
+ const abort = new AbortController();
34
+ let cancelled = false;
35
+ process.on("SIGINT", () => {
36
+ cancelled = true;
37
+ abort.abort();
38
+ });
39
+ let server;
40
+ let serverOk;
41
+ try {
42
+ server = spawnPromise("node", [
43
+ inspectorServerPath,
44
+ ...(args.command ? [`--env`, args.command] : []),
45
+ ...(args.args ? [`--args=${args.args.join(" ")}`] : []),
46
+ ], {
47
+ env: {
48
+ ...process.env,
49
+ PORT: SERVER_PORT,
50
+ MCP_ENV_VARS: JSON.stringify(args.envArgs),
51
+ },
52
+ signal: abort.signal,
53
+ echoOutput: true,
54
+ });
55
+ // Make sure server started before starting client
56
+ serverOk = await Promise.race([server, delay(2 * 1000)]);
57
+ }
58
+ catch (error) { }
59
+ if (serverOk) {
60
+ try {
61
+ await spawnPromise("node", [inspectorClientPath], {
62
+ env: { ...process.env, PORT: CLIENT_PORT },
63
+ signal: abort.signal,
64
+ echoOutput: true,
65
+ });
66
+ }
67
+ catch (e) {
68
+ if (!cancelled || process.env.DEBUG)
69
+ throw e;
70
+ }
71
+ }
72
+ }
73
+ async function runCli(args) {
74
+ const projectRoot = resolve(__dirname, "..");
75
+ const cliPath = resolve(projectRoot, "build", "index.js");
76
+ const abort = new AbortController();
77
+ let cancelled = false;
78
+ process.on("SIGINT", () => {
79
+ cancelled = true;
80
+ abort.abort();
81
+ });
82
+ try {
83
+ await spawnPromise("node", [cliPath, args.command, ...args.args], {
84
+ env: { ...process.env, ...args.envArgs },
85
+ signal: abort.signal,
86
+ echoOutput: true,
87
+ });
88
+ }
89
+ catch (e) {
90
+ if (!cancelled || process.env.DEBUG) {
91
+ throw e;
92
+ }
93
+ }
94
+ }
95
+ function loadConfigFile(configPath, serverName) {
96
+ try {
97
+ const resolvedConfigPath = path.isAbsolute(configPath)
98
+ ? configPath
99
+ : path.resolve(process.cwd(), configPath);
100
+ if (!fs.existsSync(resolvedConfigPath)) {
101
+ throw new Error(`Config file not found: ${resolvedConfigPath}`);
102
+ }
103
+ const configContent = fs.readFileSync(resolvedConfigPath, "utf8");
104
+ const parsedConfig = JSON.parse(configContent);
105
+ if (!parsedConfig.mcpServers || !parsedConfig.mcpServers[serverName]) {
106
+ const availableServers = Object.keys(parsedConfig.mcpServers || {}).join(", ");
107
+ throw new Error(`Server '${serverName}' not found in config file. Available servers: ${availableServers}`);
108
+ }
109
+ const serverConfig = parsedConfig.mcpServers[serverName];
110
+ return serverConfig;
111
+ }
112
+ catch (err) {
113
+ if (err instanceof SyntaxError) {
114
+ throw new Error(`Invalid JSON in config file: ${err.message}`);
115
+ }
116
+ throw err;
117
+ }
118
+ }
119
+ function parseKeyValuePair(value, previous = {}) {
120
+ const parts = value.split("=");
121
+ const key = parts[0];
122
+ const val = parts.slice(1).join("=");
123
+ if (val === undefined || val === "") {
124
+ throw new Error(`Invalid parameter format: ${value}. Use key=value format.`);
125
+ }
126
+ return { ...previous, [key]: val };
127
+ }
128
+ function parseArgs() {
129
+ const program = new Command();
130
+ const argSeparatorIndex = process.argv.indexOf("--");
131
+ let preArgs = process.argv;
132
+ let postArgs = [];
133
+ if (argSeparatorIndex !== -1) {
134
+ preArgs = process.argv.slice(0, argSeparatorIndex);
135
+ postArgs = process.argv.slice(argSeparatorIndex + 1);
136
+ }
137
+ program
138
+ .name("inspector-bin")
139
+ .allowExcessArguments()
140
+ .allowUnknownOption()
141
+ .option("-e <env>", "environment variables in KEY=VALUE format", parseKeyValuePair, {})
142
+ .option("--config <path>", "config file path")
143
+ .option("--server <n>", "server name from config file")
144
+ .option("--cli", "enable CLI mode");
145
+ // Parse only the arguments before --
146
+ program.parse(preArgs);
147
+ const options = program.opts();
148
+ const remainingArgs = program.args;
149
+ // Add back any arguments that came after --
150
+ const finalArgs = [...remainingArgs, ...postArgs];
151
+ // Validate that config and server are provided together
152
+ if ((options.config && !options.server) ||
153
+ (!options.config && options.server)) {
154
+ throw new Error("Both --config and --server must be provided together. If you specify one, you must specify the other.");
155
+ }
156
+ // If config file is specified, load and use the options from the file. We must merge the args
157
+ // from the command line and the file together, or we will miss the method options (--method,
158
+ // etc.)
159
+ if (options.config && options.server) {
160
+ const config = loadConfigFile(options.config, options.server);
161
+ return {
162
+ command: config.command,
163
+ args: [...(config.args || []), ...finalArgs],
164
+ envArgs: { ...(config.env || {}), ...(options.e || {}) },
165
+ cli: options.cli || false,
166
+ };
167
+ }
168
+ // Otherwise use command line arguments
169
+ const command = finalArgs[0] || "";
170
+ const args = finalArgs.slice(1);
171
+ return {
172
+ command,
173
+ args,
174
+ envArgs: options.e || {},
175
+ cli: options.cli || false,
176
+ };
177
+ }
178
+ async function main() {
179
+ process.on("uncaughtException", (error) => {
180
+ handleError(error);
181
+ });
182
+ try {
183
+ const args = parseArgs();
184
+ if (args.cli) {
185
+ runCli(args);
186
+ }
187
+ else {
188
+ await runWebClient(args);
189
+ }
190
+ }
191
+ catch (error) {
192
+ handleError(error);
193
+ }
194
+ }
195
+ main();
@@ -0,0 +1,33 @@
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
+ }
12
+ catch (error) {
13
+ throw new Error(`Failed to connect to MCP server: ${error instanceof Error ? error.message : String(error)}`);
14
+ }
15
+ }
16
+ export async function disconnect(transport) {
17
+ try {
18
+ await transport.close();
19
+ }
20
+ catch (error) {
21
+ throw new Error(`Failed to disconnect from MCP server: ${error instanceof Error ? error.message : String(error)}`);
22
+ }
23
+ }
24
+ // Set logging level
25
+ export async function setLoggingLevel(client, level) {
26
+ try {
27
+ const response = await client.setLoggingLevel(level);
28
+ return response;
29
+ }
30
+ catch (error) {
31
+ throw new Error(`Failed to set logging level: ${error instanceof Error ? error.message : String(error)}`);
32
+ }
33
+ }
@@ -0,0 +1,6 @@
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";
@@ -0,0 +1,23 @@
1
+ // List available prompts
2
+ export async function listPrompts(client) {
3
+ try {
4
+ const response = await client.listPrompts();
5
+ return response;
6
+ }
7
+ catch (error) {
8
+ throw new Error(`Failed to list prompts: ${error instanceof Error ? error.message : String(error)}`);
9
+ }
10
+ }
11
+ // Get a prompt
12
+ export async function getPrompt(client, name, args) {
13
+ try {
14
+ const response = await client.getPrompt({
15
+ name,
16
+ arguments: args || {},
17
+ });
18
+ return response;
19
+ }
20
+ catch (error) {
21
+ throw new Error(`Failed to get prompt: ${error instanceof Error ? error.message : String(error)}`);
22
+ }
23
+ }
@@ -0,0 +1,30 @@
1
+ // List available resources
2
+ export async function listResources(client) {
3
+ try {
4
+ const response = await client.listResources();
5
+ return response;
6
+ }
7
+ catch (error) {
8
+ throw new Error(`Failed to list resources: ${error instanceof Error ? error.message : String(error)}`);
9
+ }
10
+ }
11
+ // Read a resource
12
+ export async function readResource(client, uri) {
13
+ try {
14
+ const response = await client.readResource({ uri });
15
+ return response;
16
+ }
17
+ catch (error) {
18
+ throw new Error(`Failed to read resource ${uri}: ${error instanceof Error ? error.message : String(error)}`);
19
+ }
20
+ }
21
+ // List resource templates
22
+ export async function listResourceTemplates(client) {
23
+ try {
24
+ const response = await client.listResourceTemplates();
25
+ return response;
26
+ }
27
+ catch (error) {
28
+ throw new Error(`Failed to list resource templates: ${error instanceof Error ? error.message : String(error)}`);
29
+ }
30
+ }
@@ -0,0 +1,64 @@
1
+ export async function listTools(client) {
2
+ try {
3
+ const response = await client.listTools();
4
+ return response;
5
+ }
6
+ catch (error) {
7
+ throw new Error(`Failed to list tools: ${error instanceof Error ? error.message : String(error)}`);
8
+ }
9
+ }
10
+ function convertParameterValue(value, schema) {
11
+ if (!value) {
12
+ return value;
13
+ }
14
+ if (schema.type === "number" || schema.type === "integer") {
15
+ return Number(value);
16
+ }
17
+ if (schema.type === "boolean") {
18
+ return value.toLowerCase() === "true";
19
+ }
20
+ if (schema.type === "object" || schema.type === "array") {
21
+ try {
22
+ return JSON.parse(value);
23
+ }
24
+ catch (error) {
25
+ return value;
26
+ }
27
+ }
28
+ return value;
29
+ }
30
+ function convertParameters(tool, params) {
31
+ const result = {};
32
+ const properties = tool.inputSchema.properties || {};
33
+ for (const [key, value] of Object.entries(params)) {
34
+ const paramSchema = properties[key];
35
+ if (paramSchema) {
36
+ result[key] = convertParameterValue(value, paramSchema);
37
+ }
38
+ else {
39
+ // If no schema is found for this parameter, keep it as string
40
+ result[key] = value;
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+ export async function callTool(client, name, args) {
46
+ try {
47
+ const toolsResponse = await listTools(client);
48
+ const tools = toolsResponse.tools;
49
+ const tool = tools.find((t) => t.name === name);
50
+ let convertedArgs = args;
51
+ if (tool) {
52
+ // Convert parameters based on the tool's schema
53
+ convertedArgs = convertParameters(tool, args);
54
+ }
55
+ const response = await client.callTool({
56
+ name: name,
57
+ arguments: convertedArgs,
58
+ });
59
+ return response;
60
+ }
61
+ catch (error) {
62
+ throw new Error(`Failed to call tool ${name}: ${error instanceof Error ? error.message : String(error)}`);
63
+ }
64
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
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
+ }