Skip to content
Merged
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
14 changes: 11 additions & 3 deletions core/mcp/clientmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -1283,10 +1283,18 @@ func (m *MCPManager) createSTDIOConnection(_ context.Context, config *schemas.MC

cmdString := fmt.Sprintf("%s %s", cmd, strings.Join(args, " "))

// Check if environment variables are set (envs are not plugin-mutable)
// Check referenced environment variables are set. Inline KEY=value
// assignments are passed directly to the stdio transport.
for _, env := range config.StdioConfig.Envs {
if os.Getenv(env) == "" {
return nil, nil, fmt.Errorf("environment variable %s is not set for MCP client %s", env, config.Name)
envName, _, hasInlineValue := strings.Cut(env, "=")
if envName == "" {
return nil, nil, fmt.Errorf("environment variable name is empty for MCP client %s", config.Name)
}
if hasInlineValue {
continue
}
if os.Getenv(envName) == "" {
return nil, nil, fmt.Errorf("environment variable %s is not set for MCP client %s", envName, config.Name)
}
}

Expand Down
75 changes: 75 additions & 0 deletions core/mcp/clientmanager_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package mcp

import (
"context"
"testing"

"github.com/maximhq/bifrost/core/schemas"
"github.com/stretchr/testify/require"
)

func TestCreateSTDIOConnectionAllowsInlineEnvAssignments(t *testing.T) {
t.Parallel()

config := &schemas.MCPClientConfig{
Name: "test-stdio-client",
ConnectionType: schemas.MCPConnectionTypeSTDIO,
StdioConfig: &schemas.MCPStdioConfig{
Command: "echo",
Envs: []string{"TEST_STDIO_ENV_ASSIGNMENT=inline-value"},
},
}

_, _, err := (&MCPManager{}).createSTDIOConnection(context.Background(), config, nil)
require.NoError(t, err)
}

func TestCreateSTDIOConnectionAllowsSetReferencedEnvVars(t *testing.T) {
t.Setenv("TEST_STDIO_ENV_REFERENCE_SET", "set-value")

config := &schemas.MCPClientConfig{
Name: "test-stdio-client",
ConnectionType: schemas.MCPConnectionTypeSTDIO,
StdioConfig: &schemas.MCPStdioConfig{
Command: "echo",
Envs: []string{"TEST_STDIO_ENV_REFERENCE_SET"},
},
}

_, _, err := (&MCPManager{}).createSTDIOConnection(context.Background(), config, nil)
require.NoError(t, err)
}

func TestCreateSTDIOConnectionRequiresReferencedEnvVars(t *testing.T) {
t.Setenv("TEST_STDIO_ENV_REFERENCE_MISSING", "")

config := &schemas.MCPClientConfig{
Name: "test-stdio-client",
ConnectionType: schemas.MCPConnectionTypeSTDIO,
StdioConfig: &schemas.MCPStdioConfig{
Command: "echo",
Envs: []string{"TEST_STDIO_ENV_REFERENCE_MISSING"},
},
}

_, _, err := (&MCPManager{}).createSTDIOConnection(context.Background(), config, nil)
require.Error(t, err)
require.Contains(t, err.Error(), "environment variable TEST_STDIO_ENV_REFERENCE_MISSING is not set")
}
Comment thread
greptile-apps[bot] marked this conversation as resolved.

func TestCreateSTDIOConnectionRejectsEmptyEnvAssignmentName(t *testing.T) {
t.Parallel()

config := &schemas.MCPClientConfig{
Name: "test-stdio-client",
ConnectionType: schemas.MCPConnectionTypeSTDIO,
StdioConfig: &schemas.MCPStdioConfig{
Command: "echo",
Envs: []string{"=inline-value"},
},
}

_, _, err := (&MCPManager{}).createSTDIOConnection(context.Background(), config, nil)
require.Error(t, err)
require.Contains(t, err.Error(), "environment variable name is empty")
}