Skip to content

Commit 6c6d9cb

Browse files
committed
Added support for empty mcpServer type, normalized "http" type (Claude Code) to "streamable-http". Added support for custom headers in config from file (mcpServers).
1 parent ca579f0 commit 6c6d9cb

4 files changed

Lines changed: 73 additions & 26 deletions

File tree

cli/src/cli.ts

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ type ServerConfig =
4949
| {
5050
type: "sse" | "streamable-http";
5151
url: string;
52+
headers?: Record<string, string>;
5253
note?: string;
5354
};
5455

@@ -111,6 +112,11 @@ async function runWeb(args: Args): Promise<void> {
111112
startArgs.push("--server-url", args.serverUrl);
112113
}
113114

115+
// Pass headers if specified (for SSE/streamable-http)
116+
if (args.headers && Object.keys(args.headers).length > 0) {
117+
startArgs.push("--headers", JSON.stringify(args.headers));
118+
}
119+
114120
// Pass cwd if specified (for stdio transport)
115121
if (args.cwd) {
116122
startArgs.push("--cwd", path.resolve(args.cwd));
@@ -244,7 +250,13 @@ function loadConfigFile(configPath: string, serverName: string): ServerConfig {
244250
}
245251

246252
const serverConfig = parsedConfig.mcpServers[serverName];
247-
253+
if (serverConfig?.type === undefined) {
254+
// Normalize missing type to "stdio" (backwards compatibility)
255+
return { ...serverConfig, type: "stdio" };
256+
} else if (serverConfig.type === "http") {
257+
// Normalize "http" to "streamable-http" (some clients, like Claude Code, use http instead of streamable-http)
258+
return { ...serverConfig, type: "streamable-http" };
259+
}
248260
return serverConfig;
249261
} catch (err: unknown) {
250262
if (err instanceof SyntaxError) {
@@ -382,7 +394,6 @@ function parseArgs(): Args {
382394
// etc.)
383395
if (options.config && options.server) {
384396
const config = loadConfigFile(options.config, options.server);
385-
386397
if (config.type === "stdio") {
387398
const cwd = options.cwd ?? config.cwd ?? path.resolve(process.cwd());
388399
return {
@@ -396,6 +407,10 @@ function parseArgs(): Args {
396407
cwd: path.resolve(cwd),
397408
};
398409
} else if (config.type === "sse" || config.type === "streamable-http") {
410+
const headers = {
411+
...(config.headers || {}),
412+
...(options.header || {}),
413+
};
399414
return {
400415
command: config.url,
401416
args: finalArgs,
@@ -404,32 +419,10 @@ function parseArgs(): Args {
404419
dev: options.dev || false,
405420
transport: config.type,
406421
serverUrl: config.url,
407-
headers: options.header,
408-
};
409-
} else {
410-
// Backwards compatibility: if no type field, assume stdio
411-
const cwd =
412-
options.cwd ??
413-
(config as { cwd?: string }).cwd ??
414-
path.resolve(process.cwd());
415-
return {
416-
command: (config as { command?: string }).command || "",
417-
args: [
418-
...(((config as { args?: string[] }).args || []) as string[]),
419-
...finalArgs,
420-
],
421-
envArgs: {
422-
...(((config as { env?: Record<string, string> }).env ||
423-
{}) as Record<string, string>),
424-
...(options.e || {}),
425-
},
426-
cli: options.cli || false,
427-
dev: options.dev || false,
428-
transport: "stdio",
429-
headers: options.header,
430-
cwd: path.resolve(cwd),
422+
headers: Object.keys(headers).length > 0 ? headers : undefined,
431423
};
432424
}
425+
throw new Error(`Invalid server config: ${JSON.stringify(config)}`);
433426
}
434427

435428
// Otherwise use command line arguments

core/mcp/remote/node/server.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ function buildInitialConfigFromEnv(): {
186186
defaultArgs?: string[];
187187
defaultTransport?: string;
188188
defaultServerUrl?: string;
189+
defaultHeaders?: Record<string, string>;
189190
defaultCwd?: string;
190191
defaultEnvironment: Record<string, string>;
191192
} {
@@ -238,6 +239,20 @@ function buildInitialConfigFromEnv(): {
238239
...(process.env.MCP_INITIAL_SERVER_URL
239240
? { defaultServerUrl: process.env.MCP_INITIAL_SERVER_URL }
240241
: {}),
242+
...(process.env.MCP_INITIAL_HEADERS
243+
? (() => {
244+
try {
245+
const parsed = JSON.parse(
246+
process.env.MCP_INITIAL_HEADERS,
247+
) as Record<string, string>;
248+
return Object.keys(parsed).length > 0
249+
? { defaultHeaders: parsed }
250+
: {};
251+
} catch {
252+
return {};
253+
}
254+
})()
255+
: {}),
241256
...(process.env.MCP_INITIAL_CWD
242257
? { defaultCwd: process.env.MCP_INITIAL_CWD }
243258
: {}),

web/bin/start.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ async function startDevClient(clientOptions) {
2121
mcpServerArgs,
2222
transport,
2323
serverUrl,
24+
headers,
2425
envVars,
2526
cwd,
2627
abort,
@@ -43,6 +44,9 @@ async function startDevClient(clientOptions) {
4344
: {}),
4445
...(transport ? { MCP_INITIAL_TRANSPORT: transport } : {}),
4546
...(serverUrl ? { MCP_INITIAL_SERVER_URL: serverUrl } : {}),
47+
...(headers && Object.keys(headers).length > 0
48+
? { MCP_INITIAL_HEADERS: JSON.stringify(headers) }
49+
: {}),
4650
...(envVars && Object.keys(envVars).length > 0
4751
? { MCP_ENV_VARS: JSON.stringify(envVars) }
4852
: {}),
@@ -102,6 +106,7 @@ async function startProdClient(clientOptions) {
102106
mcpServerArgs,
103107
transport,
104108
serverUrl,
109+
headers,
105110
envVars,
106111
cwd,
107112
} = clientOptions;
@@ -123,6 +128,9 @@ async function startProdClient(clientOptions) {
123128
: {}),
124129
...(transport ? { MCP_INITIAL_TRANSPORT: transport } : {}),
125130
...(serverUrl ? { MCP_INITIAL_SERVER_URL: serverUrl } : {}),
131+
...(headers && Object.keys(headers).length > 0
132+
? { MCP_INITIAL_HEADERS: JSON.stringify(headers) }
133+
: {}),
126134
...(envVars && Object.keys(envVars).length > 0
127135
? { MCP_ENV_VARS: JSON.stringify(envVars) }
128136
: {}),
@@ -143,6 +151,7 @@ async function main() {
143151
let isDev = false;
144152
let transport = null;
145153
let serverUrl = null;
154+
let headers = null;
146155
let cwd = null;
147156

148157
for (let i = 0; i < args.length; i++) {
@@ -174,6 +183,15 @@ async function main() {
174183
continue;
175184
}
176185

186+
if (arg === "--headers" && i + 1 < args.length) {
187+
try {
188+
headers = JSON.parse(args[++i]);
189+
} catch {
190+
// Ignore invalid JSON
191+
}
192+
continue;
193+
}
194+
177195
if (arg === "--cwd" && i + 1 < args.length) {
178196
cwd = args[++i];
179197
continue;
@@ -210,6 +228,13 @@ async function main() {
210228
if (!transport && process.env.MCP_INITIAL_TRANSPORT) {
211229
transport = process.env.MCP_INITIAL_TRANSPORT;
212230
}
231+
if (!headers && process.env.MCP_INITIAL_HEADERS) {
232+
try {
233+
headers = JSON.parse(process.env.MCP_INITIAL_HEADERS);
234+
} catch {
235+
// Ignore invalid JSON
236+
}
237+
}
213238
if (!cwd && process.env.MCP_INITIAL_CWD) {
214239
cwd = process.env.MCP_INITIAL_CWD;
215240
}
@@ -254,6 +279,7 @@ async function main() {
254279
mcpServerArgs,
255280
transport,
256281
serverUrl,
282+
headers,
257283
envVars,
258284
cwd,
259285
abort,
@@ -274,6 +300,7 @@ async function main() {
274300
mcpServerArgs,
275301
transport,
276302
serverUrl,
303+
headers,
277304
envVars,
278305
cwd,
279306
abort,

web/src/App.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import ElicitationTab, {
9696
import {
9797
CustomHeaders,
9898
migrateFromLegacyAuth,
99+
recordToHeaders,
99100
} from "./lib/types/customHeaders";
100101
import MetadataTab from "./components/MetadataTab";
101102
import TokenLoginScreen from "./components/TokenLoginScreen";
@@ -333,6 +334,7 @@ const App = () => {
333334
setSseUrl,
334335
setSandboxUrl,
335336
setCwd,
337+
setCustomHeaders,
336338
});
337339
applyConfigRef.current = {
338340
setConfigFetchStatus,
@@ -345,6 +347,7 @@ const App = () => {
345347
setSseUrl,
346348
setSandboxUrl,
347349
setCwd,
350+
setCustomHeaders,
348351
};
349352

350353
// Helper to check if we can create InspectorClient (without actually creating it)
@@ -954,6 +957,15 @@ const App = () => {
954957
apply.setTransportType(transport || "stdio");
955958
apply.setSseUrl((data.defaultServerUrl as string) ?? "");
956959
apply.setCwd((data.defaultCwd as string) ?? "");
960+
if (
961+
data.defaultHeaders &&
962+
typeof data.defaultHeaders === "object" &&
963+
!Array.isArray(data.defaultHeaders)
964+
) {
965+
apply.setCustomHeaders(
966+
recordToHeaders(data.defaultHeaders as Record<string, string>),
967+
);
968+
}
957969
}
958970
apply.setSandboxUrl(
959971
typeof data.sandboxUrl === "string" ? data.sandboxUrl : undefined,

0 commit comments

Comments
 (0)