ruby_llm-docker 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.
@@ -2,110 +2,72 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Docker
5
- # RubyLLM tool for removing Docker networks.
5
+ # MCP tool for removing Docker networks.
6
6
  #
7
- # This tool provides the ability to permanently delete Docker networks from
8
- # the system. It safely removes custom networks while protecting built-in
9
- # system networks from accidental deletion.
7
+ # This tool provides the ability to delete Docker networks when they
8
+ # are no longer needed. Network removal helps maintain clean network
9
+ # configurations and prevents resource leaks.
10
10
  #
11
11
  # == Features
12
12
  #
13
- # - Remove custom Docker networks by ID or name
14
- # - Protection against removing built-in networks
13
+ # - Remove networks by ID or name
14
+ # - Validation of network existence
15
15
  # - Comprehensive error handling
16
- # - Dependency checking (prevents removal if containers are connected)
16
+ # - Prevention of removing networks in use
17
17
  # - Safe cleanup of network resources
18
- #
19
- # == ⚠️ Service Disruption Warning ⚠️
20
- #
21
- # **NETWORK REMOVAL CAN DISRUPT SERVICES**
22
- #
23
- # Removing networks can cause immediate service disruption:
24
- # - Connected containers lose network connectivity
25
- # - Inter-container communication is broken
26
- # - Services may become unreachable
27
- # - Application functionality can be severely impacted
28
- # - Network-dependent processes may fail
29
- #
30
- # == Protected Networks
31
- #
32
- # Docker protects certain built-in networks from removal:
33
- # - **bridge**: Default bridge network
34
- # - **host**: Host networking
35
- # - **none**: No networking
36
- # - **System networks**: Docker-managed networks
18
+ # - Network dependency checking
37
19
  #
38
20
  # == Security Considerations
39
21
  #
40
- # Network removal affects security boundaries:
41
- # - Removes network isolation between containers
42
- # - May expose containers to unintended networks
43
- # - Could impact security segmentation strategies
44
- # - Affects network-based access controls
22
+ # Network removal involves important considerations:
23
+ # - **Service Disruption**: Removing active networks disconnects containers
24
+ # - **Data Isolation**: Network removal can affect container communication
25
+ # - **Resource Cleanup**: Improper removal can leave network artifacts
26
+ # - **Container Dependencies**: Containers may fail without expected networks
27
+ # - **Network Policies**: Removal affects security and access policies
45
28
  #
46
- # Security implications:
47
- # - Ensure no critical containers depend on the network
48
- # - Verify alternative connectivity exists if needed
49
- # - Consider impact on security boundaries
50
- # - Monitor for unauthorized network modifications
29
+ # **Security Recommendations**:
30
+ # - Verify no containers are connected before removal
31
+ # - Check for dependent services and applications
32
+ # - Document network removal in change logs
33
+ # - Implement network lifecycle management
34
+ # - Monitor for orphaned network resources
35
+ # - Use network removal as part of cleanup procedures
51
36
  #
52
- # Best practices:
53
- # - Stop containers before removing their networks
54
- # - Verify network dependencies before removal
55
- # - Have rollback plans for critical networks
56
- # - Document network removal procedures
57
- # - Monitor network connectivity after removal
37
+ # == Parameters
38
+ #
39
+ # - **id**: Network ID or name (required)
58
40
  #
59
41
  # == Example Usage
60
42
  #
61
- # # Remove custom network
62
- # RemoveNetwork.call(
43
+ # # Remove network by name
44
+ # response = RemoveNetwork.call(
63
45
  # server_context: context,
64
46
  # id: "app-network"
65
47
  # )
66
48
  #
67
- # # Remove by network ID
68
- # RemoveNetwork.call(
49
+ # # Remove network by ID
50
+ # response = RemoveNetwork.call(
69
51
  # server_context: context,
70
52
  # id: "abc123def456"
71
53
  # )
72
54
  #
73
- # @see CreateNetwork
74
- # @see ListNetworks
75
- # @see Docker::Network#delete
55
+ # # Clean up test networks
56
+ # response = RemoveNetwork.call(
57
+ # server_context: context,
58
+ # id: "test-isolated-network"
59
+ # )
60
+ #
61
+ # @see ::Docker::Network#delete
76
62
  # @since 0.1.0
77
- class RemoveNetwork < RubyLLM::Tool
63
+ REMOVE_NETWORK_DEFINITION = ToolForge.define(:remove_network) do
78
64
  description 'Remove a Docker network'
79
65
 
80
- param :id, type: :string, desc: 'Network ID or name'
66
+ param :id,
67
+ type: :string,
68
+ description: 'Network ID or name'
81
69
 
82
- # Remove a Docker network from the system.
83
- #
84
- # This method permanently deletes the specified network. The network
85
- # must not have any containers connected to it, and built-in system
86
- # networks cannot be removed.
87
- #
88
- # @param id [String] network ID or name to remove
89
- # @param server_context [Object] RubyLLM context (unused but required)
90
- #
91
- # @return [RubyLLM::Tool::Response] removal operation results
92
- #
93
- # @raise [Docker::Error::NotFoundError] if network doesn't exist
94
- # @raise [StandardError] for removal failures or dependency conflicts
95
- #
96
- # @example Remove custom network
97
- # response = RemoveNetwork.call(
98
- # server_context: context,
99
- # id: "frontend-network"
100
- # )
101
- #
102
- # @example Remove by ID
103
- # response = tool.execute(
104
- # id: "1a2b3c4d5e6f"
105
- # )
106
- #
107
- # @see Docker::Network#delete
108
- def execute(id:)
70
+ execute do |id:|
109
71
  network = ::Docker::Network.get(id)
110
72
  network.delete
111
73
 
@@ -116,5 +78,7 @@ module RubyLLM
116
78
  "Error removing network: #{e.message}"
117
79
  end
118
80
  end
81
+
82
+ RemoveNetwork = REMOVE_NETWORK_DEFINITION.to_ruby_llm_tool
119
83
  end
120
84
  end
@@ -2,117 +2,82 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Docker
5
- # RubyLLM tool for removing Docker volumes.
5
+ # MCP tool for removing Docker volumes.
6
6
  #
7
- # This tool provides the ability to permanently delete Docker volumes from
8
- # the system. This is a destructive operation that will permanently delete
9
- # all data stored in the volume.
7
+ # This tool provides the ability to delete Docker volumes when they
8
+ # are no longer needed. Volume removal is critical for preventing
9
+ # storage leaks and maintaining clean Docker environments.
10
10
  #
11
11
  # == Features
12
12
  #
13
- # - Remove Docker volumes by name
14
- # - Force removal option for volumes in use
13
+ # - Remove volumes by name
14
+ # - Force removal of volumes in use
15
+ # - Validation of volume existence
15
16
  # - Comprehensive error handling
16
- # - Dependency checking (prevents removal if containers are using the volume)
17
- # - Safe cleanup of storage resources
18
- #
19
- # == ⚠️ CRITICAL DATA LOSS WARNING ⚠️
20
- #
21
- # **DESTRUCTIVE OPERATION - PERMANENT DATA LOSS**
22
- #
23
- # This operation permanently and irreversibly deletes data:
24
- # - **ALL DATA** in the volume is deleted forever
25
- # - No recovery possible after deletion
26
- # - Applications may lose critical data
27
- # - Databases and persistent state are destroyed
28
- # - Configuration files and user data are lost
29
- # - Operation cannot be undone
30
- #
31
- # == Volume Dependencies
32
- #
33
- # Volumes may have active dependencies:
34
- # - **Running Containers**: Containers currently using the volume
35
- # - **Stopped Containers**: Containers that could be restarted
36
- # - **Application Data**: Critical application state and databases
37
- # - **User Data**: User-generated content and files
17
+ # - Safe volume cleanup procedures
18
+ # - Prevention of accidental data loss
38
19
  #
39
20
  # == Security Considerations
40
21
  #
41
- # Volume removal has security implications:
42
- # - Sensitive data is not securely wiped
43
- # - Data may be recoverable from disk sectors
44
- # - Shared volumes may affect multiple applications
45
- # - Removal logs may reveal data existence
22
+ # Volume removal involves critical data considerations:
23
+ # - **Data Loss**: Removed volumes and their data are permanently deleted
24
+ # - **Service Disruption**: Removing volumes can break running containers
25
+ # - **Data Recovery**: Volume data cannot be recovered after removal
26
+ # - **Container Dependencies**: Applications may fail without expected volumes
27
+ # - **Storage Cleanup**: Improper removal can leave orphaned data
28
+ # - **Backup Requirements**: Critical data should be backed up before removal
46
29
  #
47
- # Critical security measures:
48
- # - **Backup critical data** before removal
49
- # - Verify no containers depend on the volume
50
- # - Consider secure data wiping for sensitive volumes
51
- # - Audit volume removal operations
52
- # - Monitor for unauthorized volume deletions
30
+ # **Security Recommendations**:
31
+ # - Always backup critical data before volume removal
32
+ # - Verify no containers are using the volume
33
+ # - Use force option only when absolutely necessary
34
+ # - Document volume removal in change management
35
+ # - Implement volume lifecycle and retention policies
36
+ # - Monitor storage usage after volume removal
37
+ # - Consider data migration instead of removal
53
38
  #
54
- # == Force Removal Risks
39
+ # == Parameters
55
40
  #
56
- # Force removal bypasses safety checks:
57
- # - Removes volumes even if containers are using them
58
- # - Can cause immediate application failures
59
- # - May corrupt running applications
60
- # - Data loss occurs immediately
41
+ # - **name**: Volume name (required)
42
+ # - **force**: Force removal of the volume (optional, default: false)
61
43
  #
62
44
  # == Example Usage
63
45
  #
64
- # # Safe removal of unused volume
65
- # RemoveVolume.call(
46
+ # # Remove unused volume
47
+ # response = RemoveVolume.call(
66
48
  # server_context: context,
67
- # name: "temp-data"
49
+ # name: "old-app-data"
68
50
  # )
69
51
  #
70
- # # Force removal of volume in use (DANGEROUS)
71
- # RemoveVolume.call(
52
+ # # Force remove volume in use
53
+ # response = RemoveVolume.call(
72
54
  # server_context: context,
73
55
  # name: "stuck-volume",
74
56
  # force: true
75
57
  # )
76
58
  #
77
- # @see CreateVolume
78
- # @see ListVolumes
79
- # @see Docker::Volume#remove
59
+ # # Clean up test volumes
60
+ # response = RemoveVolume.call(
61
+ # server_context: context,
62
+ # name: "test-data-volume"
63
+ # )
64
+ #
65
+ # @see ::Docker::Volume#remove
80
66
  # @since 0.1.0
81
- class RemoveVolume < RubyLLM::Tool
67
+ REMOVE_VOLUME_DEFINITION = ToolForge.define(:remove_volume) do
82
68
  description 'Remove a Docker volume'
83
69
 
84
- param :name, type: :string, desc: 'Volume name'
85
- param :force, type: :boolean, desc: 'Force removal of the volume (default: false)', required: false
70
+ param :name,
71
+ type: :string,
72
+ description: 'Volume name'
86
73
 
87
- # Remove a Docker volume permanently from the system.
88
- #
89
- # This method permanently deletes the specified volume and all data
90
- # contained within it. By default, it performs safety checks to prevent
91
- # removal of volumes with active container dependencies.
92
- #
93
- # @param name [String] name of the volume to remove
94
- # @param server_context [Object] RubyLLM context (unused but required)
95
- # @param force [Boolean] whether to force removal despite dependencies (default: false)
96
- #
97
- # @return [RubyLLM::Tool::Response] removal operation results
98
- #
99
- # @raise [Docker::Error::NotFoundError] if volume doesn't exist
100
- # @raise [StandardError] for removal failures or dependency conflicts
101
- #
102
- # @example Remove unused volume
103
- # response = RemoveVolume.call(
104
- # server_context: context,
105
- # name: "old-cache-data"
106
- # )
107
- #
108
- # @example Force remove problematic volume
109
- # response = tool.execute(
110
- # name: "corrupted-volume",
111
- # force: true
112
- # )
113
- #
114
- # @see Docker::Volume#remove
115
- def execute(name:, force: false)
74
+ param :force,
75
+ type: :boolean,
76
+ description: 'Force removal of the volume (default: false)',
77
+ required: false,
78
+ default: false
79
+
80
+ execute do |name:, force: false|
116
81
  volume = ::Docker::Volume.get(name)
117
82
  volume.remove(force: force)
118
83
 
@@ -123,5 +88,7 @@ module RubyLLM
123
88
  "Error removing volume: #{e.message}"
124
89
  end
125
90
  end
91
+
92
+ RemoveVolume = REMOVE_VOLUME_DEFINITION.to_ruby_llm_tool
126
93
  end
127
94
  end
@@ -2,87 +2,105 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Docker
5
- # RubyLLM tool for running Docker containers (create and start in one operation).
5
+ # MCP tool for running Docker containers.
6
6
  #
7
- # This tool provides a convenient way to create and immediately start Docker
8
- # containers from images. It combines the functionality of container creation
9
- # and startup into a single operation, which is the most common use case for
10
- # Docker containers.
7
+ # This tool creates and immediately starts a Docker container from a
8
+ # specified image in a single operation. It combines the functionality
9
+ # of create_container and start_container for convenience when immediate
10
+ # execution is desired.
11
11
  #
12
12
  # == Features
13
13
  #
14
- # - Create and start containers in one operation
15
- # - Full support for container configuration options
16
- # - Port mapping and network configuration
17
- # - Volume mounting capabilities
18
- # - Environment variable configuration
19
- # - Custom command execution
20
- # - Comprehensive error handling
14
+ # - Creates and starts containers in one operation
15
+ # - Supports all container configuration options
16
+ # - Configures command execution and environment variables
17
+ # - Sets up port exposure and network configuration
18
+ # - Applies advanced host configurations and volume mounts
19
+ # - Handles container naming and labeling
21
20
  #
22
21
  # == Security Considerations
23
22
  #
24
- # - Containers inherit Docker daemon privileges
25
- # - Port mappings expose services to host network
26
- # - Volume mounts provide filesystem access
27
- # - Environment variables may contain sensitive data
28
- # - Custom commands can execute arbitrary code
23
+ # Running containers involves significant security considerations:
24
+ # - **Immediate Execution**: Starts processes immediately upon creation
25
+ # - **Resource Consumption**: Consumes CPU, memory, and storage resources
26
+ # - **Network Exposure**: Creates active network endpoints
27
+ # - **File System Access**: Potentially accesses host directories
28
+ # - **Process Isolation**: Runs processes with configured privileges
29
29
  #
30
- # Use appropriate security measures:
31
- # - Run containers with minimal required privileges
32
- # - Limit port exposure to necessary services only
33
- # - Use read-only volumes where possible
34
- # - Avoid mounting sensitive host directories
35
- # - Validate environment variables for secrets
30
+ # Implement strict access controls and resource monitoring.
31
+ #
32
+ # == Parameters
33
+ #
34
+ # - **image**: Docker image to use (required)
35
+ # - **name**: Custom container name (optional)
36
+ # - **cmd**: Command to execute as space-separated string (optional)
37
+ # - **env**: Environment variables as comma-separated KEY=VALUE pairs (optional)
38
+ # - **exposed_ports**: Port exposure configuration as JSON object (optional)
39
+ # - **host_config**: Advanced host configuration as JSON object (optional)
36
40
  #
37
41
  # == Example Usage
38
42
  #
39
- # # Simple container run
40
- # RunContainer.call(
43
+ # # Simple container execution
44
+ # response = RunContainer.call(
41
45
  # server_context: context,
42
- # image: "nginx:latest",
43
- # name: "web-server"
46
+ # image: "alpine:latest",
47
+ # cmd: "echo 'Hello World'"
44
48
  # )
45
49
  #
46
- # # Advanced configuration with ports and volumes
47
- # RunContainer.call(
50
+ # # Web server with port binding
51
+ # response = RunContainer.call(
48
52
  # server_context: context,
49
- # image: "postgres:13",
50
- # name: "database",
51
- # env: ["POSTGRES_PASSWORD=secret"],
53
+ # image: "nginx:latest",
54
+ # name: "web-server",
55
+ # exposed_ports: {"80/tcp" => {}},
52
56
  # host_config: {
53
- # "PortBindings" => {"5432/tcp" => [{"HostPort" => "5432"}]},
54
- # "Binds" => ["/host/data:/var/lib/postgresql/data"]
57
+ # "PortBindings" => {"80/tcp" => [{"HostPort" => "8080"}]}
55
58
  # }
56
59
  # )
57
60
  #
58
- # @see CreateContainer
59
- # @see StartContainer
60
- # @see Docker::Container.create
61
+ # @see ::Docker::Container.create
61
62
  # @since 0.1.0
62
- class RunContainer < RubyLLM::Tool
63
+ RUN_CONTAINER_DEFINITION = ToolForge.define(:run_container) do
63
64
  description 'Run a Docker container (create and start)'
64
65
 
65
- param :image, desc: 'Image name to use (e.g., "ubuntu:22.04")'
66
- param :name, desc: 'Container name (optional)', required: false
67
- param :cmd, desc: 'Command to run (optional)', required: false
66
+ param :image,
67
+ type: :string,
68
+ description: 'Image name to use (e.g., "ubuntu:22.04")'
69
+
70
+ param :name,
71
+ type: :string,
72
+ description: 'Container name (optional)',
73
+ required: false
74
+
75
+ param :cmd,
76
+ type: :string,
77
+ description: 'Command to run as space-separated string (optional, e.g., "npm start" or "python app.py")',
78
+ required: false
79
+
68
80
  param :env,
69
- desc: 'Environment variables as comma-separated KEY=VALUE pairs ' \
70
- '(optional, e.g., "VAR1=value1,VAR2=value2")',
81
+ type: :string,
82
+ description: 'Environment variables as comma-separated KEY=VALUE pairs (optional)',
83
+ required: false
84
+
85
+ param :exposed_ports,
86
+ type: :object,
87
+ description: 'Exposed ports as {"port/protocol": {}} (optional)',
71
88
  required: false
72
- param :exposed_ports, desc: 'Exposed ports as JSON object (optional)', required: false
73
- param :host_config, desc: 'Host configuration including port bindings, volumes, etc.',
74
- required: false
75
89
 
76
- def execute(image:, name: nil, cmd: nil, env: nil, exposed_ports: nil, host_config: nil)
90
+ param :host_config,
91
+ type: :object,
92
+ description: 'Host configuration including port bindings, volumes, etc. (optional)',
93
+ required: false
94
+
95
+ execute do |image:, name: nil, cmd: nil, env: nil, exposed_ports: nil, host_config: nil|
77
96
  config = { 'Image' => image }
78
97
  config['name'] = name if name
79
- config['Cmd'] = cmd if cmd
80
98
 
81
- # Parse environment variables string into array if provided
82
- if env && !env.empty?
83
- env_array = env.split(',').map(&:strip).select { |e| e.include?('=') }
84
- config['Env'] = env_array unless env_array.empty?
85
- end
99
+ # Parse cmd string into array if provided
100
+ config['Cmd'] = Shellwords.split(cmd) if cmd && !cmd.strip.empty?
101
+
102
+ # Parse env string into array if provided
103
+ config['Env'] = env.split(',').map(&:strip) if env && !env.strip.empty?
86
104
 
87
105
  config['ExposedPorts'] = exposed_ports if exposed_ports
88
106
  config['HostConfig'] = host_config if host_config
@@ -100,5 +118,7 @@ module RubyLLM
100
118
  "Error running container: #{e.message}"
101
119
  end
102
120
  end
121
+
122
+ RunContainer = RUN_CONTAINER_DEFINITION.to_ruby_llm_tool
103
123
  end
104
124
  end
@@ -2,87 +2,62 @@
2
2
 
3
3
  module RubyLLM
4
4
  module Docker
5
- # RubyLLM tool for starting existing Docker containers.
5
+ # MCP tool for starting Docker containers.
6
6
  #
7
- # This tool provides the ability to start Docker containers that have been
8
- # created but are currently stopped. It's the counterpart to StopContainer
9
- # and is commonly used after CreateContainer or when restarting stopped
10
- # containers.
7
+ # This tool starts a previously created Docker container that is currently
8
+ # in a "created" or "stopped" state. It transitions the container to a
9
+ # "running" state and begins executing the configured command or entrypoint.
11
10
  #
12
11
  # == Features
13
12
  #
14
- # - Start stopped containers by ID or name
15
- # - Simple and reliable container lifecycle management
16
- # - Comprehensive error handling
17
- # - Works with containers in any stopped state
13
+ # - Starts containers by ID or name
14
+ # - Supports both short and full container IDs
15
+ # - Works with custom container names
16
+ # - Provides clear success/failure feedback
17
+ # - Handles container state transitions
18
+ # - Preserves all container configuration
18
19
  #
19
20
  # == Security Considerations
20
21
  #
21
- # Starting containers can have security implications:
22
- # - Containers resume with their original configuration
23
- # - Services become accessible on mapped ports
24
- # - Processes resume execution with previous privileges
25
- # - Network connections are re-established
22
+ # Starting containers involves security implications:
23
+ # - **Process Execution**: Begins running container processes
24
+ # - **Resource Activation**: Activates CPU, memory, and I/O usage
25
+ # - **Network Activation**: Brings network interfaces online
26
+ # - **Service Exposure**: Makes configured services accessible
26
27
  #
27
- # Ensure containers are properly configured before starting:
28
- # - Review port mappings and network exposure
29
- # - Verify volume mounts and file permissions
30
- # - Check environment variables for sensitive data
31
- # - Validate container image integrity
28
+ # Ensure proper monitoring and access controls are in place.
29
+ #
30
+ # == Parameters
31
+ #
32
+ # - **id**: Container ID or name (required)
33
+ # - Accepts full container IDs
34
+ # - Accepts short container IDs (first 12+ characters)
35
+ # - Accepts custom container names
32
36
  #
33
37
  # == Example Usage
34
38
  #
35
- # # Start container by name
36
- # StartContainer.call(
39
+ # # Start by container name
40
+ # response = StartContainer.call(
37
41
  # server_context: context,
38
42
  # id: "web-server"
39
43
  # )
40
44
  #
41
- # # Start container by ID
42
- # StartContainer.call(
45
+ # # Start by container ID
46
+ # response = StartContainer.call(
43
47
  # server_context: context,
44
48
  # id: "a1b2c3d4e5f6"
45
49
  # )
46
50
  #
47
- # @see CreateContainer
48
- # @see StopContainer
49
- # @see RunContainer
50
- # @see Docker::Container#start
51
+ # @see ::Docker::Container#start
51
52
  # @since 0.1.0
52
- class StartContainer < RubyLLM::Tool
53
+ START_CONTAINER_DEFINITION = ToolForge.define(:start_container) do
53
54
  description 'Start a Docker container'
54
55
 
55
- param :id, desc: 'Container ID or name'
56
+ param :id,
57
+ type: :string,
58
+ description: 'Container ID or name'
56
59
 
57
- # Start an existing Docker container.
58
- #
59
- # This method starts a container that is currently in a stopped state.
60
- # The container must already exist and be in a startable state. If the
61
- # container is already running, Docker will typically ignore the start
62
- # command without error.
63
- #
64
- # @param id [String] container ID (full or short) or container name
65
- # @param server_context [Object] RubyLLM context (unused but required)
66
- #
67
- # @return [RubyLLM::Tool::Response] start operation results
68
- #
69
- # @raise [Docker::Error::NotFoundError] if container doesn't exist
70
- # @raise [StandardError] for other start failures
71
- #
72
- # @example Start by container name
73
- # response = StartContainer.call(
74
- # server_context: context,
75
- # id: "my-app-container"
76
- # )
77
- #
78
- # @example Start by container ID
79
- # response = StartContainer.call(
80
- # server_context: context,
81
- # id: "abc123def456"
82
- # )
83
- #
84
- # @see Docker::Container#start
85
- def execute(id:)
60
+ execute do |id:|
86
61
  container = ::Docker::Container.get(id)
87
62
  container.start
88
63
 
@@ -93,5 +68,7 @@ module RubyLLM
93
68
  "Error starting container: #{e.message}"
94
69
  end
95
70
  end
71
+
72
+ StartContainer = START_CONTAINER_DEFINITION.to_ruby_llm_tool
96
73
  end
97
74
  end