docker_mcp 0.2.5 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,167 +1,124 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DockerMCP
4
- # MCP tool for executing commands inside running Docker containers.
4
+ # MCP tool for executing commands inside Docker containers.
5
5
  #
6
- # This tool provides the ability to execute arbitrary commands inside running
7
- # Docker containers, with full control over execution environment including
8
- # working directory, user context, environment variables, and stdin input.
6
+ # This tool provides the ability to execute arbitrary commands inside
7
+ # running Docker containers. It supports interactive and non-interactive
8
+ # execution, environment variable injection, working directory specification,
9
+ # and user context switching within the container.
9
10
  #
10
- # == ⚠️ CRITICAL SECURITY WARNING ⚠️
11
+ # == Features
11
12
  #
12
- # This tool is EXTREMELY DANGEROUS as it allows arbitrary command execution
13
- # within Docker containers. This can be used to:
14
- # - Execute malicious code inside containers
15
- # - Access sensitive data within container filesystems
16
- # - Escalate privileges if container is poorly configured
17
- # - Perform lateral movement within containerized environments
18
- # - Exfiltrate data from applications
13
+ # - Execute arbitrary commands in running containers
14
+ # - Support for command arguments and shell parsing
15
+ # - Environment variable injection
16
+ # - Working directory specification
17
+ # - User context switching (run as specific user)
18
+ # - Standard input, output, and error handling
19
+ # - Configurable execution timeouts
19
20
  #
20
- # ONLY use this tool in trusted environments with proper security controls:
21
- # - Ensure containers run with minimal privileges
22
- # - Use read-only filesystems where possible
23
- # - Implement proper network segmentation
24
- # - Monitor and audit all command executions
25
- # - Never expose this tool to untrusted clients
21
+ # == Security Considerations
26
22
  #
27
- # == Features
23
+ # **CRITICAL WARNING**: This tool provides arbitrary command execution
24
+ # capabilities with significant security implications:
25
+ #
26
+ # - **Code Execution**: Can run any command available in the container
27
+ # - **File System Access**: Can read, write, and modify container files
28
+ # - **Network Access**: Can initiate network connections from container
29
+ # - **Process Manipulation**: Can start, stop, and signal processes
30
+ # - **Data Exposure**: Can access sensitive data within the container
31
+ # - **Privilege Escalation**: May exploit container or kernel vulnerabilities
32
+ # - **Resource Consumption**: Can consume container and host resources
33
+ #
34
+ # **Security Recommendations**:
35
+ # - Implement strict access controls and authentication
36
+ # - Use dedicated execution containers with minimal privileges
37
+ # - Monitor and log all command executions
38
+ # - Apply resource limits and timeouts
39
+ # - Validate and sanitize all command inputs
40
+ # - Consider using read-only file systems where possible
41
+ # - Implement network segmentation for container environments
28
42
  #
29
- # - Execute commands with custom working directory
30
- # - Run commands as specific users
31
- # - Set custom environment variables
32
- # - Provide stdin input to commands
33
- # - Configurable timeout protection
34
- # - Comprehensive error handling
35
- # - Separate stdout/stderr capture
43
+ # == Parameters
44
+ #
45
+ # - **id**: Container ID or name (required)
46
+ # - **cmd**: Command to execute (shell-parsed into arguments) (required)
47
+ # - **working_dir**: Working directory for command execution (optional)
48
+ # - **user**: User to run the command as (optional, e.g., "1000" or "username")
49
+ # - **env**: Environment variables as comma-separated KEY=VALUE pairs (optional)
50
+ # - **stdin**: Input to send to command via stdin (optional)
51
+ # - **timeout**: Timeout in seconds (optional, default: 60)
36
52
  #
37
53
  # == Example Usage
38
54
  #
39
- # # Simple command execution
40
- # ExecContainer.call(
55
+ # # Basic command execution
56
+ # response = ExecContainer.call(
41
57
  # server_context: context,
42
- # id: "my-container",
43
- # cmd: "ls -la /app"
58
+ # id: "web-container",
59
+ # cmd: "nginx -t"
44
60
  # )
45
61
  #
46
- # # Advanced execution with custom environment
47
- # ExecContainer.call(
62
+ # # Advanced execution with environment
63
+ # response = ExecContainer.call(
48
64
  # server_context: context,
49
- # id: "web-server",
50
- # cmd: "python manage.py migrate",
65
+ # id: "app-container",
66
+ # cmd: "bundle exec rails console",
51
67
  # working_dir: "/app",
52
- # user: "appuser",
53
- # env: "DJANGO_ENV=production,DEBUG=false",
54
- # timeout: 120
68
+ # user: "rails",
69
+ # env: "RAILS_ENV=production,DEBUG=true",
70
+ # timeout: 300
55
71
  # )
56
72
  #
57
73
  # @see Docker::Container#exec
58
74
  # @since 0.1.0
59
- class ExecContainer < MCP::Tool
75
+ EXEC_CONTAINER_DEFINITION = ToolForge.define(:exec_container) do
60
76
  description 'Execute a command inside a running Docker container. ' \
61
77
  'WARNING: This provides arbitrary command execution within the container. ' \
62
78
  'Ensure proper security measures are in place.'
63
79
 
64
- input_schema(
65
- properties: {
66
- id: {
67
- type: 'string',
80
+ param :id,
81
+ type: :string,
68
82
  description: 'Container ID or name'
69
- },
70
- cmd: {
71
- type: 'string',
83
+
84
+ param :cmd,
85
+ type: :string,
72
86
  description: 'Command to execute (e.g., "ls -la /app" or "python script.py")'
73
- },
74
- working_dir: {
75
- type: 'string',
76
- description: 'Working directory for the command (optional)'
77
- },
78
- user: {
79
- type: 'string',
80
- description: 'User to run the command as (optional, e.g., "1000" or "username")'
81
- },
82
- env: {
83
- type: 'string',
84
- description: 'Environment variables as comma-separated KEY=VALUE pairs (optional)'
85
- },
86
- stdin: {
87
- type: 'string',
88
- description: 'Input to send to the command via stdin (optional)'
89
- },
90
- timeout: {
91
- type: 'integer',
92
- description: 'Timeout in seconds (optional, default: 60)'
93
- }
94
- },
95
- required: %w[id cmd]
96
- )
97
-
98
- # Execute a command inside a running Docker container.
99
- #
100
- # This method provides comprehensive command execution capabilities within
101
- # Docker containers, including advanced features like custom user context,
102
- # environment variables, working directory, and stdin input.
103
- #
104
- # The command is parsed using shell-like syntax with support for quoted
105
- # arguments. Output is captured separately for stdout and stderr, and
106
- # the exit code is reported.
107
- #
108
- # @param id [String] container ID or name to execute command in
109
- # @param cmd [String] command to execute (shell-parsed into arguments)
110
- # @param server_context [Object] MCP server context (unused but required)
111
- # @param working_dir [String, nil] working directory for command execution
112
- # @param user [String, nil] user to run command as (username or UID)
113
- # @param env [String, nil] environment variables as comma-separated KEY=VALUE pairs
114
- # @param stdin [String, nil] input to send to command via stdin
115
- # @param timeout [Integer] maximum execution time in seconds (default: 60)
116
- #
117
- # @return [MCP::Tool::Response] execution results including stdout, stderr, and exit code
118
- #
119
- # @raise [Docker::Error::NotFoundError] if container doesn't exist
120
- # @raise [Docker::Error::TimeoutError] if execution exceeds timeout
121
- # @raise [StandardError] for other execution failures
122
- #
123
- # @example Basic command execution
124
- # response = ExecContainer.call(
125
- # server_context: context,
126
- # id: "web-container",
127
- # cmd: "nginx -t"
128
- # )
129
- #
130
- # @example Advanced execution with environment
131
- # response = ExecContainer.call(
132
- # server_context: context,
133
- # id: "app-container",
134
- # cmd: "bundle exec rails console",
135
- # working_dir: "/app",
136
- # user: "rails",
137
- # env: "RAILS_ENV=production,DEBUG=true",
138
- # timeout: 300
139
- # )
140
- #
141
- # @see Docker::Container#exec
142
- def self.call(id:, cmd:, server_context:, working_dir: nil, user: nil,
143
- env: nil, stdin: nil, timeout: 60)
87
+
88
+ param :working_dir,
89
+ type: :string,
90
+ description: 'Working directory for the command (optional)',
91
+ required: false
92
+
93
+ param :user,
94
+ type: :string,
95
+ description: 'User to run the command as (optional, e.g., "1000" or "username")',
96
+ required: false
97
+
98
+ param :env,
99
+ type: :string,
100
+ description: 'Environment variables as comma-separated KEY=VALUE pairs (optional)',
101
+ required: false
102
+
103
+ param :stdin,
104
+ type: :string,
105
+ description: 'Input to send to the command via stdin (optional)',
106
+ required: false
107
+
108
+ param :timeout,
109
+ type: :integer,
110
+ description: 'Timeout in seconds (optional, default: 60)',
111
+ required: false,
112
+ default: 60
113
+
114
+ execute do |id:, cmd:, working_dir: nil, user: nil, env: nil, stdin: nil, timeout: 60|
144
115
  container = Docker::Container.get(id)
145
116
 
146
117
  # Parse command string into array
147
- # Simple shell-like parsing: split on spaces but respect quoted strings
148
-
149
118
  cmd_array = Shellwords.split(cmd)
150
119
 
151
120
  # Parse environment variables from comma-separated string to array
152
- env_array = nil
153
- env_array = env.split(',').map(&:strip) if env && !env.empty?
154
-
155
- # Build exec options
156
- exec_options = {
157
- 'Cmd' => cmd_array,
158
- 'AttachStdout' => true,
159
- 'AttachStderr' => true
160
- }
161
- exec_options['WorkingDir'] = working_dir if working_dir
162
- exec_options['User'] = user if user
163
- exec_options['Env'] = env_array if env_array
164
- exec_options['AttachStdin'] = true if stdin
121
+ env.split(',').map(&:strip) if env && !env.empty?
165
122
 
166
123
  # Execute the command
167
124
  stdout_data = []
@@ -180,10 +137,7 @@ module DockerMCP
180
137
  stderr_data = result[1]
181
138
  exit_code = result[2]
182
139
  rescue Docker::Error::TimeoutError
183
- return MCP::Tool::Response.new([{
184
- type: 'text',
185
- text: "Command execution timed out after #{timeout} seconds"
186
- }])
140
+ return "Command execution timed out after #{timeout} seconds"
187
141
  end
188
142
 
189
143
  # Format response
@@ -200,20 +154,13 @@ module DockerMCP
200
154
  response_text += "\nSTDERR:\n#{stderr_str}\n" unless stderr_str.strip.empty?
201
155
  end
202
156
 
203
- MCP::Tool::Response.new([{
204
- type: 'text',
205
- text: response_text.strip
206
- }])
157
+ response_text.strip
207
158
  rescue Docker::Error::NotFoundError
208
- MCP::Tool::Response.new([{
209
- type: 'text',
210
- text: "Container #{id} not found"
211
- }])
159
+ "Container #{id} not found"
212
160
  rescue StandardError => e
213
- MCP::Tool::Response.new([{
214
- type: 'text',
215
- text: "Error executing command: #{e.message}"
216
- }])
161
+ "Error executing command: #{e.message}"
217
162
  end
218
163
  end
164
+
165
+ ExecContainer = EXEC_CONTAINER_DEFINITION.to_mcp_tool
219
166
  end
@@ -1,136 +1,92 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DockerMCP
4
- # MCP tool for retrieving Docker container logs.
4
+ # MCP tool for fetching Docker container logs.
5
5
  #
6
- # This tool provides access to container logs with flexible filtering and
7
- # formatting options. It can retrieve both stdout and stderr logs with
8
- # optional timestamps and tail functionality for recent entries.
6
+ # This tool retrieves log output from Docker containers, including both
7
+ # standard output and standard error streams. It supports filtering by
8
+ # stream type, limiting output length, timestamp inclusion, and retrieving
9
+ # logs from both running and stopped containers.
9
10
  #
10
11
  # == Features
11
12
  #
12
- # - Retrieve stdout and/or stderr logs
13
- # - Optional timestamp inclusion
14
- # - Tail functionality for recent logs
15
- # - Flexible log stream selection
16
- # - Comprehensive error handling
17
- # - Works with any container state
18
- #
19
- # == Log Sources
20
- #
21
- # Docker containers can generate logs from multiple sources:
22
- # - **stdout**: Standard output from container processes
23
- # - **stderr**: Standard error from container processes
24
- # - **timestamps**: Docker-generated timestamps for each log line
13
+ # - Fetch logs from running and stopped containers
14
+ # - Separate or combined stdout and stderr streams
15
+ # - Configurable output length limiting (tail functionality)
16
+ # - Optional timestamp inclusion for log entries
17
+ # - Support for container identification by ID or name
18
+ # - Comprehensive error handling and status reporting
25
19
  #
26
20
  # == Security Considerations
27
21
  #
28
22
  # Container logs may contain sensitive information:
29
- # - Application secrets and API keys
30
- # - User data and personal information
31
- # - Internal system information
32
- # - Database connection strings
33
- # - Error messages with stack traces
23
+ # - **Application Data**: Database queries, API keys, user data
24
+ # - **System Information**: Internal paths, configuration details
25
+ # - **Error Details**: Stack traces revealing application internals
26
+ # - **Access Patterns**: User behavior and system usage information
27
+ # - **Debugging Information**: Temporary credentials or session data
28
+ #
29
+ # Implement proper access controls and data sanitization for log access.
30
+ #
31
+ # == Parameters
34
32
  #
35
- # Security recommendations:
36
- # - Review log content before sharing
37
- # - Limit access to container logs
38
- # - Sanitize logs in production environments
39
- # - Use log rotation to manage log size
40
- # - Be cautious with log forwarding
33
+ # - **id**: Container ID or name (required)
34
+ # - **stdout**: Include stdout in logs (optional, default: true)
35
+ # - **stderr**: Include stderr in logs (optional, default: true)
36
+ # - **timestamps**: Show timestamps for log entries (optional, default: false)
37
+ # - **tail**: Number of lines to show from end of logs (optional, default: all)
41
38
  #
42
39
  # == Example Usage
43
40
  #
44
- # # Get all logs
45
- # FetchContainerLogs.call(
41
+ # # Fetch all logs
42
+ # response = FetchContainerLogs.call(
46
43
  # server_context: context,
47
44
  # id: "web-server"
48
45
  # )
49
46
  #
50
- # # Get recent logs with timestamps
51
- # FetchContainerLogs.call(
47
+ # # Fetch recent errors with timestamps
48
+ # response = FetchContainerLogs.call(
52
49
  # server_context: context,
53
50
  # id: "app-container",
54
- # tail: 100,
55
- # timestamps: true
56
- # )
57
- #
58
- # # Get only error logs
59
- # FetchContainerLogs.call(
60
- # server_context: context,
61
- # id: "database",
62
51
  # stdout: false,
63
- # stderr: true
52
+ # stderr: true,
53
+ # timestamps: true,
54
+ # tail: 100
64
55
  # )
65
56
  #
66
- # @see ExecContainer
67
57
  # @see Docker::Container#logs
68
58
  # @since 0.1.0
69
- class FetchContainerLogs < MCP::Tool
59
+ FETCH_CONTAINER_LOGS_DEFINITION = ToolForge.define(:fetch_container_logs) do
70
60
  description 'Fetch Docker container logs'
71
61
 
72
- input_schema(
73
- properties: {
74
- id: {
75
- type: 'string',
62
+ param :id,
63
+ type: :string,
76
64
  description: 'Container ID or name'
77
- },
78
- stdout: {
79
- type: 'boolean',
80
- description: 'Include stdout (default: true)'
81
- },
82
- stderr: {
83
- type: 'boolean',
84
- description: 'Include stderr (default: true)'
85
- },
86
- tail: {
87
- type: 'integer',
88
- description: 'Number of lines to show from the end of logs (default: all)'
89
- },
90
- timestamps: {
91
- type: 'boolean',
92
- description: 'Show timestamps (default: false)'
93
- }
94
- },
95
- required: ['id']
96
- )
97
65
 
98
- # Retrieve logs from a Docker container.
99
- #
100
- # This method fetches logs from the specified container with configurable
101
- # options for log sources (stdout/stderr), formatting (timestamps), and
102
- # quantity (tail). The logs are returned as a text response.
103
- #
104
- # @param id [String] container ID (full or short) or container name
105
- # @param server_context [Object] MCP server context (unused but required)
106
- # @param stdout [Boolean] whether to include stdout logs (default: true)
107
- # @param stderr [Boolean] whether to include stderr logs (default: true)
108
- # @param tail [Integer, nil] number of recent lines to return (nil for all)
109
- # @param timestamps [Boolean] whether to include timestamps (default: false)
110
- #
111
- # @return [MCP::Tool::Response] container logs as text
112
- #
113
- # @raise [Docker::Error::NotFoundError] if container doesn't exist
114
- # @raise [StandardError] for other log retrieval failures
115
- #
116
- # @example Get all logs
117
- # response = FetchContainerLogs.call(
118
- # server_context: context,
119
- # id: "nginx-server"
120
- # )
121
- #
122
- # @example Get recent error logs with timestamps
123
- # response = FetchContainerLogs.call(
124
- # server_context: context,
125
- # id: "app-container",
126
- # stdout: false,
127
- # stderr: true,
128
- # tail: 50,
129
- # timestamps: true
130
- # )
131
- #
132
- # @see Docker::Container#logs
133
- def self.call(id:, server_context:, stdout: true, stderr: true, tail: nil, timestamps: false)
66
+ param :stdout,
67
+ type: :boolean,
68
+ description: 'Include stdout (default: true)',
69
+ required: false,
70
+ default: true
71
+
72
+ param :stderr,
73
+ type: :boolean,
74
+ description: 'Include stderr (default: true)',
75
+ required: false,
76
+ default: true
77
+
78
+ param :tail,
79
+ type: :integer,
80
+ description: 'Number of lines to show from the end of logs (default: all)',
81
+ required: false
82
+
83
+ param :timestamps,
84
+ type: :boolean,
85
+ description: 'Show timestamps (default: false)',
86
+ required: false,
87
+ default: false
88
+
89
+ execute do |id:, stdout: true, stderr: true, tail: nil, timestamps: false|
134
90
  container = Docker::Container.get(id)
135
91
 
136
92
  options = {
@@ -140,22 +96,13 @@ module DockerMCP
140
96
  }
141
97
  options[:tail] = tail if tail
142
98
 
143
- logs = container.logs(options)
144
-
145
- MCP::Tool::Response.new([{
146
- type: 'text',
147
- text: logs
148
- }])
99
+ container.logs(options)
149
100
  rescue Docker::Error::NotFoundError
150
- MCP::Tool::Response.new([{
151
- type: 'text',
152
- text: "Container #{id} not found"
153
- }])
101
+ "Container #{id} not found"
154
102
  rescue StandardError => e
155
- MCP::Tool::Response.new([{
156
- type: 'text',
157
- text: "Error fetching logs: #{e.message}"
158
- }])
103
+ "Error fetching logs: #{e.message}"
159
104
  end
160
105
  end
106
+
107
+ FetchContainerLogs = FETCH_CONTAINER_LOGS_DEFINITION.to_mcp_tool
161
108
  end
@@ -3,64 +3,61 @@
3
3
  module DockerMCP
4
4
  # MCP tool for listing Docker containers.
5
5
  #
6
- # This tool provides functionality to list all Docker containers on the system,
7
- # including both running and stopped containers. It returns detailed information
8
- # about each container including names, images, status, ports, and other metadata.
6
+ # This tool provides comprehensive information about all Docker containers
7
+ # on the system, including both running and stopped containers. It returns
8
+ # detailed metadata for each container including names, images, status,
9
+ # network configuration, and resource usage.
9
10
  #
10
- # == Security Notes
11
+ # == Features
11
12
  #
12
- # This is a read-only operation that provides system information about containers.
13
- # While generally safe, it may reveal information about the Docker environment
14
- # that could be useful for reconnaissance.
13
+ # - Lists all containers (running and stopped)
14
+ # - Provides detailed container metadata
15
+ # - Shows network configuration and port mappings
16
+ # - Displays resource usage and statistics
17
+ # - Includes mount point information
18
+ # - Shows container labels and annotations
15
19
  #
16
- # == Example Usage
20
+ # == Security Considerations
21
+ #
22
+ # This tool provides system information that could be useful for:
23
+ # - **System Reconnaissance**: Reveals running services and configurations
24
+ # - **Network Discovery**: Shows internal network topology
25
+ # - **Resource Analysis**: Exposes system resource usage patterns
17
26
  #
18
- # # List all containers (default behavior)
19
- # ListContainers.call(server_context: context)
27
+ # Use with appropriate access controls in production environments.
20
28
  #
21
- # # Explicitly request all containers
22
- # ListContainers.call(server_context: context, all: true)
29
+ # == Return Format
30
+ #
31
+ # Returns an array of container objects with comprehensive metadata:
32
+ # - Container names and IDs
33
+ # - Image information and tags
34
+ # - Current state and status
35
+ # - Network settings and port bindings
36
+ # - Mount points and volumes
37
+ # - Labels and environment details
38
+ #
39
+ # == Example Usage
40
+ #
41
+ # containers = ListContainers.call(server_context: context)
42
+ # containers.each do |container|
43
+ # puts "#{container['Names'].first}: #{container['State']}"
44
+ # end
23
45
  #
24
46
  # @see Docker::Container.all
25
47
  # @since 0.1.0
26
- class ListContainers < MCP::Tool
48
+ LIST_CONTAINERS_DEFINITION = ToolForge.define(:list_containers) do
27
49
  description 'List Docker containers'
28
50
 
29
- input_schema(
30
- properties: {
31
- all: {
32
- type: 'boolean',
33
- description: 'Show all containers (default shows all containers including stopped ones)'
34
- }
35
- },
36
- required: []
37
- )
51
+ param :all,
52
+ type: :boolean,
53
+ description: 'Show all containers (default shows all containers including stopped ones)',
54
+ required: false,
55
+ default: true
38
56
 
39
- # List all Docker containers with detailed information.
40
- #
41
- # Retrieves information about all containers on the system, including:
42
- # - Container names and IDs
43
- # - Image information
44
- # - Current state (running, stopped, etc.)
45
- # - Port mappings
46
- # - Network configuration
47
- # - Volume mounts
48
- # - Creation and status timestamps
49
- #
50
- # @param server_context [Object] the MCP server context (unused but required)
51
- # @param all [Boolean] whether to show all containers (default: true)
52
- # @return [MCP::Tool::Response] response containing container information
53
- #
54
- # @example List all containers
55
- # response = ListContainers.call(server_context: context)
56
- # # Returns detailed info for all containers
57
- #
58
- # @see Docker::Container.all
59
- def self.call(server_context:, all: true)
60
- MCP::Tool::Response.new([{
61
- type: 'text',
62
- text: Docker::Container.all(all: all).map(&:info).to_s
63
- }])
57
+ execute do |all: true|
58
+ Docker::Container.all(all: all).map(&:info)
64
59
  end
65
60
  end
61
+
62
+ ListContainers = LIST_CONTAINERS_DEFINITION.to_mcp_tool
66
63
  end