docker_mcp 0.2.0 → 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,164 +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: 'array',
84
- items: { type: 'string' },
85
- description: 'Environment variables as KEY=VALUE (optional)'
86
- },
87
- stdin: {
88
- type: 'string',
89
- description: 'Input to send to the command via stdin (optional)'
90
- },
91
- timeout: {
92
- type: 'integer',
93
- description: 'Timeout in seconds (optional, default: 60)'
94
- }
95
- },
96
- required: %w[id cmd]
97
- )
98
-
99
- # Execute a command inside a running Docker container.
100
- #
101
- # This method provides comprehensive command execution capabilities within
102
- # Docker containers, including advanced features like custom user context,
103
- # environment variables, working directory, and stdin input.
104
- #
105
- # The command is parsed using shell-like syntax with support for quoted
106
- # arguments. Output is captured separately for stdout and stderr, and
107
- # the exit code is reported.
108
- #
109
- # @param id [String] container ID or name to execute command in
110
- # @param cmd [String] command to execute (shell-parsed into arguments)
111
- # @param server_context [Object] MCP server context (unused but required)
112
- # @param working_dir [String, nil] working directory for command execution
113
- # @param user [String, nil] user to run command as (username or UID)
114
- # @param env [Array<String>, nil] environment variables in KEY=VALUE format
115
- # @param stdin [String, nil] input to send to command via stdin
116
- # @param timeout [Integer] maximum execution time in seconds (default: 60)
117
- #
118
- # @return [MCP::Tool::Response] execution results including stdout, stderr, and exit code
119
- #
120
- # @raise [Docker::Error::NotFoundError] if container doesn't exist
121
- # @raise [Docker::Error::TimeoutError] if execution exceeds timeout
122
- # @raise [StandardError] for other execution failures
123
- #
124
- # @example Basic command execution
125
- # response = ExecContainer.call(
126
- # server_context: context,
127
- # id: "web-container",
128
- # cmd: "nginx -t"
129
- # )
130
- #
131
- # @example Advanced execution with environment
132
- # response = ExecContainer.call(
133
- # server_context: context,
134
- # id: "app-container",
135
- # cmd: "bundle exec rails console",
136
- # working_dir: "/app",
137
- # user: "rails",
138
- # env: ["RAILS_ENV=production"],
139
- # timeout: 300
140
- # )
141
- #
142
- # @see Docker::Container#exec
143
- def self.call(id:, cmd:, server_context:, working_dir: nil, user: nil,
144
- 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|
145
115
  container = Docker::Container.get(id)
146
116
 
147
117
  # Parse command string into array
148
- # Simple shell-like parsing: split on spaces but respect quoted strings
149
-
150
118
  cmd_array = Shellwords.split(cmd)
151
119
 
152
- # Build exec options
153
- exec_options = {
154
- 'Cmd' => cmd_array,
155
- 'AttachStdout' => true,
156
- 'AttachStderr' => true
157
- }
158
- exec_options['WorkingDir'] = working_dir if working_dir
159
- exec_options['User'] = user if user
160
- exec_options['Env'] = env if env
161
- exec_options['AttachStdin'] = true if stdin
120
+ # Parse environment variables from comma-separated string to array
121
+ env.split(',').map(&:strip) if env && !env.empty?
162
122
 
163
123
  # Execute the command
164
124
  stdout_data = []
@@ -177,10 +137,7 @@ module DockerMCP
177
137
  stderr_data = result[1]
178
138
  exit_code = result[2]
179
139
  rescue Docker::Error::TimeoutError
180
- return MCP::Tool::Response.new([{
181
- type: 'text',
182
- text: "Command execution timed out after #{timeout} seconds"
183
- }])
140
+ return "Command execution timed out after #{timeout} seconds"
184
141
  end
185
142
 
186
143
  # Format response
@@ -197,20 +154,13 @@ module DockerMCP
197
154
  response_text += "\nSTDERR:\n#{stderr_str}\n" unless stderr_str.strip.empty?
198
155
  end
199
156
 
200
- MCP::Tool::Response.new([{
201
- type: 'text',
202
- text: response_text.strip
203
- }])
157
+ response_text.strip
204
158
  rescue Docker::Error::NotFoundError
205
- MCP::Tool::Response.new([{
206
- type: 'text',
207
- text: "Container #{id} not found"
208
- }])
159
+ "Container #{id} not found"
209
160
  rescue StandardError => e
210
- MCP::Tool::Response.new([{
211
- type: 'text',
212
- text: "Error executing command: #{e.message}"
213
- }])
161
+ "Error executing command: #{e.message}"
214
162
  end
215
163
  end
164
+
165
+ ExecContainer = EXEC_CONTAINER_DEFINITION.to_mcp_tool
216
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