@@ -7,213 +7,186 @@ import { spawnPromise } from "spawn-rx";
7
7
import { fileURLToPath } from "url" ;
8
8
const __dirname = dirname ( fileURLToPath ( import . meta. url ) ) ;
9
9
function handleError ( error ) {
10
- let message ;
11
- if ( error instanceof Error ) {
12
- message = error . message ;
13
- } else if ( typeof error === "string" ) {
14
- message = error ;
15
- } else {
16
- message = "Unknown error" ;
17
- }
18
- console . error ( message ) ;
19
- process . exit ( 1 ) ;
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 ) ;
20
22
}
21
23
function delay ( ms ) {
22
- return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
24
+ return new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
23
25
}
24
26
async function runWebClient ( args ) {
25
- const inspectorServerPath = resolve (
26
- __dirname ,
27
- ".." ,
28
- "server" ,
29
- "build" ,
30
- "index.js" ,
31
- ) ;
32
- // Path to the client entry point
33
- const inspectorClientPath = resolve (
34
- __dirname ,
35
- ".." ,
36
- "client" ,
37
- "bin" ,
38
- "cli.js" ,
39
- ) ;
40
- const CLIENT_PORT = process . env . CLIENT_PORT ?? "5173" ;
41
- const SERVER_PORT = process . env . SERVER_PORT ?? "3000" ;
42
- console . log ( "Starting MCP inspector..." ) ;
43
- const abort = new AbortController ( ) ;
44
- let cancelled = false ;
45
- process . on ( "SIGINT" , ( ) => {
46
- cancelled = true ;
47
- abort . abort ( ) ;
48
- } ) ;
49
- const server = spawnPromise (
50
- "node" ,
51
- [
52
- inspectorServerPath ,
53
- ...( args . command ? [ `--env` , args . command ] : [ ] ) ,
54
- ...( args . args ? [ `--args=${ args . args . join ( " " ) } ` ] : [ ] ) ,
55
- ] ,
56
- {
57
- env : {
58
- ...process . env ,
59
- PORT : SERVER_PORT ,
60
- MCP_ENV_VARS : JSON . stringify ( args . envArgs ) ,
61
- } ,
62
- signal : abort . signal ,
63
- echoOutput : true ,
64
- } ,
65
- ) ;
66
- const client = spawnPromise ( "node" , [ inspectorClientPath ] , {
67
- env : { ...process . env , PORT : CLIENT_PORT } ,
68
- signal : abort . signal ,
69
- echoOutput : true ,
70
- } ) ;
71
- // Make sure our server/client didn't immediately fail
72
- await Promise . any ( [ server , client , delay ( 2 * 1000 ) ] ) ;
73
- const portParam = SERVER_PORT === "3000" ? "" : `?proxyPort=${ SERVER_PORT } ` ;
74
- console . log (
75
- `\n🔍 MCP Inspector is up and running at http://localhost:${ CLIENT_PORT } ${ portParam } 🚀` ,
76
- ) ;
77
- try {
78
- await Promise . any ( [ server , client ] ) ;
79
- } catch ( e ) {
80
- if ( ! cancelled || process . env . DEBUG ) {
81
- throw e ;
27
+ const inspectorServerPath = resolve ( __dirname , ".." , "server" , "build" , "index.js" ) ;
28
+ // Path to the client entry point
29
+ const inspectorClientPath = resolve ( __dirname , ".." , "client" , "bin" , "cli.js" ) ;
30
+ const CLIENT_PORT = process . env . CLIENT_PORT ?? "5173" ;
31
+ const SERVER_PORT = process . env . SERVER_PORT ?? "3000" ;
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
+ const server = spawnPromise ( "node" , [
40
+ inspectorServerPath ,
41
+ ...( args . command ? [ `--env` , args . command ] : [ ] ) ,
42
+ ...( args . args ? [ `--args=${ args . args . join ( " " ) } ` ] : [ ] ) ,
43
+ ] , {
44
+ env : {
45
+ ...process . env ,
46
+ PORT : SERVER_PORT ,
47
+ MCP_ENV_VARS : JSON . stringify ( args . envArgs ) ,
48
+ } ,
49
+ signal : abort . signal ,
50
+ echoOutput : true ,
51
+ } ) ;
52
+ const client = spawnPromise ( "node" , [ inspectorClientPath ] , {
53
+ env : { ...process . env , PORT : CLIENT_PORT } ,
54
+ signal : abort . signal ,
55
+ echoOutput : true ,
56
+ } ) ;
57
+ // Make sure our server/client didn't immediately fail
58
+ await Promise . any ( [ server , client , delay ( 2 * 1000 ) ] ) ;
59
+ const portParam = SERVER_PORT === "3000" ? "" : `?proxyPort=${ SERVER_PORT } ` ;
60
+ console . log ( `\n🔍 MCP Inspector is up and running at http://localhost:${ CLIENT_PORT } ${ portParam } 🚀` ) ;
61
+ try {
62
+ await Promise . any ( [ server , client ] ) ;
63
+ }
64
+ catch ( e ) {
65
+ if ( ! cancelled || process . env . DEBUG ) {
66
+ throw e ;
67
+ }
82
68
}
83
- }
84
69
}
85
70
async function runCli ( args ) {
86
- const projectRoot = resolve ( __dirname , ".." ) ;
87
- const cliPath = resolve ( projectRoot , "cli" , "build" , "index.js" ) ;
88
- const abort = new AbortController ( ) ;
89
- let cancelled = false ;
90
- process . on ( "SIGINT" , ( ) => {
91
- cancelled = true ;
92
- abort . abort ( ) ;
93
- } ) ;
94
- try {
95
- await spawnPromise ( "node" , [ cliPath , args . command , ...args . args ] , {
96
- env : { ...process . env , ...args . envArgs } ,
97
- signal : abort . signal ,
98
- echoOutput : true ,
71
+ const projectRoot = resolve ( __dirname , ".." ) ;
72
+ const cliPath = resolve ( projectRoot , "cli" , "build" , "index.js" ) ;
73
+ const abort = new AbortController ( ) ;
74
+ let cancelled = false ;
75
+ process . on ( "SIGINT" , ( ) => {
76
+ cancelled = true ;
77
+ abort . abort ( ) ;
99
78
} ) ;
100
- } catch ( e ) {
101
- if ( ! cancelled || process . env . DEBUG ) {
102
- throw e ;
79
+ try {
80
+ await spawnPromise ( "node" , [ cliPath , args . command , ...args . args ] , {
81
+ env : { ...process . env , ...args . envArgs } ,
82
+ signal : abort . signal ,
83
+ echoOutput : true ,
84
+ } ) ;
85
+ }
86
+ catch ( e ) {
87
+ if ( ! cancelled || process . env . DEBUG ) {
88
+ throw e ;
89
+ }
103
90
}
104
- }
105
91
}
106
92
function loadConfigFile ( configPath , serverName ) {
107
- try {
108
- const resolvedConfigPath = path . isAbsolute ( configPath )
109
- ? configPath
110
- : path . resolve ( process . cwd ( ) , configPath ) ;
111
- if ( ! fs . existsSync ( resolvedConfigPath ) ) {
112
- throw new Error ( `Config file not found: ${ resolvedConfigPath } ` ) ;
93
+ try {
94
+ const resolvedConfigPath = path . isAbsolute ( configPath )
95
+ ? configPath
96
+ : path . resolve ( process . cwd ( ) , configPath ) ;
97
+ if ( ! fs . existsSync ( resolvedConfigPath ) ) {
98
+ throw new Error ( `Config file not found: ${ resolvedConfigPath } ` ) ;
99
+ }
100
+ const configContent = fs . readFileSync ( resolvedConfigPath , "utf8" ) ;
101
+ const parsedConfig = JSON . parse ( configContent ) ;
102
+ if ( ! parsedConfig . mcpServers || ! parsedConfig . mcpServers [ serverName ] ) {
103
+ const availableServers = Object . keys ( parsedConfig . mcpServers || { } ) . join ( ", " ) ;
104
+ throw new Error ( `Server '${ serverName } ' not found in config file. Available servers: ${ availableServers } ` ) ;
105
+ }
106
+ const serverConfig = parsedConfig . mcpServers [ serverName ] ;
107
+ return serverConfig ;
113
108
}
114
- const configContent = fs . readFileSync ( resolvedConfigPath , "utf8" ) ;
115
- const parsedConfig = JSON . parse ( configContent ) ;
116
- if ( ! parsedConfig . mcpServers || ! parsedConfig . mcpServers [ serverName ] ) {
117
- const availableServers = Object . keys ( parsedConfig . mcpServers || { } ) . join (
118
- ", " ,
119
- ) ;
120
- throw new Error (
121
- `Server '${ serverName } ' not found in config file. Available servers: ${ availableServers } ` ,
122
- ) ;
109
+ catch ( err ) {
110
+ if ( err instanceof SyntaxError ) {
111
+ throw new Error ( `Invalid JSON in config file: ${ err . message } ` ) ;
112
+ }
113
+ throw err ;
123
114
}
124
- const serverConfig = parsedConfig . mcpServers [ serverName ] ;
125
- return serverConfig ;
126
- } catch ( err ) {
127
- if ( err instanceof SyntaxError ) {
128
- throw new Error ( `Invalid JSON in config file: ${ err . message } ` ) ;
129
- }
130
- throw err ;
131
- }
132
115
}
133
116
function parseKeyValuePair ( value , previous = { } ) {
134
- const parts = value . split ( "=" ) ;
135
- const key = parts [ 0 ] ;
136
- const val = parts . slice ( 1 ) . join ( "=" ) ;
137
- if ( val === undefined || val === "" ) {
138
- throw new Error (
139
- `Invalid parameter format: ${ value } . Use key=value format.` ,
140
- ) ;
141
- }
142
- return { ...previous , [ key ] : val } ;
117
+ const parts = value . split ( "=" ) ;
118
+ const key = parts [ 0 ] ;
119
+ const val = parts . slice ( 1 ) . join ( "=" ) ;
120
+ if ( val === undefined || val === "" ) {
121
+ throw new Error ( `Invalid parameter format: ${ value } . Use key=value format.` ) ;
122
+ }
123
+ return { ...previous , [ key ] : val } ;
143
124
}
144
125
function parseArgs ( ) {
145
- const program = new Command ( ) ;
146
- const argSeparatorIndex = process . argv . indexOf ( "--" ) ;
147
- let preArgs = process . argv ;
148
- let postArgs = [ ] ;
149
- if ( argSeparatorIndex !== - 1 ) {
150
- preArgs = process . argv . slice ( 0 , argSeparatorIndex ) ;
151
- postArgs = process . argv . slice ( argSeparatorIndex + 1 ) ;
152
- }
153
- program
154
- . name ( "inspector-bin" )
155
- . allowExcessArguments ( )
156
- . allowUnknownOption ( )
157
- . option (
158
- "-e <env>" ,
159
- "environment variables in KEY=VALUE format" ,
160
- parseKeyValuePair ,
161
- { } ,
162
- )
163
- . option ( "--config <path>" , "config file path" )
164
- . option ( "--server <n>" , "server name from config file" )
165
- . option ( "--cli" , "enable CLI mode" ) ;
166
- // Parse only the arguments before --
167
- program . parse ( preArgs ) ;
168
- const options = program . opts ( ) ;
169
- const remainingArgs = program . args ;
170
- // Add back any arguments that came after --
171
- const finalArgs = [ ...remainingArgs , ...postArgs ] ;
172
- // Validate that config and server are provided together
173
- if (
174
- ( options . config && ! options . server ) ||
175
- ( ! options . config && options . server )
176
- ) {
177
- throw new Error (
178
- "Both --config and --server must be provided together. If you specify one, you must specify the other." ,
179
- ) ;
180
- }
181
- // If config file is specified, load and use the options from the file. We must merge the args
182
- // from the command line and the file together, or we will miss the method options (--method,
183
- // etc.)
184
- if ( options . config && options . server ) {
185
- const config = loadConfigFile ( options . config , options . server ) ;
126
+ const program = new Command ( ) ;
127
+ const argSeparatorIndex = process . argv . indexOf ( "--" ) ;
128
+ let preArgs = process . argv ;
129
+ let postArgs = [ ] ;
130
+ if ( argSeparatorIndex !== - 1 ) {
131
+ preArgs = process . argv . slice ( 0 , argSeparatorIndex ) ;
132
+ postArgs = process . argv . slice ( argSeparatorIndex + 1 ) ;
133
+ }
134
+ program
135
+ . name ( "inspector-bin" )
136
+ . allowExcessArguments ( )
137
+ . allowUnknownOption ( )
138
+ . option ( "-e <env>" , "environment variables in KEY=VALUE format" , parseKeyValuePair , { } )
139
+ . option ( "--config <path>" , "config file path" )
140
+ . option ( "--server <n>" , "server name from config file" )
141
+ . option ( "--cli" , "enable CLI mode" ) ;
142
+ // Parse only the arguments before --
143
+ program . parse ( preArgs ) ;
144
+ const options = program . opts ( ) ;
145
+ const remainingArgs = program . args ;
146
+ // Add back any arguments that came after --
147
+ const finalArgs = [ ...remainingArgs , ...postArgs ] ;
148
+ // Validate that config and server are provided together
149
+ if ( ( options . config && ! options . server ) ||
150
+ ( ! options . config && options . server ) ) {
151
+ throw new Error ( "Both --config and --server must be provided together. If you specify one, you must specify the other." ) ;
152
+ }
153
+ // If config file is specified, load and use the options from the file. We must merge the args
154
+ // from the command line and the file together, or we will miss the method options (--method,
155
+ // etc.)
156
+ if ( options . config && options . server ) {
157
+ const config = loadConfigFile ( options . config , options . server ) ;
158
+ return {
159
+ command : config . command ,
160
+ args : [ ...( config . args || [ ] ) , ...finalArgs ] ,
161
+ envArgs : { ...( config . env || { } ) , ...( options . e || { } ) } ,
162
+ cli : options . cli || false ,
163
+ } ;
164
+ }
165
+ // Otherwise use command line arguments
166
+ const command = finalArgs [ 0 ] || "" ;
167
+ const args = finalArgs . slice ( 1 ) ;
186
168
return {
187
- command : config . command ,
188
- args : [ ... ( config . args || [ ] ) , ... finalArgs ] ,
189
- envArgs : { ... ( config . env || { } ) , ... ( options . e || { } ) } ,
190
- cli : options . cli || false ,
169
+ command,
170
+ args ,
171
+ envArgs : options . e || { } ,
172
+ cli : options . cli || false ,
191
173
} ;
192
- }
193
- // Otherwise use command line arguments
194
- const command = finalArgs [ 0 ] || "" ;
195
- const args = finalArgs . slice ( 1 ) ;
196
- return {
197
- command,
198
- args,
199
- envArgs : options . e || { } ,
200
- cli : options . cli || false ,
201
- } ;
202
174
}
203
175
async function main ( ) {
204
- process . on ( "uncaughtException" , ( error ) => {
205
- handleError ( error ) ;
206
- } ) ;
207
- try {
208
- const args = parseArgs ( ) ;
209
- console . log ( args ) ;
210
- if ( args . cli ) {
211
- runCli ( args ) ;
212
- } else {
213
- await runWebClient ( args ) ;
176
+ process . on ( "uncaughtException" , ( error ) => {
177
+ handleError ( error ) ;
178
+ } ) ;
179
+ try {
180
+ const args = parseArgs ( ) ;
181
+ if ( args . cli ) {
182
+ runCli ( args ) ;
183
+ }
184
+ else {
185
+ await runWebClient ( args ) ;
186
+ }
187
+ }
188
+ catch ( error ) {
189
+ handleError ( error ) ;
214
190
}
215
- } catch ( error ) {
216
- handleError ( error ) ;
217
- }
218
191
}
219
192
main ( ) ;
0 commit comments