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.
- checksums.yaml +4 -4
- data/lib/docker_mcp/build_image.rb +65 -84
- data/lib/docker_mcp/copy_to_container.rb +87 -161
- data/lib/docker_mcp/create_container.rb +63 -115
- data/lib/docker_mcp/create_network.rb +63 -102
- data/lib/docker_mcp/create_volume.rb +57 -100
- data/lib/docker_mcp/exec_container.rb +94 -147
- data/lib/docker_mcp/fetch_container_logs.rb +64 -117
- data/lib/docker_mcp/list_containers.rb +44 -47
- data/lib/docker_mcp/list_images.rb +32 -56
- data/lib/docker_mcp/list_networks.rb +33 -60
- data/lib/docker_mcp/list_volumes.rb +33 -67
- data/lib/docker_mcp/pull_image.rb +24 -68
- data/lib/docker_mcp/push_image.rb +61 -118
- data/lib/docker_mcp/recreate_container.rb +48 -99
- data/lib/docker_mcp/remove_container.rb +49 -101
- data/lib/docker_mcp/remove_image.rb +53 -119
- data/lib/docker_mcp/remove_network.rb +42 -96
- data/lib/docker_mcp/remove_volume.rb +52 -106
- data/lib/docker_mcp/run_container.rb +72 -82
- data/lib/docker_mcp/start_container.rb +36 -76
- data/lib/docker_mcp/stop_container.rb +41 -86
- data/lib/docker_mcp/tag_image.rb +67 -121
- data/lib/docker_mcp/version.rb +1 -1
- data/lib/docker_mcp.rb +2 -0
- metadata +15 -1
@@ -1,179 +1,122 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'json'
|
4
|
-
require 'open3'
|
5
|
-
|
6
3
|
module DockerMCP
|
7
4
|
# MCP tool for pushing Docker images to registries.
|
8
5
|
#
|
9
|
-
# This tool provides the ability to upload Docker images to Docker
|
10
|
-
# such as Docker Hub, private registries, or cloud-based
|
11
|
-
#
|
12
|
-
#
|
6
|
+
# This tool provides the ability to upload Docker images to Docker
|
7
|
+
# registries such as Docker Hub, private registries, or cloud-based
|
8
|
+
# container registries. It supports various push configurations and
|
9
|
+
# authentication scenarios.
|
13
10
|
#
|
14
11
|
# == Features
|
15
12
|
#
|
16
|
-
# - Push images to any
|
17
|
-
# -
|
18
|
-
# -
|
19
|
-
# -
|
20
|
-
# -
|
21
|
-
# -
|
13
|
+
# - Push images to any Docker registry
|
14
|
+
# - Support for tagged and untagged pushes
|
15
|
+
# - Registry authentication integration
|
16
|
+
# - Comprehensive error handling and validation
|
17
|
+
# - Multi-registry support
|
18
|
+
# - Progress tracking and status reporting
|
19
|
+
# - Registry namespace validation
|
22
20
|
#
|
23
|
-
# ==
|
21
|
+
# == Security Considerations
|
24
22
|
#
|
25
23
|
# Pushing images involves significant security risks:
|
26
24
|
# - **Credential Exposure**: Registry credentials may be exposed
|
27
|
-
# - **
|
28
|
-
# - **
|
29
|
-
# - **
|
30
|
-
# - **
|
25
|
+
# - **Image Integrity**: Pushed images become publicly accessible
|
26
|
+
# - **Supply Chain Risk**: Malicious images can be distributed
|
27
|
+
# - **Registry Security**: Vulnerable registries can be compromised
|
28
|
+
# - **Network Exposure**: Push operations traverse networks
|
29
|
+
# - **Access Control**: Improper permissions can lead to unauthorized access
|
31
30
|
#
|
32
|
-
#
|
33
|
-
# -
|
34
|
-
# - Scan images for
|
35
|
-
# - Use private registries for sensitive applications
|
31
|
+
# **Security Recommendations**:
|
32
|
+
# - Use secure registry authentication
|
33
|
+
# - Scan images for vulnerabilities before pushing
|
36
34
|
# - Implement image signing and verification
|
37
|
-
# -
|
38
|
-
# -
|
35
|
+
# - Use private registries for sensitive images
|
36
|
+
# - Monitor registry access and usage
|
37
|
+
# - Implement proper RBAC for registry operations
|
38
|
+
# - Validate image content before distribution
|
39
39
|
#
|
40
|
-
# ==
|
40
|
+
# == Parameters
|
41
41
|
#
|
42
|
-
#
|
43
|
-
# -
|
44
|
-
# -
|
45
|
-
# - Examples: `username/myapp`, `registry.company.com/team/app`
|
46
|
-
# - Local image names (without `/`) cannot be pushed
|
42
|
+
# - **name**: Image name or ID to push (required)
|
43
|
+
# - **tag**: Tag to push (optional, pushes all tags if not specified)
|
44
|
+
# - **repo_tag**: Full repo:tag to push (optional, e.g., "registry/repo:tag")
|
47
45
|
#
|
48
46
|
# == Example Usage
|
49
47
|
#
|
50
48
|
# # Push to Docker Hub
|
51
|
-
# PushImage.call(
|
49
|
+
# response = PushImage.call(
|
52
50
|
# server_context: context,
|
53
|
-
# name: "
|
54
|
-
# tag: "v1.0"
|
51
|
+
# name: "username/myapp",
|
52
|
+
# tag: "v1.0.0"
|
55
53
|
# )
|
56
54
|
#
|
57
55
|
# # Push to private registry
|
58
|
-
# PushImage.call(
|
56
|
+
# response = PushImage.call(
|
59
57
|
# server_context: context,
|
60
|
-
# name: "
|
61
|
-
#
|
58
|
+
# name: "myapp",
|
59
|
+
# repo_tag: "registry.company.com/team/myapp:latest"
|
62
60
|
# )
|
63
61
|
#
|
64
|
-
# # Push
|
65
|
-
# PushImage.call(
|
62
|
+
# # Push all tags
|
63
|
+
# response = PushImage.call(
|
66
64
|
# server_context: context,
|
67
|
-
# name: "myapp"
|
68
|
-
# repo_tag: "myregistry.com/myuser/myapp:v2.0"
|
65
|
+
# name: "username/myapp"
|
69
66
|
# )
|
70
67
|
#
|
71
|
-
# @see
|
72
|
-
# @see TagImage
|
73
|
-
# @see BuildImage
|
68
|
+
# @see Docker CLI push command
|
74
69
|
# @since 0.1.0
|
75
|
-
|
70
|
+
PUSH_IMAGE_DEFINITION = ToolForge.define(:push_image) do
|
76
71
|
description 'Push a Docker image'
|
77
72
|
|
78
|
-
|
79
|
-
|
80
|
-
name: {
|
81
|
-
type: 'string',
|
73
|
+
param :name,
|
74
|
+
type: :string,
|
82
75
|
description: 'Image name or ID to push'
|
83
|
-
},
|
84
|
-
tag: {
|
85
|
-
type: 'string',
|
86
|
-
description: 'Tag to push (optional, pushes all tags if not specified)'
|
87
|
-
},
|
88
|
-
repo_tag: {
|
89
|
-
type: 'string',
|
90
|
-
description: 'Full repo:tag to push (e.g., "registry/repo:tag") (optional)'
|
91
|
-
}
|
92
|
-
},
|
93
|
-
required: ['name']
|
94
|
-
)
|
95
76
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
# @return [MCP::Tool::Response] push operation results
|
108
|
-
#
|
109
|
-
# @raise [StandardError] for push failures or authentication issues
|
110
|
-
#
|
111
|
-
# @example Push tagged image to Docker Hub
|
112
|
-
# response = PushImage.call(
|
113
|
-
# server_context: context,
|
114
|
-
# name: "myuser/webapp",
|
115
|
-
# tag: "v1.2.3"
|
116
|
-
# )
|
117
|
-
#
|
118
|
-
# @example Push to private registry
|
119
|
-
# response = PushImage.call(
|
120
|
-
# server_context: context,
|
121
|
-
# name: "internal-registry.com/team/service",
|
122
|
-
# tag: "latest"
|
123
|
-
# )
|
124
|
-
#
|
125
|
-
# @see Docker::Image.get
|
126
|
-
def self.call(name:, server_context:, tag: nil, repo_tag: nil)
|
77
|
+
param :tag,
|
78
|
+
type: :string,
|
79
|
+
description: 'Tag to push (optional, pushes all tags if not specified)',
|
80
|
+
required: false
|
81
|
+
|
82
|
+
param :repo_tag,
|
83
|
+
type: :string,
|
84
|
+
description: 'Full repo:tag to push (e.g., "registry/repo:tag") (optional)',
|
85
|
+
required: false
|
86
|
+
|
87
|
+
execute do |name:, tag: nil, repo_tag: nil|
|
127
88
|
# Construct the full image identifier
|
128
89
|
image_identifier = tag ? "#{name}:#{tag}" : name
|
129
90
|
|
130
91
|
# Validate that the image name includes a registry/username
|
131
|
-
# Images without a registry prefix will fail to push to Docker Hub
|
132
92
|
unless name.include?('/') || repo_tag&.include?('/')
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
return MCP::Tool::Response.new([{
|
137
|
-
type: 'text',
|
138
|
-
text: error_msg
|
139
|
-
}])
|
93
|
+
next 'Error: Image name must include registry/username ' \
|
94
|
+
"(e.g., 'username/#{name}'). Local images cannot be " \
|
95
|
+
'pushed without a registry prefix.'
|
140
96
|
end
|
141
97
|
|
142
98
|
# Verify the image exists
|
143
99
|
begin
|
144
100
|
Docker::Image.get(image_identifier)
|
145
101
|
rescue Docker::Error::NotFoundError
|
146
|
-
|
147
|
-
type: 'text',
|
148
|
-
text: "Image #{image_identifier} not found"
|
149
|
-
}])
|
102
|
+
next "Image #{image_identifier} not found"
|
150
103
|
end
|
151
104
|
|
152
105
|
# Use the Docker CLI to push the image
|
153
|
-
# This way we leverage Docker's native credential handling
|
154
106
|
push_target = repo_tag || image_identifier
|
155
107
|
_, stderr, status = Open3.capture3('docker', 'push', push_target)
|
156
108
|
|
157
109
|
if status.success?
|
158
|
-
|
159
|
-
type: 'text',
|
160
|
-
text: "Image #{push_target} pushed successfully"
|
161
|
-
}])
|
110
|
+
"Image #{push_target} pushed successfully"
|
162
111
|
else
|
163
|
-
# Extract the error message from stderr
|
164
112
|
error_msg = stderr.strip
|
165
113
|
error_msg = 'Failed to push image' if error_msg.empty?
|
166
|
-
|
167
|
-
MCP::Tool::Response.new([{
|
168
|
-
type: 'text',
|
169
|
-
text: "Error pushing image: #{error_msg}"
|
170
|
-
}])
|
114
|
+
"Error pushing image: #{error_msg}"
|
171
115
|
end
|
172
116
|
rescue StandardError => e
|
173
|
-
|
174
|
-
type: 'text',
|
175
|
-
text: "Error pushing image: #{e.message}"
|
176
|
-
}])
|
117
|
+
"Error pushing image: #{e.message}"
|
177
118
|
end
|
178
119
|
end
|
120
|
+
|
121
|
+
PushImage = PUSH_IMAGE_DEFINITION.to_mcp_tool
|
179
122
|
end
|
@@ -1,123 +1,79 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module DockerMCP
|
4
|
-
# MCP tool for recreating Docker containers
|
4
|
+
# MCP tool for recreating Docker containers.
|
5
5
|
#
|
6
|
-
# This tool provides a
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# This tool provides a complete container recreation process that stops
|
7
|
+
# the existing container, removes it, and creates a new container with
|
8
|
+
# the same configuration. This is useful for applying image updates,
|
9
|
+
# clearing container state, or resolving container corruption issues.
|
10
10
|
#
|
11
11
|
# == Features
|
12
12
|
#
|
13
|
-
# -
|
14
|
-
# -
|
15
|
-
# -
|
16
|
-
# -
|
17
|
-
# -
|
18
|
-
# -
|
13
|
+
# - Complete container recreation with preserved configuration
|
14
|
+
# - Automatic stop, remove, and recreate sequence
|
15
|
+
# - Preserves original container configuration and settings
|
16
|
+
# - Configurable stop timeout for graceful shutdown
|
17
|
+
# - Handles both running and stopped containers
|
18
|
+
# - Maintains container networking and volume configurations
|
19
19
|
#
|
20
|
-
# ==
|
21
|
-
#
|
22
|
-
# 1. Retrieve existing container configuration
|
23
|
-
# 2. Stop container gracefully (if running)
|
24
|
-
# 3. Remove the old container
|
25
|
-
# 4. Create new container with identical config
|
26
|
-
# 5. Start new container (if original was running)
|
20
|
+
# == Security Considerations
|
27
21
|
#
|
28
|
-
#
|
22
|
+
# Container recreation involves several security considerations:
|
23
|
+
# - **Service Downtime**: Temporary service interruption during recreation
|
24
|
+
# - **Data Loss**: Container file system changes are lost (volumes preserved)
|
25
|
+
# - **Resource Allocation**: New container may have different resource usage
|
26
|
+
# - **Network Reconfiguration**: IP addresses may change
|
27
|
+
# - **State Reset**: Application state within container is lost
|
29
28
|
#
|
30
|
-
#
|
29
|
+
# Plan recreations carefully and coordinate with dependent services.
|
31
30
|
#
|
32
|
-
#
|
33
|
-
# - Container filesystem changes are lost
|
34
|
-
# - Temporary data and logs are deleted
|
35
|
-
# - Container state is reset completely
|
36
|
-
# - Network connections are interrupted
|
37
|
-
# - Anonymous volumes may be recreated empty
|
31
|
+
# == Parameters
|
38
32
|
#
|
39
|
-
#
|
33
|
+
# - **id**: Container ID or name to recreate (required)
|
34
|
+
# - **timeout**: Seconds to wait before killing container when stopping (optional, default: 10)
|
40
35
|
#
|
41
|
-
#
|
42
|
-
# - Sensitive environment variables are maintained
|
43
|
-
# - Port mappings and volume mounts are restored
|
44
|
-
# - Network access patterns remain the same
|
36
|
+
# == Process Flow
|
45
37
|
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
38
|
+
# 1. Inspect existing container to capture configuration
|
39
|
+
# 2. Stop the running container (if running)
|
40
|
+
# 3. Remove the stopped container
|
41
|
+
# 4. Create new container with captured configuration
|
42
|
+
# 5. Return new container information
|
51
43
|
#
|
52
44
|
# == Example Usage
|
53
45
|
#
|
54
46
|
# # Recreate with default timeout
|
55
|
-
# RecreateContainer.call(
|
47
|
+
# response = RecreateContainer.call(
|
56
48
|
# server_context: context,
|
57
49
|
# id: "web-server"
|
58
50
|
# )
|
59
51
|
#
|
60
|
-
# # Recreate with
|
61
|
-
# RecreateContainer.call(
|
52
|
+
# # Recreate with extended timeout
|
53
|
+
# response = RecreateContainer.call(
|
62
54
|
# server_context: context,
|
63
55
|
# id: "database",
|
64
56
|
# timeout: 30
|
65
57
|
# )
|
66
58
|
#
|
67
|
-
# @see
|
68
|
-
# @see
|
69
|
-
# @see RemoveContainer
|
59
|
+
# @see Docker::Container#stop
|
60
|
+
# @see Docker::Container#remove
|
70
61
|
# @see Docker::Container.create
|
71
62
|
# @since 0.1.0
|
72
|
-
|
63
|
+
RECREATE_CONTAINER_DEFINITION = ToolForge.define(:recreate_container) do
|
73
64
|
description 'Recreate a Docker container (stops, removes, and recreates with same configuration)'
|
74
65
|
|
75
|
-
|
76
|
-
|
77
|
-
id: {
|
78
|
-
type: 'string',
|
66
|
+
param :id,
|
67
|
+
type: :string,
|
79
68
|
description: 'Container ID or name to recreate'
|
80
|
-
},
|
81
|
-
timeout: {
|
82
|
-
type: 'integer',
|
83
|
-
description: 'Seconds to wait before killing the container when stopping (default: 10)'
|
84
|
-
}
|
85
|
-
},
|
86
|
-
required: ['id']
|
87
|
-
)
|
88
69
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
# @param id [String] container ID (full or short) or container name
|
97
|
-
# @param server_context [Object] MCP server context (unused but required)
|
98
|
-
# @param timeout [Integer] seconds to wait before force killing during stop (default: 10)
|
99
|
-
#
|
100
|
-
# @return [MCP::Tool::Response] recreation results with new container ID
|
101
|
-
#
|
102
|
-
# @raise [Docker::Error::NotFoundError] if container doesn't exist
|
103
|
-
# @raise [StandardError] for recreation failures
|
104
|
-
#
|
105
|
-
# @example Recreate application container
|
106
|
-
# response = RecreateContainer.call(
|
107
|
-
# server_context: context,
|
108
|
-
# id: "my-app"
|
109
|
-
# )
|
110
|
-
#
|
111
|
-
# @example Recreate database with extended timeout
|
112
|
-
# response = RecreateContainer.call(
|
113
|
-
# server_context: context,
|
114
|
-
# id: "postgres-main",
|
115
|
-
# timeout: 60 # Allow time for DB shutdown
|
116
|
-
# )
|
117
|
-
#
|
118
|
-
# @see Docker::Container.get
|
119
|
-
# @see Docker::Container.create
|
120
|
-
def self.call(id:, server_context:, timeout: 10)
|
70
|
+
param :timeout,
|
71
|
+
type: :integer,
|
72
|
+
description: 'Seconds to wait before killing the container when stopping (default: 10)',
|
73
|
+
required: false,
|
74
|
+
default: 10
|
75
|
+
|
76
|
+
execute do |id:, timeout: 10|
|
121
77
|
# Get the existing container
|
122
78
|
old_container = Docker::Container.get(id)
|
123
79
|
config = old_container.json
|
@@ -149,20 +105,13 @@ module DockerMCP
|
|
149
105
|
# Start if the old one was running
|
150
106
|
new_container.start if config['State']['Running']
|
151
107
|
|
152
|
-
|
153
|
-
type: 'text',
|
154
|
-
text: "Container #{id} recreated successfully. New ID: #{new_container.id}"
|
155
|
-
}])
|
108
|
+
"Container #{id} recreated successfully. New ID: #{new_container.id}"
|
156
109
|
rescue Docker::Error::NotFoundError
|
157
|
-
|
158
|
-
type: 'text',
|
159
|
-
text: "Container #{id} not found"
|
160
|
-
}])
|
110
|
+
"Container #{id} not found"
|
161
111
|
rescue StandardError => e
|
162
|
-
|
163
|
-
type: 'text',
|
164
|
-
text: "Error recreating container: #{e.message}"
|
165
|
-
}])
|
112
|
+
"Error recreating container: #{e.message}"
|
166
113
|
end
|
167
114
|
end
|
115
|
+
|
116
|
+
RecreateContainer = RECREATE_CONTAINER_DEFINITION.to_mcp_tool
|
168
117
|
end
|
@@ -3,140 +3,88 @@
|
|
3
3
|
module DockerMCP
|
4
4
|
# MCP tool for removing Docker containers.
|
5
5
|
#
|
6
|
-
# This tool
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
6
|
+
# This tool permanently removes a Docker container from the system,
|
7
|
+
# including its file system, configuration, and metadata. This is a
|
8
|
+
# destructive operation that cannot be undone. The container must
|
9
|
+
# be stopped before removal unless force is specified.
|
10
10
|
#
|
11
11
|
# == Features
|
12
12
|
#
|
13
|
-
# -
|
14
|
-
# -
|
13
|
+
# - Permanent container removal from system
|
14
|
+
# - Supports forced removal of running containers
|
15
15
|
# - Optional removal of associated volumes
|
16
|
-
# -
|
17
|
-
# -
|
16
|
+
# - Handles container identification by ID or name
|
17
|
+
# - Provides comprehensive error handling
|
18
|
+
# - Frees all associated system resources
|
18
19
|
#
|
19
|
-
# ==
|
20
|
-
#
|
21
|
-
# ⚠️ **DESTRUCTIVE OPERATION** ⚠️
|
20
|
+
# == Security Considerations
|
22
21
|
#
|
23
|
-
#
|
24
|
-
# -
|
25
|
-
# -
|
26
|
-
# -
|
27
|
-
# -
|
28
|
-
# -
|
22
|
+
# Container removal is a destructive operation with implications:
|
23
|
+
# - **Data Loss**: Permanently destroys container file system
|
24
|
+
# - **Configuration Loss**: Removes container settings and metadata
|
25
|
+
# - **Service Disruption**: Eliminates containerized services
|
26
|
+
# - **Resource Recovery**: Frees storage, memory, and system resources
|
27
|
+
# - **Audit Trail**: May remove forensic evidence if needed
|
29
28
|
#
|
30
|
-
#
|
29
|
+
# Implement proper backup and approval workflows for production systems.
|
31
30
|
#
|
32
|
-
#
|
33
|
-
# - Volume removal may affect other containers
|
34
|
-
# - Running container removal terminates services abruptly
|
35
|
-
# - Sensitive data in container memory is not securely wiped
|
31
|
+
# == Parameters
|
36
32
|
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
# -
|
33
|
+
# - **id**: Container ID or name (required)
|
34
|
+
# - Accepts full container IDs
|
35
|
+
# - Accepts short container IDs (first 12+ characters)
|
36
|
+
# - Accepts custom container names
|
37
|
+
# - **force**: Force removal of running container (optional, default: false)
|
38
|
+
# - **volumes**: Remove associated volumes (optional, default: false)
|
42
39
|
#
|
43
40
|
# == Example Usage
|
44
41
|
#
|
45
42
|
# # Remove stopped container
|
46
|
-
# RemoveContainer.call(
|
43
|
+
# response = RemoveContainer.call(
|
47
44
|
# server_context: context,
|
48
|
-
# id: "old-
|
45
|
+
# id: "old-web-server"
|
49
46
|
# )
|
50
47
|
#
|
51
48
|
# # Force remove running container with volumes
|
52
|
-
# RemoveContainer.call(
|
49
|
+
# response = RemoveContainer.call(
|
53
50
|
# server_context: context,
|
54
51
|
# id: "problematic-container",
|
55
52
|
# force: true,
|
56
53
|
# volumes: true
|
57
54
|
# )
|
58
55
|
#
|
59
|
-
# @see
|
60
|
-
# @see CreateContainer
|
61
|
-
# @see Docker::Container#delete
|
56
|
+
# @see Docker::Container#remove
|
62
57
|
# @since 0.1.0
|
63
|
-
|
58
|
+
REMOVE_CONTAINER_DEFINITION = ToolForge.define(:remove_container) do
|
64
59
|
description 'Remove a Docker container'
|
65
60
|
|
66
|
-
|
67
|
-
|
68
|
-
id: {
|
69
|
-
type: 'string',
|
61
|
+
param :id,
|
62
|
+
type: :string,
|
70
63
|
description: 'Container ID or name'
|
71
|
-
},
|
72
|
-
force: {
|
73
|
-
type: 'boolean',
|
74
|
-
description: 'Force removal of running container (default: false)'
|
75
|
-
},
|
76
|
-
volumes: {
|
77
|
-
type: 'boolean',
|
78
|
-
description: 'Remove associated volumes (default: false)'
|
79
|
-
}
|
80
|
-
},
|
81
|
-
required: ['id']
|
82
|
-
)
|
83
64
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
#
|
98
|
-
# @raise [Docker::Error::NotFoundError] if container doesn't exist
|
99
|
-
# @raise [StandardError] for other removal failures
|
100
|
-
#
|
101
|
-
# @example Remove stopped container
|
102
|
-
# response = RemoveContainer.call(
|
103
|
-
# server_context: context,
|
104
|
-
# id: "finished-job"
|
105
|
-
# )
|
106
|
-
#
|
107
|
-
# @example Force remove running container
|
108
|
-
# response = RemoveContainer.call(
|
109
|
-
# server_context: context,
|
110
|
-
# id: "stuck-container",
|
111
|
-
# force: true
|
112
|
-
# )
|
113
|
-
#
|
114
|
-
# @example Remove container and its volumes
|
115
|
-
# response = RemoveContainer.call(
|
116
|
-
# server_context: context,
|
117
|
-
# id: "temp-container",
|
118
|
-
# volumes: true
|
119
|
-
# )
|
120
|
-
#
|
121
|
-
# @see Docker::Container#delete
|
122
|
-
def self.call(id:, server_context:, force: false, volumes: false)
|
65
|
+
param :force,
|
66
|
+
type: :boolean,
|
67
|
+
description: 'Force removal of running container (default: false)',
|
68
|
+
required: false,
|
69
|
+
default: false
|
70
|
+
|
71
|
+
param :volumes,
|
72
|
+
type: :boolean,
|
73
|
+
description: 'Remove associated volumes (default: false)',
|
74
|
+
required: false,
|
75
|
+
default: false
|
76
|
+
|
77
|
+
execute do |id:, force: false, volumes: false|
|
123
78
|
container = Docker::Container.get(id)
|
124
79
|
container.delete(force: force, v: volumes)
|
125
80
|
|
126
|
-
|
127
|
-
type: 'text',
|
128
|
-
text: "Container #{id} removed successfully"
|
129
|
-
}])
|
81
|
+
"Container #{id} removed successfully"
|
130
82
|
rescue Docker::Error::NotFoundError
|
131
|
-
|
132
|
-
type: 'text',
|
133
|
-
text: "Container #{id} not found"
|
134
|
-
}])
|
83
|
+
"Container #{id} not found"
|
135
84
|
rescue StandardError => e
|
136
|
-
|
137
|
-
type: 'text',
|
138
|
-
text: "Error removing container: #{e.message}"
|
139
|
-
}])
|
85
|
+
"Error removing container: #{e.message}"
|
140
86
|
end
|
141
87
|
end
|
88
|
+
|
89
|
+
RemoveContainer = REMOVE_CONTAINER_DEFINITION.to_mcp_tool
|
142
90
|
end
|