@@ -149,7 +149,8 @@ func getOrRenewClient(ctx context.Context, name string) (*client.Client, error)
149 return nil, fmt.Errorf("mcp '%s' not available", name)
149 return nil, fmt.Errorf("mcp '%s' not available", name)
152− m := config.Get().MCP[name]
152+ cfg := config.Get()
153 state, _ := mcpStates.Get(name)
154 state, _ := mcpStates.Get(name)
155 timeout := mcpTimeout(m)
156 timeout := mcpTimeout(m)
@@ -161,7 +162,7 @@ func getOrRenewClient(ctx context.Context, name string) (*client.Client, error)
162 updateMCPState(name, MCPStateError, maybeTimeoutErr(err, timeout), nil, state.ToolCount)
163 updateMCPState(name, MCPStateError, maybeTimeoutErr(err, timeout), nil, state.ToolCount)
164− c, err = createAndInitializeClient(ctx, name, m)
165+ c, err = createAndInitializeClient(ctx, name, m, cfg.Resolver())
165 if err != nil {
166 if err != nil {
166 return nil, err
167 return nil, err
@@ -313,7 +314,7 @@ func doGetMCPTools(ctx context.Context, permissions permission.Service, cfg *con
314 ctx, cancel := context.WithTimeout(ctx, mcpTimeout(m))
315 ctx, cancel := context.WithTimeout(ctx, mcpTimeout(m))
315 defer cancel()
316 defer cancel()
316− c, err := createAndInitializeClient(ctx, name, m)
317+ c, err := createAndInitializeClient(ctx, name, m, cfg.Resolver())
317 if err != nil {
318 if err != nil {
@@ -328,8 +329,8 @@ func doGetMCPTools(ctx context.Context, permissions permission.Service, cfg *con
328 return slices.Collect(result.Seq())
329 return slices.Collect(result.Seq())
331−func createAndInitializeClient(ctx context.Context, name string, m config.MCPConfig) (*client.Client, error) {
332+func createAndInitializeClient(ctx context.Context, name string, m config.MCPConfig, resolver config.VariableResolver) (*client.Client, error) {
332− c, err := createMcpClient(name, m)
333+ c, err := createMcpClient(name, m, resolver)
333 if err != nil {
334 if err != nil {
334 updateMCPState(name, MCPStateError, err, nil, 0)
335 updateMCPState(name, MCPStateError, err, nil, 0)
335 slog.Error("error creating mcp client", "error", err, "name", name)
336 slog.Error("error creating mcp client", "error", err, "name", name)
@@ -367,14 +368,18 @@ func maybeTimeoutErr(err error, timeout time.Duration) error {
367 return err
368 return err
370−func createMcpClient(name string, m config.MCPConfig) (*client.Client, error) {
371+func createMcpClient(name string, m config.MCPConfig, resolver config.VariableResolver) (*client.Client, error) {
371 switch m.Type {
372 switch m.Type {
372 case config.MCPStdio:
373 case config.MCPStdio:
373− if strings.TrimSpace(m.Command) == "" {
374+ command, err := resolver.ResolveValue(m.Command)
376+ return nil, fmt.Errorf("invalid mcp command: %w", err)
378+ if strings.TrimSpace(command) == "" {
374 return nil, fmt.Errorf("mcp stdio config requires a non-empty 'command' field")
379 return nil, fmt.Errorf("mcp stdio config requires a non-empty 'command' field")
376 return client.NewStdioMCPClientWithOptions(
381 return client.NewStdioMCPClientWithOptions(
377− home.Long(m.Command),
382+ home.Long(command),
378 m.ResolvedEnv(),
383 m.ResolvedEnv(),
380 transport.WithCommandLogger(mcpLogger{name: name}),
385 transport.WithCommandLogger(mcpLogger{name: name}),