Skip to content

Commit 87370a9

Browse files
committed
Allow forcing an MCP Server to be remote with an env var
Signed-off-by: David Gageot <david.gageot@docker.com>
1 parent 95897f9 commit 87370a9

3 files changed

Lines changed: 29 additions & 27 deletions

File tree

pkg/secrets/gather.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,12 @@ func GatherMissingEnvVars(ctx context.Context, cfg *latest.Config, env environme
2929
}
3030

3131
// Tools
32-
if mcpGatewayURL := os.Getenv(mcp.DOCKER_MCP_GATEWAY_URL_ENV); mcpGatewayURL == "" {
33-
names, err := GatherEnvVarsForTools(ctx, cfg)
34-
if err != nil {
35-
return nil, err
36-
}
37-
for _, e := range names {
38-
requiredEnv[e] = true
39-
}
32+
names, err := GatherEnvVarsForTools(ctx, cfg)
33+
if err != nil {
34+
return nil, err
35+
}
36+
for _, e := range names {
37+
requiredEnv[e] = true
4038
}
4139

4240
// Check for missing
@@ -82,6 +80,10 @@ func GatherEnvVarsForTools(ctx context.Context, cfg *latest.Config) ([]string, e
8280

8381
for _, ref := range config.GatherMCPServerReferences(cfg) {
8482
mcpServerName := gateway.ParseServerRef(ref)
83+
if mcpServerURL := os.Getenv(mcp.ENV_DOCKER_MCP_URL_PREFIX + mcpServerName); mcpServerURL != "" {
84+
// This MCP server is configured at runtime to be remote. We don't need to know its secrets.
85+
continue
86+
}
8587

8688
secrets, err := gateway.RequiredEnvVars(ctx, mcpServerName, gateway.DockerCatalogURL)
8789
if err != nil {

pkg/teamloader/teamloader.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"github.com/docker/cagent/pkg/config"
1414
latest "github.com/docker/cagent/pkg/config/v2"
1515
"github.com/docker/cagent/pkg/environment"
16+
"github.com/docker/cagent/pkg/gateway"
1617
"github.com/docker/cagent/pkg/memory"
1718
"github.com/docker/cagent/pkg/memory/database/sqlite"
1819
"github.com/docker/cagent/pkg/model/provider"
@@ -302,15 +303,16 @@ func getToolsForAgent(ctx context.Context, a *latest.AgentConfig, parentDir stri
302303
t = append(t, builtin.NewFilesystemTool([]string{wd}, opts...))
303304

304305
case toolset.Type == "mcp" && toolset.Ref != "":
305-
if mcpGatewayURL := os.Getenv(mcp.DOCKER_MCP_GATEWAY_URL_ENV); mcpGatewayURL != "" {
306-
// TODO(dga): we might connect multiple times to the same MCP Gateway and end up with duplicate toolsets.
307-
toolset, err := mcp.NewToolsetRemote(mcpGatewayURL, "streaming", nil, toolset.Tools, "")
306+
mcpServerName := gateway.ParseServerRef(toolset.Ref)
307+
if mcpServerURL := os.Getenv(mcp.ENV_DOCKER_MCP_URL_PREFIX + mcpServerName); mcpServerURL != "" {
308+
// This MCP server is configured at runtime to be remote. We connect to it directly over http.
309+
toolset, err := mcp.NewToolsetRemote(mcpServerURL, "streaming", nil, toolset.Tools, "")
308310
if err != nil {
309-
return nil, fmt.Errorf("connecting to remote MCP Gateway: %w", err)
311+
return nil, fmt.Errorf("connecting to remote MCP Server: %w", err)
310312
}
311313
t = append(t, toolset)
312314
} else {
313-
t = append(t, mcp.NewGatewayToolset(toolset.Ref, toolset.Config, toolset.Tools, envProvider))
315+
t = append(t, mcp.NewGatewayToolset(mcpServerName, toolset.Config, toolset.Tools, envProvider))
314316
}
315317

316318
case toolset.Type == "mcp" && toolset.Command != "":

pkg/tools/mcp/gateway.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ import (
1515
"gopkg.in/yaml.v3"
1616
)
1717

18-
const DOCKER_MCP_GATEWAY_URL_ENV = "DOCKER_MCP_GATEWAY_URL"
18+
const ENV_DOCKER_MCP_URL_PREFIX = "DOCKER_MCP_URL_"
1919

2020
type GatewayToolset struct {
21-
ref string
22-
config any
23-
toolFilter []string
24-
envProvider environment.Provider
21+
mcpServerName string
22+
config any
23+
toolFilter []string
24+
envProvider environment.Provider
2525

2626
once sync.Once
2727
initErr error
@@ -32,11 +32,11 @@ type GatewayToolset struct {
3232

3333
var _ tools.ToolSet = (*GatewayToolset)(nil)
3434

35-
func NewGatewayToolset(ref string, config any, toolFilter []string, envProvider environment.Provider) *GatewayToolset {
36-
slog.Debug("Creating MCP Gateway toolset", "ref", ref, "toolFilter", toolFilter)
35+
func NewGatewayToolset(mcpServerName string, config any, toolFilter []string, envProvider environment.Provider) *GatewayToolset {
36+
slog.Debug("Creating MCP Gateway toolset", "name", mcpServerName, "toolFilter", toolFilter)
3737

3838
return &GatewayToolset{
39-
ref: ref,
39+
mcpServerName: mcpServerName,
4040
config: config,
4141
toolFilter: toolFilter,
4242
envProvider: envProvider,
@@ -50,23 +50,21 @@ func (t *GatewayToolset) Instructions() string {
5050
}
5151

5252
func (t *GatewayToolset) configureOnce(ctx context.Context) error {
53-
mcpServerName := gateway.ParseServerRef(t.ref)
54-
5553
// Check which secrets (env vars) are required by the MCP server.
56-
secrets, err := gateway.RequiredEnvVars(ctx, mcpServerName, gateway.DockerCatalogURL)
54+
secrets, err := gateway.RequiredEnvVars(ctx, t.mcpServerName, gateway.DockerCatalogURL)
5755
if err != nil {
5856
return fmt.Errorf("reading which secrets the MCP server needs: %w", err)
5957
}
6058

6159
// Make sure all the required secrets are available in the environment.
6260
// TODO(dga): Ideally, the MCP gateway would use the same provider that we have.
63-
fileSecrets, err := writeSecretsToFile(ctx, mcpServerName, secrets, t.envProvider)
61+
fileSecrets, err := writeSecretsToFile(ctx, t.mcpServerName, secrets, t.envProvider)
6462
if err != nil {
6563
return fmt.Errorf("writing secrets to file: %w", err)
6664
}
6765
t.cleanUpSecrets = func() error { return os.Remove(fileSecrets) }
6866

69-
fileConfig, err := writeConfigToFile(ctx, mcpServerName, t.config)
67+
fileConfig, err := writeConfigToFile(ctx, t.mcpServerName, t.config)
7068
if err != nil {
7169
return fmt.Errorf("writing config to file: %w", err)
7270
}
@@ -76,7 +74,7 @@ func (t *GatewayToolset) configureOnce(ctx context.Context) error {
7674
// This improves shareability of agents.
7775
args := []string{
7876
"mcp", "gateway", "run",
79-
"--servers", mcpServerName,
77+
"--servers", t.mcpServerName,
8078
"--catalog", gateway.DockerCatalogURL,
8179
"--secrets", fileSecrets,
8280
"--config", fileConfig,

0 commit comments

Comments
 (0)