Skip to content

Commit dde71d2

Browse files
NamesMTdaniel-lxs
andauthored
feat(McpHub): inject env vars on whole mcp config (#3970)
* types(utils/config): improve return type infer * feat(McpHub): inject env variable on whole mcp config * fix: check for undefined configInjected * refactor: improve type assertion --------- Co-authored-by: Daniel <[email protected]>
1 parent 1365800 commit dde71d2

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

src/services/mcp/McpHub.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,16 @@ export class McpHub {
443443

444444
let transport: StdioClientTransport | SSEClientTransport
445445

446-
if (config.type === "stdio") {
446+
// Inject environment variables to the config
447+
const configInjected = (await injectEnv(config)) as typeof config
448+
449+
if (configInjected.type === "stdio") {
447450
transport = new StdioClientTransport({
448-
command: config.command,
449-
args: config.args,
450-
cwd: config.cwd,
451+
command: configInjected.command,
452+
args: configInjected.args,
453+
cwd: configInjected.cwd,
451454
env: {
452-
...(config.env ? await injectEnv(config.env) : {}),
455+
...(configInjected.env || {}),
453456
...(process.env.PATH ? { PATH: process.env.PATH } : {}),
454457
...(process.env.HOME ? { HOME: process.env.HOME } : {}),
455458
},
@@ -508,16 +511,16 @@ export class McpHub {
508511
// SSE connection
509512
const sseOptions = {
510513
requestInit: {
511-
headers: config.headers,
514+
headers: configInjected.headers,
512515
},
513516
}
514517
// Configure ReconnectingEventSource options
515518
const reconnectingEventSourceOptions = {
516519
max_retry_time: 5000, // Maximum retry time in milliseconds
517-
withCredentials: config.headers?.["Authorization"] ? true : false, // Enable credentials if Authorization header exists
520+
withCredentials: configInjected.headers?.["Authorization"] ? true : false, // Enable credentials if Authorization header exists
518521
}
519522
global.EventSource = ReconnectingEventSource
520-
transport = new SSEClientTransport(new URL(config.url), {
523+
transport = new SSEClientTransport(new URL(configInjected.url), {
521524
...sseOptions,
522525
eventSourceInit: reconnectingEventSourceOptions,
523526
})
@@ -537,9 +540,9 @@ export class McpHub {
537540
const connection: McpConnection = {
538541
server: {
539542
name,
540-
config: JSON.stringify(config),
543+
config: JSON.stringify(configInjected),
541544
status: "connecting",
542-
disabled: config.disabled,
545+
disabled: configInjected.disabled,
543546
source,
544547
projectPath: source === "project" ? vscode.workspace.workspaceFolders?.[0]?.uri.fsPath : undefined,
545548
errorHistory: [],

src/utils/config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
*
66
* Does not mutate original object
77
*/
8-
export async function injectEnv(config: string | Record<PropertyKey, any>, notFoundValue: any = "") {
8+
export async function injectEnv<C extends string | Record<PropertyKey, any>>(config: C, notFoundValue: any = "") {
99
// Use simple regex replace for now, will see if object traversal and recursion is needed here (e.g: for non-serializable objects)
1010

1111
const isObject = typeof config === "object"
12-
let _config = isObject ? JSON.stringify(config) : config
12+
let _config: string = isObject ? JSON.stringify(config) : config
1313

1414
_config = _config.replace(/\$\{env:([\w]+)\}/g, (_, name) => {
1515
// Check if null or undefined
@@ -21,5 +21,5 @@ export async function injectEnv(config: string | Record<PropertyKey, any>, notFo
2121
return process.env[name] ?? notFoundValue
2222
})
2323

24-
return isObject ? JSON.parse(_config) : _config
24+
return (isObject ? JSON.parse(_config) : _config) as C extends string ? string : C
2525
}

0 commit comments

Comments
 (0)