Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,28 @@ To inspect an MCP server implementation, there's no need to clone this repo. Ins
```bash
npx @modelcontextprotocol/inspector build/index.js
```

You can also pass arguments along which will get passed as arguments to your MCP server:

```
```bash
npx @modelcontextprotocol/inspector build/index.js arg1 arg2 ...
```

Environment variables can be passed to your MCP server using either the long form `--envVars` or short form `-e` flags:

```bash
# Long form
npx @modelcontextprotocol/inspector build/index.js --envVars API_KEY=abc123 --envVars DEBUG=true

# Short form
npx @modelcontextprotocol/inspector build/index.js -e API_KEY=abc123 -e DEBUG=true
```

Environment variables are merged with the following precedence:
- Base: process.env (system environment)
- Override: Command line envVars (using either --envVars or -e)
- Final Override: Query parameters
```

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:

```bash
Expand All @@ -45,6 +60,27 @@ npm run build
npm start
```

## Testing

The inspector includes a comprehensive test suite. To run the tests:

```bash
cd server
npm test
```

### Test Coverage

The test suite includes:
- Environment variable handling
- Single variable with long flag (--envVars)
- Single variable with short flag (-e)
- Multiple environment variables
- Empty environment variables list
- Environment variable object merging

To add new tests, place them in the `server/src/__tests__` directory.

## License

This project is licensed under the MIT License—see the [LICENSE](LICENSE) file for details.
15 changes: 9 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@
"@types/cors": "^2.8.17",
"@types/eventsource": "^1.1.15",
"@types/express": "^4.17.21",
"@types/node": "^22.10.5",
"@types/shell-quote": "^1.7.5",
"@types/ws": "^8.5.12",
"spawn-rx": "^5.1.1",
"tsx": "^4.19.0",
"typescript": "^5.6.2"
},
Expand Down
39 changes: 35 additions & 4 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
getDefaultEnvironment,
} from "@modelcontextprotocol/sdk/client/stdio.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
import express from "express";
import mcpProxy from "./mcpProxy.js";
import { findActualExecutable } from "spawn-rx";
Expand All @@ -24,34 +25,64 @@ const { values } = parseArgs({
options: {
env: { type: "string", default: "" },
args: { type: "string", default: "" },
envVars: {
type: "string",
multiple: true,
default: [],
short: "e"
},
},
});

// Parse environment variables from command line and set them in process.env
const envFromArgs = values.envVars.reduce((acc: Record<string, string>, curr: string) => {
const [key, value] = curr.split('=');
if (key && value) {
acc[key] = value;
// Set in process.env so the main process has access
process.env[key] = value;
}
return acc;
}, {});

const app = express();
app.use(cors());

let webAppTransports: SSEServerTransport[] = [];

const createTransport = async (query: express.Request["query"]) => {
/**
* Creates a transport based on query parameters and command line arguments.
* Environment variables can be provided in three ways:
* 1. Through process.env (base environment)
* 2. Through command line using --envVars KEY=VALUE (multiple allowed)
* 3. Through query parameters (takes precedence)
*/
const createTransport = async (query: express.Request["query"]): Promise<Transport> => {
console.log("Query parameters:", query);

const transportType = query.transportType as string;

if (transportType === "stdio") {
const command = query.command as string;
const origArgs = shellParseArgs(query.args as string) as string[];
const env = query.env ? JSON.parse(query.env as string) : undefined;
// Merge environment variables from query params and command line
const queryEnv = query.env ? JSON.parse(query.env as string) : {};
const mergedEnv = {
...process.env, // Include current process env
...envFromArgs, // Add our command line env vars
...queryEnv, // Query params take precedence
};

const { cmd, args } = findActualExecutable(command, origArgs);

console.log(
`Stdio transport: command=${cmd}, args=${args}, env=${JSON.stringify(env)}`,
`Stdio transport: command=${cmd}, args=${args}, env=${JSON.stringify(mergedEnv)}`,
);

const transport = new StdioClientTransport({
command: cmd,
args,
env,
env: mergedEnv,
stderr: "pipe",
});

Expand Down