1package config
2
3import (
4 "context"
5 "fmt"
6 "os/exec"
7 "time"
8)
9
10var dockerMCPVersionRunner = func(ctx context.Context) error {
11 cmd := exec.CommandContext(ctx, "docker", "mcp", "version")
12 return cmd.Run()
13}
14
15// DockerMCPName is the name of the Docker MCP configuration.
16const DockerMCPName = "docker"
17
18// IsDockerMCPAvailable checks if Docker MCP is available by running
19// 'docker mcp version'.
20func IsDockerMCPAvailable() bool {
21 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
22 defer cancel()
23
24 err := dockerMCPVersionRunner(ctx)
25 return err == nil
26}
27
28// IsDockerMCPEnabled checks if Docker MCP is already configured.
29func (c *Config) IsDockerMCPEnabled() bool {
30 if c.MCP == nil {
31 return false
32 }
33 _, exists := c.MCP[DockerMCPName]
34 return exists
35}
36
37func DockerMCPConfig() MCPConfig {
38 return MCPConfig{
39 Type: MCPStdio,
40 Command: "docker",
41 Args: []string{"mcp", "gateway", "run"},
42 Disabled: false,
43 }
44}
45
46func (s *ConfigStore) PrepareDockerMCPConfig() (MCPConfig, error) {
47 if !IsDockerMCPAvailable() {
48 return MCPConfig{}, fmt.Errorf("docker mcp is not available, please ensure docker is installed and 'docker mcp version' succeeds")
49 }
50
51 mcpConfig := DockerMCPConfig()
52 if s.config.MCP == nil {
53 s.config.MCP = make(map[string]MCPConfig)
54 }
55 s.config.MCP[DockerMCPName] = mcpConfig
56 return mcpConfig, nil
57}
58
59func (s *ConfigStore) PersistDockerMCPConfig(mcpConfig MCPConfig) error {
60 if err := s.SetConfigField(ScopeGlobal, "mcp."+DockerMCPName, mcpConfig); err != nil {
61 return fmt.Errorf("failed to persist docker mcp configuration: %w", err)
62 }
63 return nil
64}
65
66// EnableDockerMCP adds Docker MCP configuration and persists it.
67func (s *ConfigStore) EnableDockerMCP() error {
68 mcpConfig, err := s.PrepareDockerMCPConfig()
69 if err != nil {
70 return err
71 }
72 if err := s.PersistDockerMCPConfig(mcpConfig); err != nil {
73 return err
74 }
75 return nil
76}
77
78// DisableDockerMCP removes Docker MCP configuration and persists the change.
79func (s *ConfigStore) DisableDockerMCP() error {
80 if s.config.MCP == nil {
81 return nil
82 }
83
84 // Remove from in-memory config.
85 delete(s.config.MCP, DockerMCPName)
86
87 // Persist the updated MCP map to the config file.
88 if err := s.SetConfigField(ScopeGlobal, "mcp", s.config.MCP); err != nil {
89 return fmt.Errorf("failed to persist docker mcp removal: %w", err)
90 }
91
92 return nil
93}