ruby_llm-docker 0.0.1 → 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.
@@ -0,0 +1,168 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for executing commands inside Docker containers.
6
+ #
7
+ # This tool provides the ability to execute arbitrary commands inside
8
+ # running Docker containers. It supports interactive and non-interactive
9
+ # execution, environment variable injection, working directory specification,
10
+ # and user context switching within the container.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Execute arbitrary commands in running containers
15
+ # - Support for command arguments and shell parsing
16
+ # - Environment variable injection
17
+ # - Working directory specification
18
+ # - User context switching (run as specific user)
19
+ # - Standard input, output, and error handling
20
+ # - Configurable execution timeouts
21
+ #
22
+ # == Security Considerations
23
+ #
24
+ # **CRITICAL WARNING**: This tool provides arbitrary command execution
25
+ # capabilities with significant security implications:
26
+ #
27
+ # - **Code Execution**: Can run any command available in the container
28
+ # - **File System Access**: Can read, write, and modify container files
29
+ # - **Network Access**: Can initiate network connections from container
30
+ # - **Process Manipulation**: Can start, stop, and signal processes
31
+ # - **Data Exposure**: Can access sensitive data within the container
32
+ # - **Privilege Escalation**: May exploit container or kernel vulnerabilities
33
+ # - **Resource Consumption**: Can consume container and host resources
34
+ #
35
+ # **Security Recommendations**:
36
+ # - Implement strict access controls and authentication
37
+ # - Use dedicated execution containers with minimal privileges
38
+ # - Monitor and log all command executions
39
+ # - Apply resource limits and timeouts
40
+ # - Validate and sanitize all command inputs
41
+ # - Consider using read-only file systems where possible
42
+ # - Implement network segmentation for container environments
43
+ #
44
+ # == Parameters
45
+ #
46
+ # - **id**: Container ID or name (required)
47
+ # - **cmd**: Command to execute (shell-parsed into arguments) (required)
48
+ # - **working_dir**: Working directory for command execution (optional)
49
+ # - **user**: User to run the command as (optional, e.g., "1000" or "username")
50
+ # - **env**: Environment variables as comma-separated KEY=VALUE pairs (optional)
51
+ # - **stdin**: Input to send to command via stdin (optional)
52
+ # - **timeout**: Timeout in seconds (optional, default: 60)
53
+ #
54
+ # == Example Usage
55
+ #
56
+ # # Basic command execution
57
+ # response = ExecContainer.call(
58
+ # server_context: context,
59
+ # id: "web-container",
60
+ # cmd: "nginx -t"
61
+ # )
62
+ #
63
+ # # Advanced execution with environment
64
+ # response = ExecContainer.call(
65
+ # server_context: context,
66
+ # id: "app-container",
67
+ # cmd: "bundle exec rails console",
68
+ # working_dir: "/app",
69
+ # user: "rails",
70
+ # env: "RAILS_ENV=production,DEBUG=true",
71
+ # timeout: 300
72
+ # )
73
+ #
74
+ # @see ::Docker::Container#exec
75
+ # @since 0.1.0
76
+ EXEC_CONTAINER_DEFINITION = ToolForge.define(:exec_container) do
77
+ description 'Execute a command inside a running Docker container. ' \
78
+ 'WARNING: This provides arbitrary command execution within the container. ' \
79
+ 'Ensure proper security measures are in place.'
80
+
81
+ param :id,
82
+ type: :string,
83
+ description: 'Container ID or name'
84
+
85
+ param :cmd,
86
+ type: :string,
87
+ description: 'Command to execute (e.g., "ls -la /app" or "python script.py")'
88
+
89
+ param :working_dir,
90
+ type: :string,
91
+ description: 'Working directory for the command (optional)',
92
+ required: false
93
+
94
+ param :user,
95
+ type: :string,
96
+ description: 'User to run the command as (optional, e.g., "1000" or "username")',
97
+ required: false
98
+
99
+ param :env,
100
+ type: :string,
101
+ description: 'Environment variables as comma-separated KEY=VALUE pairs (optional)',
102
+ required: false
103
+
104
+ param :stdin,
105
+ type: :string,
106
+ description: 'Input to send to the command via stdin (optional)',
107
+ required: false
108
+
109
+ param :timeout,
110
+ type: :integer,
111
+ description: 'Timeout in seconds (optional, default: 60)',
112
+ required: false,
113
+ default: 60
114
+
115
+ execute do |id:, cmd:, working_dir: nil, user: nil, env: nil, stdin: nil, timeout: 60|
116
+ container = ::Docker::Container.get(id)
117
+
118
+ # Parse command string into array
119
+ cmd_array = Shellwords.split(cmd)
120
+
121
+ # Parse environment variables from comma-separated string to array
122
+ env.split(',').map(&:strip) if env && !env.empty?
123
+
124
+ # Execute the command
125
+ stdout_data = []
126
+ stderr_data = []
127
+ exit_code = nil
128
+
129
+ begin
130
+ # Use container.exec which returns [stdout, stderr, exit_code]
131
+ result = if stdin
132
+ container.exec(cmd_array, stdin: StringIO.new(stdin), wait: timeout)
133
+ else
134
+ container.exec(cmd_array, wait: timeout)
135
+ end
136
+
137
+ stdout_data = result[0]
138
+ stderr_data = result[1]
139
+ exit_code = result[2]
140
+ rescue ::Docker::Error::TimeoutError
141
+ return "Command execution timed out after #{timeout} seconds"
142
+ end
143
+
144
+ # Format response
145
+ response_text = "Command executed in container #{id}\n"
146
+ response_text += "Exit code: #{exit_code}\n\n"
147
+
148
+ if stdout_data && !stdout_data.empty?
149
+ stdout_str = stdout_data.join
150
+ response_text += "STDOUT:\n#{stdout_str}\n" unless stdout_str.strip.empty?
151
+ end
152
+
153
+ if stderr_data && !stderr_data.empty?
154
+ stderr_str = stderr_data.join
155
+ response_text += "\nSTDERR:\n#{stderr_str}\n" unless stderr_str.strip.empty?
156
+ end
157
+
158
+ response_text.strip
159
+ rescue ::Docker::Error::NotFoundError
160
+ "Container #{id} not found"
161
+ rescue StandardError => e
162
+ "Error executing command: #{e.message}"
163
+ end
164
+ end
165
+
166
+ ExecContainer = EXEC_CONTAINER_DEFINITION.to_ruby_llm_tool
167
+ end
168
+ end
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for fetching Docker container logs.
6
+ #
7
+ # This tool retrieves log output from Docker containers, including both
8
+ # standard output and standard error streams. It supports filtering by
9
+ # stream type, limiting output length, timestamp inclusion, and retrieving
10
+ # logs from both running and stopped containers.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Fetch logs from running and stopped containers
15
+ # - Separate or combined stdout and stderr streams
16
+ # - Configurable output length limiting (tail functionality)
17
+ # - Optional timestamp inclusion for log entries
18
+ # - Support for container identification by ID or name
19
+ # - Comprehensive error handling and status reporting
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # Container logs may contain sensitive information:
24
+ # - **Application Data**: Database queries, API keys, user data
25
+ # - **System Information**: Internal paths, configuration details
26
+ # - **Error Details**: Stack traces revealing application internals
27
+ # - **Access Patterns**: User behavior and system usage information
28
+ # - **Debugging Information**: Temporary credentials or session data
29
+ #
30
+ # Implement proper access controls and data sanitization for log access.
31
+ #
32
+ # == Parameters
33
+ #
34
+ # - **id**: Container ID or name (required)
35
+ # - **stdout**: Include stdout in logs (optional, default: true)
36
+ # - **stderr**: Include stderr in logs (optional, default: true)
37
+ # - **timestamps**: Show timestamps for log entries (optional, default: false)
38
+ # - **tail**: Number of lines to show from end of logs (optional, default: all)
39
+ #
40
+ # == Example Usage
41
+ #
42
+ # # Fetch all logs
43
+ # response = FetchContainerLogs.call(
44
+ # server_context: context,
45
+ # id: "web-server"
46
+ # )
47
+ #
48
+ # # Fetch recent errors with timestamps
49
+ # response = FetchContainerLogs.call(
50
+ # server_context: context,
51
+ # id: "app-container",
52
+ # stdout: false,
53
+ # stderr: true,
54
+ # timestamps: true,
55
+ # tail: 100
56
+ # )
57
+ #
58
+ # @see ::Docker::Container#logs
59
+ # @since 0.1.0
60
+ FETCH_CONTAINER_LOGS_DEFINITION = ToolForge.define(:fetch_container_logs) do
61
+ description 'Fetch Docker container logs'
62
+
63
+ param :id,
64
+ type: :string,
65
+ description: 'Container ID or name'
66
+
67
+ param :stdout,
68
+ type: :boolean,
69
+ description: 'Include stdout (default: true)',
70
+ required: false,
71
+ default: true
72
+
73
+ param :stderr,
74
+ type: :boolean,
75
+ description: 'Include stderr (default: true)',
76
+ required: false,
77
+ default: true
78
+
79
+ param :tail,
80
+ type: :integer,
81
+ description: 'Number of lines to show from the end of logs (default: all)',
82
+ required: false
83
+
84
+ param :timestamps,
85
+ type: :boolean,
86
+ description: 'Show timestamps (default: false)',
87
+ required: false,
88
+ default: false
89
+
90
+ execute do |id:, stdout: true, stderr: true, tail: nil, timestamps: false|
91
+ container = ::Docker::Container.get(id)
92
+
93
+ options = {
94
+ stdout: stdout,
95
+ stderr: stderr,
96
+ timestamps: timestamps
97
+ }
98
+ options[:tail] = tail if tail
99
+
100
+ container.logs(options)
101
+ rescue ::Docker::Error::NotFoundError
102
+ "Container #{id} not found"
103
+ rescue StandardError => e
104
+ "Error fetching logs: #{e.message}"
105
+ end
106
+ end
107
+
108
+ FetchContainerLogs = FETCH_CONTAINER_LOGS_DEFINITION.to_ruby_llm_tool
109
+ end
110
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for listing Docker containers.
6
+ #
7
+ # This tool provides comprehensive information about all Docker containers
8
+ # on the system, including both running and stopped containers. It returns
9
+ # detailed metadata for each container including names, images, status,
10
+ # network configuration, and resource usage.
11
+ #
12
+ # == Features
13
+ #
14
+ # - Lists all containers (running and stopped)
15
+ # - Provides detailed container metadata
16
+ # - Shows network configuration and port mappings
17
+ # - Displays resource usage and statistics
18
+ # - Includes mount point information
19
+ # - Shows container labels and annotations
20
+ #
21
+ # == Security Considerations
22
+ #
23
+ # This tool provides system information that could be useful for:
24
+ # - **System Reconnaissance**: Reveals running services and configurations
25
+ # - **Network Discovery**: Shows internal network topology
26
+ # - **Resource Analysis**: Exposes system resource usage patterns
27
+ #
28
+ # Use with appropriate access controls in production environments.
29
+ #
30
+ # == Return Format
31
+ #
32
+ # Returns an array of container objects with comprehensive metadata:
33
+ # - Container names and IDs
34
+ # - Image information and tags
35
+ # - Current state and status
36
+ # - Network settings and port bindings
37
+ # - Mount points and volumes
38
+ # - Labels and environment details
39
+ #
40
+ # == Example Usage
41
+ #
42
+ # containers = ListContainers.call(server_context: context)
43
+ # containers.each do |container|
44
+ # puts "#{container['Names'].first}: #{container['State']}"
45
+ # end
46
+ #
47
+ # @see ::Docker::Container.all
48
+ # @since 0.1.0
49
+ LIST_CONTAINERS_DEFINITION = ToolForge.define(:list_containers) do
50
+ description 'List Docker containers'
51
+
52
+ param :all,
53
+ type: :boolean,
54
+ description: 'Show all containers (default shows all containers including stopped ones)',
55
+ required: false,
56
+ default: true
57
+
58
+ execute do |all: true|
59
+ ::Docker::Container.all(all: all).map(&:info)
60
+ end
61
+ end
62
+
63
+ ListContainers = LIST_CONTAINERS_DEFINITION.to_ruby_llm_tool
64
+ end
65
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for listing Docker images.
6
+ #
7
+ # This tool provides comprehensive information about all Docker images
8
+ # stored on the local system. It returns detailed metadata including
9
+ # image sizes, creation dates, tags, and usage statistics.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Lists all locally stored Docker images
14
+ # - Provides detailed image metadata and statistics
15
+ # - Shows image sizes and storage usage
16
+ # - Displays repository tags and digests
17
+ # - Includes creation timestamps and labels
18
+ # - Reports container usage counts
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # This tool provides information that could be useful for:
23
+ # - **System Analysis**: Reveals installed software and versions
24
+ # - **Vulnerability Assessment**: Shows potential attack surfaces
25
+ # - **Resource Planning**: Exposes storage usage patterns
26
+ #
27
+ # Monitor access to this tool in production environments.
28
+ #
29
+ # == Return Format
30
+ #
31
+ # Returns an array of image objects with comprehensive metadata:
32
+ # - Repository tags and digests
33
+ # - Image sizes and virtual sizes
34
+ # - Creation timestamps
35
+ # - Container usage counts
36
+ # - Labels and annotations
37
+ # - Parent-child relationships
38
+ #
39
+ # == Example Usage
40
+ #
41
+ # images = ListImages.call(server_context: context)
42
+ # images.each do |image|
43
+ # puts "#{image['RepoTags']}: #{image['Size']} bytes"
44
+ # end
45
+ #
46
+ # @see ::Docker::Image.all
47
+ # @since 0.1.0
48
+ LIST_IMAGES_DEFINITION = ToolForge.define(:list_images) do
49
+ description 'List Docker images'
50
+
51
+ execute do
52
+ ::Docker::Image.all.map(&:info)
53
+ end
54
+ end
55
+
56
+ ListImages = LIST_IMAGES_DEFINITION.to_ruby_llm_tool
57
+ end
58
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for listing Docker networks.
6
+ #
7
+ # This tool provides comprehensive information about all Docker networks
8
+ # configured on the system. It returns detailed network configuration
9
+ # including IPAM settings, connected containers, and network drivers.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Lists all Docker networks (built-in and custom)
14
+ # - Provides detailed network configuration
15
+ # - Shows IPAM (IP Address Management) settings
16
+ # - Displays connected containers
17
+ # - Includes driver information and options
18
+ # - Reports network scope and capabilities
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Network information can be sensitive as it reveals:
23
+ # - **Network Topology**: Internal network architecture
24
+ # - **IP Addressing**: Subnet configurations and ranges
25
+ # - **Container Connectivity**: Service interconnections
26
+ # - **Network Isolation**: Security boundary configurations
27
+ #
28
+ # Restrict access to this tool in production environments.
29
+ #
30
+ # == Return Format
31
+ #
32
+ # Returns an array of network objects with comprehensive metadata:
33
+ # - Network names and IDs
34
+ # - Driver types and configurations
35
+ # - IPAM settings and subnet information
36
+ # - Connected container details
37
+ # - Network options and labels
38
+ # - Scope and capability flags
39
+ #
40
+ # == Example Usage
41
+ #
42
+ # networks = ListNetworks.call(server_context: context)
43
+ # networks.each do |network|
44
+ # puts "#{network['Name']}: #{network['Driver']}"
45
+ # end
46
+ #
47
+ # @see ::Docker::Network.all
48
+ # @since 0.1.0
49
+ LIST_NETWORKS_DEFINITION = ToolForge.define(:list_networks) do
50
+ description 'List Docker networks'
51
+
52
+ execute do
53
+ ::Docker::Network.all.map(&:info)
54
+ end
55
+ end
56
+
57
+ ListNetworks = LIST_NETWORKS_DEFINITION.to_ruby_llm_tool
58
+ end
59
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for listing Docker volumes.
6
+ #
7
+ # This tool provides comprehensive information about all Docker volumes
8
+ # configured on the system. It returns detailed volume metadata including
9
+ # mount points, drivers, usage statistics, and associated containers.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Lists all Docker volumes (named and anonymous)
14
+ # - Provides detailed volume metadata
15
+ # - Shows mount points and storage locations
16
+ # - Displays driver information and options
17
+ # - Includes creation timestamps and labels
18
+ # - Reports volume scope and capabilities
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Volume information can reveal sensitive details about:
23
+ # - **Data Storage**: Persistent data locations and structures
24
+ # - **File System Access**: Mount points and storage paths
25
+ # - **Container Dependencies**: Volume usage patterns
26
+ # - **Data Persistence**: Backup and recovery points
27
+ #
28
+ # Monitor access to this tool and implement appropriate controls.
29
+ #
30
+ # == Return Format
31
+ #
32
+ # Returns an array of volume objects with comprehensive metadata:
33
+ # - Volume names and mount points
34
+ # - Driver types and configurations
35
+ # - Creation timestamps
36
+ # - Labels and options
37
+ # - Scope information
38
+ # - Storage usage details
39
+ #
40
+ # == Example Usage
41
+ #
42
+ # volumes = ListVolumes.call(server_context: context)
43
+ # volumes.each do |volume|
44
+ # puts "#{volume['Name']}: #{volume['Mountpoint']}"
45
+ # end
46
+ #
47
+ # @see ::Docker::Volume.all
48
+ # @since 0.1.0
49
+ LIST_VOLUMES_DEFINITION = ToolForge.define(:list_volumes) do
50
+ description 'List Docker volumes'
51
+
52
+ execute do
53
+ ::Docker::Volume.all.map(&:info)
54
+ end
55
+ end
56
+
57
+ ListVolumes = LIST_VOLUMES_DEFINITION.to_ruby_llm_tool
58
+ end
59
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RubyLLM
4
+ module Docker
5
+ # MCP tool for pulling Docker images from registries.
6
+ #
7
+ # This tool provides the ability to download Docker images from Docker
8
+ # registries (like Docker Hub) to the local system. It supports flexible
9
+ # tag specification and handles various image naming conventions.
10
+ #
11
+ # == Features
12
+ #
13
+ # - Pull images from any accessible Docker registry
14
+ # - Flexible tag specification (explicit or default)
15
+ # - Support for official and user repositories
16
+ # - Automatic latest tag handling
17
+ # - Comprehensive error handling
18
+ # - Progress tracking through Docker daemon
19
+ #
20
+ # == Security Considerations
21
+ #
22
+ # Pulling images can introduce security risks:
23
+ # - **Malicious Images**: Images may contain malware or backdoors
24
+ # - **Vulnerable Software**: Images may have known security vulnerabilities
25
+ # - **Untrusted Sources**: Images from unknown publishers may be compromised
26
+ # - **Supply Chain Attacks**: Legitimate-looking images may be malicious
27
+ # - **Resource Consumption**: Large images can consume significant disk space
28
+ #
29
+ # **Security Recommendations**:
30
+ # - Only pull images from trusted registries and publishers
31
+ # - Verify image signatures when available
32
+ # - Scan pulled images for vulnerabilities
33
+ # - Use specific tags rather than 'latest'
34
+ # - Monitor registry access and authentication
35
+ # - Regularly update and patch images
36
+ #
37
+ # == Tag Handling
38
+ #
39
+ # The tool handles tags intelligently:
40
+ # - If image includes tag (e.g., "nginx:1.21"), use as specified
41
+ # - If separate tag provided, append to image name
42
+ # - If no tag specified, default to "latest"
43
+ # - Supports all Docker tag conventions
44
+ #
45
+ # == Parameters
46
+ #
47
+ # - **from_image**: Image name to pull (required, e.g., "ubuntu" or "ubuntu:22.04")
48
+ # - **tag**: Tag to pull (optional, defaults to "latest" if not specified in from_image)
49
+ #
50
+ # == Example Usage
51
+ #
52
+ # # Pull latest version
53
+ # response = PullImage.call(
54
+ # server_context: context,
55
+ # from_image: "nginx"
56
+ # )
57
+ #
58
+ # # Pull specific version
59
+ # response = PullImage.call(
60
+ # server_context: context,
61
+ # from_image: "postgres",
62
+ # tag: "13.8"
63
+ # )
64
+ #
65
+ # @see ::Docker::Image.create
66
+ # @since 0.1.0
67
+ PULL_IMAGE_DEFINITION = ToolForge.define(:pull_image) do
68
+ description 'Pull a Docker image'
69
+
70
+ param :from_image,
71
+ type: :string,
72
+ description: 'Image name to pull (e.g., "ubuntu" or "ubuntu:22.04")'
73
+
74
+ param :tag,
75
+ type: :string,
76
+ description: 'Tag to pull (optional, defaults to "latest" if not specified in from_image)',
77
+ required: false
78
+
79
+ execute do |from_image:, tag: nil|
80
+ # If tag is provided separately, append it to from_image
81
+ # If from_image already has a tag (contains :), use as-is
82
+ # Otherwise default to :latest
83
+ image_with_tag = if tag
84
+ "#{from_image}:#{tag}"
85
+ elsif from_image.include?(':')
86
+ from_image
87
+ else
88
+ "#{from_image}:latest"
89
+ end
90
+
91
+ image = ::Docker::Image.create('fromImage' => image_with_tag)
92
+
93
+ "Image #{image_with_tag} pulled successfully. ID: #{image.id}"
94
+ rescue ::Docker::Error::NotFoundError
95
+ "Image #{image_with_tag} not found"
96
+ rescue StandardError => e
97
+ "Error pulling image: #{e.message}"
98
+ end
99
+ end
100
+
101
+ PullImage = PULL_IMAGE_DEFINITION.to_ruby_llm_tool
102
+ end
103
+ end