docker_mcp 0.0.1 → 0.2.5
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/LICENSE.txt +21 -0
- data/README.md +246 -10
- data/Rakefile +3 -3
- data/examples/.keep +0 -0
- data/exe/docker_mcp +8 -0
- data/lib/docker_mcp/build_image.rb +127 -0
- data/lib/docker_mcp/copy_to_container.rb +223 -0
- data/lib/docker_mcp/create_container.rb +174 -0
- data/lib/docker_mcp/create_network.rb +152 -0
- data/lib/docker_mcp/create_volume.rb +148 -0
- data/lib/docker_mcp/exec_container.rb +219 -0
- data/lib/docker_mcp/fetch_container_logs.rb +161 -0
- data/lib/docker_mcp/list_containers.rb +66 -0
- data/lib/docker_mcp/list_images.rb +80 -0
- data/lib/docker_mcp/list_networks.rb +84 -0
- data/lib/docker_mcp/list_volumes.rb +91 -0
- data/lib/docker_mcp/pull_image.rb +145 -0
- data/lib/docker_mcp/push_image.rb +179 -0
- data/lib/docker_mcp/recreate_container.rb +168 -0
- data/lib/docker_mcp/remove_container.rb +142 -0
- data/lib/docker_mcp/remove_image.rb +164 -0
- data/lib/docker_mcp/remove_network.rb +136 -0
- data/lib/docker_mcp/remove_volume.rb +146 -0
- data/lib/docker_mcp/run_container.rb +132 -0
- data/lib/docker_mcp/server.rb +108 -0
- data/lib/docker_mcp/start_container.rb +112 -0
- data/lib/docker_mcp/stop_container.rb +126 -0
- data/lib/docker_mcp/tag_image.rb +163 -0
- data/lib/docker_mcp/version.rb +11 -2
- data/lib/docker_mcp.rb +64 -3
- data/sig/docker_mcp.rbs +1 -1
- metadata +63 -6
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for stopping running Docker containers.
|
5
|
+
#
|
6
|
+
# This tool provides the ability to gracefully stop running Docker containers
|
7
|
+
# with configurable timeout handling. It sends a SIGTERM signal to the main
|
8
|
+
# process and waits for the specified timeout before forcibly killing the
|
9
|
+
# container with SIGKILL.
|
10
|
+
#
|
11
|
+
# == Features
|
12
|
+
#
|
13
|
+
# - Graceful container shutdown with SIGTERM
|
14
|
+
# - Configurable timeout before force kill
|
15
|
+
# - Works with containers by ID or name
|
16
|
+
# - Comprehensive error handling
|
17
|
+
# - Safe for already stopped containers
|
18
|
+
#
|
19
|
+
# == Shutdown Process
|
20
|
+
#
|
21
|
+
# 1. Send SIGTERM to container's main process
|
22
|
+
# 2. Wait for graceful shutdown up to timeout
|
23
|
+
# 3. Send SIGKILL if container hasn't stopped
|
24
|
+
# 4. Return success when container is stopped
|
25
|
+
#
|
26
|
+
# == Security Considerations
|
27
|
+
#
|
28
|
+
# Stopping containers affects service availability:
|
29
|
+
# - Services become unavailable immediately
|
30
|
+
# - Network connections are terminated
|
31
|
+
# - Data may be lost if not properly persisted
|
32
|
+
# - Dependent services may be affected
|
33
|
+
#
|
34
|
+
# Best practices:
|
35
|
+
# - Ensure data persistence before stopping
|
36
|
+
# - Consider impact on dependent services
|
37
|
+
# - Use appropriate timeout for graceful shutdown
|
38
|
+
# - Monitor application logs during shutdown
|
39
|
+
#
|
40
|
+
# == Example Usage
|
41
|
+
#
|
42
|
+
# # Stop with default timeout (10 seconds)
|
43
|
+
# StopContainer.call(
|
44
|
+
# server_context: context,
|
45
|
+
# id: "web-server"
|
46
|
+
# )
|
47
|
+
#
|
48
|
+
# # Stop with custom timeout
|
49
|
+
# StopContainer.call(
|
50
|
+
# server_context: context,
|
51
|
+
# id: "database",
|
52
|
+
# timeout: 30
|
53
|
+
# )
|
54
|
+
#
|
55
|
+
# @see StartContainer
|
56
|
+
# @see RemoveContainer
|
57
|
+
# @see Docker::Container#stop
|
58
|
+
# @since 0.1.0
|
59
|
+
class StopContainer < MCP::Tool
|
60
|
+
description 'Stop a Docker container'
|
61
|
+
|
62
|
+
input_schema(
|
63
|
+
properties: {
|
64
|
+
id: {
|
65
|
+
type: 'string',
|
66
|
+
description: 'Container ID or name'
|
67
|
+
},
|
68
|
+
timeout: {
|
69
|
+
type: 'integer',
|
70
|
+
description: 'Seconds to wait before killing the container (default: 10)'
|
71
|
+
}
|
72
|
+
},
|
73
|
+
required: ['id']
|
74
|
+
)
|
75
|
+
|
76
|
+
# Stop a running Docker container gracefully.
|
77
|
+
#
|
78
|
+
# This method stops a container by sending SIGTERM to the main process
|
79
|
+
# and waiting for the specified timeout before sending SIGKILL. The
|
80
|
+
# operation is idempotent - stopping an already stopped container
|
81
|
+
# typically succeeds without error.
|
82
|
+
#
|
83
|
+
# @param id [String] container ID (full or short) or container name
|
84
|
+
# @param server_context [Object] MCP server context (unused but required)
|
85
|
+
# @param timeout [Integer] seconds to wait before force killing (default: 10)
|
86
|
+
#
|
87
|
+
# @return [MCP::Tool::Response] stop operation results
|
88
|
+
#
|
89
|
+
# @raise [Docker::Error::NotFoundError] if container doesn't exist
|
90
|
+
# @raise [StandardError] for other stop failures
|
91
|
+
#
|
92
|
+
# @example Stop with default timeout
|
93
|
+
# response = StopContainer.call(
|
94
|
+
# server_context: context,
|
95
|
+
# id: "nginx-server"
|
96
|
+
# )
|
97
|
+
#
|
98
|
+
# @example Stop database with longer timeout
|
99
|
+
# response = StopContainer.call(
|
100
|
+
# server_context: context,
|
101
|
+
# id: "postgres-db",
|
102
|
+
# timeout: 60 # Allow more time for DB shutdown
|
103
|
+
# )
|
104
|
+
#
|
105
|
+
# @see Docker::Container#stop
|
106
|
+
def self.call(id:, server_context:, timeout: 10)
|
107
|
+
container = Docker::Container.get(id)
|
108
|
+
container.stop('timeout' => timeout)
|
109
|
+
|
110
|
+
MCP::Tool::Response.new([{
|
111
|
+
type: 'text',
|
112
|
+
text: "Container #{id} stopped successfully"
|
113
|
+
}])
|
114
|
+
rescue Docker::Error::NotFoundError
|
115
|
+
MCP::Tool::Response.new([{
|
116
|
+
type: 'text',
|
117
|
+
text: "Container #{id} not found"
|
118
|
+
}])
|
119
|
+
rescue StandardError => e
|
120
|
+
MCP::Tool::Response.new([{
|
121
|
+
type: 'text',
|
122
|
+
text: "Error stopping container: #{e.message}"
|
123
|
+
}])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for tagging Docker images.
|
5
|
+
#
|
6
|
+
# This tool provides the ability to create new tags for existing Docker images,
|
7
|
+
# enabling better organization, versioning, and distribution of images. Tags
|
8
|
+
# are essential for image management and registry operations.
|
9
|
+
#
|
10
|
+
# == Features
|
11
|
+
#
|
12
|
+
# - Tag images by ID or existing name
|
13
|
+
# - Support for repository and tag specification
|
14
|
+
# - Force tagging to overwrite existing tags
|
15
|
+
# - Registry-compatible tag formatting
|
16
|
+
# - Comprehensive error handling
|
17
|
+
# - Multiple tags per image support
|
18
|
+
#
|
19
|
+
# == Tag Management Benefits
|
20
|
+
#
|
21
|
+
# Proper tagging enables:
|
22
|
+
# - **Version Control**: Track different image versions
|
23
|
+
# - **Distribution**: Prepare images for registry push
|
24
|
+
# - **Organization**: Group related images logically
|
25
|
+
# - **Deployment**: Reference specific image versions
|
26
|
+
# - **Rollback**: Maintain previous versions for rollback
|
27
|
+
#
|
28
|
+
# == Security Considerations
|
29
|
+
#
|
30
|
+
# Tagging affects image accessibility and distribution:
|
31
|
+
# - Tags determine registry push destinations
|
32
|
+
# - Overwriting tags can affect running containers
|
33
|
+
# - Registry-compatible tags expose images for distribution
|
34
|
+
# - Tag names may reveal application details
|
35
|
+
#
|
36
|
+
# Best practices:
|
37
|
+
# - Use descriptive but not sensitive tag names
|
38
|
+
# - Avoid overwriting production tags accidentally
|
39
|
+
# - Implement tag naming conventions
|
40
|
+
# - Regular cleanup of unused tags
|
41
|
+
# - Control access to critical tag operations
|
42
|
+
#
|
43
|
+
# == Tag Naming Conventions
|
44
|
+
#
|
45
|
+
# Recommended patterns:
|
46
|
+
# - **Semantic Versioning**: `v1.2.3`, `1.2.3-alpha`
|
47
|
+
# - **Environment Tags**: `prod`, `staging`, `dev`
|
48
|
+
# - **Feature Tags**: `feature-branch-name`
|
49
|
+
# - **Date Tags**: `2024-01-15`, `20240115`
|
50
|
+
# - **Commit Tags**: `sha-abc123def`
|
51
|
+
#
|
52
|
+
# == Example Usage
|
53
|
+
#
|
54
|
+
# # Tag with version
|
55
|
+
# TagImage.call(
|
56
|
+
# server_context: context,
|
57
|
+
# id: "abc123def456",
|
58
|
+
# repo: "myapp",
|
59
|
+
# tag: "v1.0.0"
|
60
|
+
# )
|
61
|
+
#
|
62
|
+
# # Tag for registry push
|
63
|
+
# TagImage.call(
|
64
|
+
# server_context: context,
|
65
|
+
# id: "myapp:latest",
|
66
|
+
# repo: "myusername/myapp",
|
67
|
+
# tag: "production"
|
68
|
+
# )
|
69
|
+
#
|
70
|
+
# # Tag for private registry
|
71
|
+
# TagImage.call(
|
72
|
+
# server_context: context,
|
73
|
+
# id: "webapp:dev",
|
74
|
+
# repo: "registry.company.com/team/webapp",
|
75
|
+
# tag: "v2.1.0"
|
76
|
+
# )
|
77
|
+
#
|
78
|
+
# @see BuildImage
|
79
|
+
# @see PushImage
|
80
|
+
# @see Docker::Image#tag
|
81
|
+
# @since 0.1.0
|
82
|
+
class TagImage < MCP::Tool
|
83
|
+
description 'Tag a Docker image'
|
84
|
+
|
85
|
+
input_schema(
|
86
|
+
properties: {
|
87
|
+
id: {
|
88
|
+
type: 'string',
|
89
|
+
description: 'Image ID or current name:tag'
|
90
|
+
},
|
91
|
+
repo: {
|
92
|
+
type: 'string',
|
93
|
+
description: 'Repository name (e.g., "username/imagename" or "registry/username/imagename")'
|
94
|
+
},
|
95
|
+
tag: {
|
96
|
+
type: 'string',
|
97
|
+
description: 'Tag for the image (default: "latest")'
|
98
|
+
},
|
99
|
+
force: {
|
100
|
+
type: 'boolean',
|
101
|
+
description: 'Force tag even if it already exists (default: true)'
|
102
|
+
}
|
103
|
+
},
|
104
|
+
required: %w[id repo]
|
105
|
+
)
|
106
|
+
|
107
|
+
# Tag a Docker image with a new repository and tag name.
|
108
|
+
#
|
109
|
+
# This method creates a new tag for an existing image, allowing it to
|
110
|
+
# be referenced by the new name. This is essential for organizing images
|
111
|
+
# and preparing them for registry distribution.
|
112
|
+
#
|
113
|
+
# @param id [String] image ID or current name:tag to tag
|
114
|
+
# @param repo [String] repository name for the new tag
|
115
|
+
# @param server_context [Object] MCP server context (unused but required)
|
116
|
+
# @param tag [String] tag name for the image (default: "latest")
|
117
|
+
# @param force [Boolean] whether to overwrite existing tags (default: true)
|
118
|
+
#
|
119
|
+
# @return [MCP::Tool::Response] tagging operation results
|
120
|
+
#
|
121
|
+
# @raise [Docker::Error::NotFoundError] if source image doesn't exist
|
122
|
+
# @raise [StandardError] for other tagging failures
|
123
|
+
#
|
124
|
+
# @example Tag for versioning
|
125
|
+
# response = TagImage.call(
|
126
|
+
# server_context: context,
|
127
|
+
# id: "my-app:latest",
|
128
|
+
# repo: "my-app",
|
129
|
+
# tag: "v1.2.3"
|
130
|
+
# )
|
131
|
+
#
|
132
|
+
# @example Tag for registry push
|
133
|
+
# response = TagImage.call(
|
134
|
+
# server_context: context,
|
135
|
+
# id: "abc123def456",
|
136
|
+
# repo: "myregistry.com/myuser/myapp",
|
137
|
+
# tag: "production",
|
138
|
+
# force: true
|
139
|
+
# )
|
140
|
+
#
|
141
|
+
# @see Docker::Image#tag
|
142
|
+
def self.call(id:, repo:, server_context:, tag: 'latest', force: true)
|
143
|
+
image = Docker::Image.get(id)
|
144
|
+
|
145
|
+
image.tag('repo' => repo, 'tag' => tag, 'force' => force)
|
146
|
+
|
147
|
+
MCP::Tool::Response.new([{
|
148
|
+
type: 'text',
|
149
|
+
text: "Image tagged successfully as #{repo}:#{tag}"
|
150
|
+
}])
|
151
|
+
rescue Docker::Error::NotFoundError
|
152
|
+
MCP::Tool::Response.new([{
|
153
|
+
type: 'text',
|
154
|
+
text: "Image #{id} not found"
|
155
|
+
}])
|
156
|
+
rescue StandardError => e
|
157
|
+
MCP::Tool::Response.new([{
|
158
|
+
type: 'text',
|
159
|
+
text: "Error tagging image: #{e.message}"
|
160
|
+
}])
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
data/lib/docker_mcp/version.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module
|
4
|
-
|
3
|
+
module DockerMCP
|
4
|
+
# Current version of the DockerMCP gem.
|
5
|
+
#
|
6
|
+
# This constant follows semantic versioning (SemVer) principles:
|
7
|
+
# - MAJOR version for incompatible API changes
|
8
|
+
# - MINOR version for backwards-compatible functionality additions
|
9
|
+
# - PATCH version for backwards-compatible bug fixes
|
10
|
+
#
|
11
|
+
# @see https://semver.org/
|
12
|
+
# @since 0.1.0
|
13
|
+
VERSION = '0.2.5'
|
5
14
|
end
|
data/lib/docker_mcp.rb
CHANGED
@@ -1,8 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'docker'
|
4
|
+
require 'json'
|
5
|
+
require 'mcp'
|
6
|
+
require 'rubygems/package'
|
7
|
+
require 'shellwords'
|
8
|
+
require 'stringio'
|
9
|
+
require 'zeitwerk'
|
4
10
|
|
5
|
-
|
11
|
+
loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
|
12
|
+
loader.inflector.inflect('docker_mcp' => 'DockerMCP')
|
13
|
+
loader.setup # ready!
|
14
|
+
|
15
|
+
require_relative 'docker_mcp/version'
|
16
|
+
|
17
|
+
# DockerMCP provides a Model Context Protocol (MCP) server for comprehensive Docker management.
|
18
|
+
#
|
19
|
+
# This module serves as the main namespace for all Docker MCP functionality, providing tools
|
20
|
+
# to interact with Docker containers, images, networks, and volumes through a standardized
|
21
|
+
# MCP interface. It enables AI assistants and other MCP clients to perform Docker operations
|
22
|
+
# programmatically.
|
23
|
+
#
|
24
|
+
# == Security Warning
|
25
|
+
#
|
26
|
+
# This tool provides powerful capabilities that can be potentially dangerous:
|
27
|
+
# - Execute arbitrary commands inside containers
|
28
|
+
# - Access and modify container filesystems
|
29
|
+
# - Create, modify, and delete Docker resources
|
30
|
+
#
|
31
|
+
# Use with caution and ensure proper security measures are in place.
|
32
|
+
#
|
33
|
+
# == Example Usage
|
34
|
+
#
|
35
|
+
# # Initialize the MCP server
|
36
|
+
# server = DockerMCP::Server.new
|
37
|
+
#
|
38
|
+
# # The server provides access to 22 Docker management tools:
|
39
|
+
# # - Container management (create, run, start, stop, remove, etc.)
|
40
|
+
# # - Image management (pull, build, tag, push, remove)
|
41
|
+
# # - Network management (create, list, remove)
|
42
|
+
# # - Volume management (create, list, remove)
|
43
|
+
#
|
44
|
+
# == Dependencies
|
45
|
+
#
|
46
|
+
# Requires:
|
47
|
+
# - Docker Engine installed and running
|
48
|
+
# - Ruby 3.2+
|
49
|
+
# - docker-api gem for Docker interactions
|
50
|
+
# - mcp gem for Model Context Protocol support
|
51
|
+
#
|
52
|
+
# @see https://github.com/afstanton/docker_mcp
|
53
|
+
# @since 0.1.0
|
54
|
+
module DockerMCP
|
55
|
+
# Base error class for all DockerMCP-specific errors.
|
56
|
+
#
|
57
|
+
# This error class serves as the parent for any custom exceptions
|
58
|
+
# that may be raised by DockerMCP operations. It inherits from
|
59
|
+
# StandardError to maintain compatibility with standard Ruby
|
60
|
+
# error handling patterns.
|
61
|
+
#
|
62
|
+
# @example Rescue DockerMCP errors
|
63
|
+
# begin
|
64
|
+
# # DockerMCP operations
|
65
|
+
# rescue DockerMCP::Error => e
|
66
|
+
# puts "DockerMCP error: #{e.message}"
|
67
|
+
# end
|
6
68
|
class Error < StandardError; end
|
7
|
-
# Your code goes here...
|
8
69
|
end
|
data/sig/docker_mcp.rbs
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: docker_mcp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron F Stanton
|
@@ -9,6 +9,20 @@ bindir: exe
|
|
9
9
|
cert_chain: []
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
|
+
- !ruby/object:Gem::Dependency
|
13
|
+
name: base64
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - ">="
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: '0'
|
19
|
+
type: :runtime
|
20
|
+
prerelease: false
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
requirements:
|
23
|
+
- - ">="
|
24
|
+
- !ruby/object:Gem::Version
|
25
|
+
version: '0'
|
12
26
|
- !ruby/object:Gem::Dependency
|
13
27
|
name: docker-api
|
14
28
|
requirement: !ruby/object:Gem::Requirement
|
@@ -37,25 +51,68 @@ dependencies:
|
|
37
51
|
- - ">="
|
38
52
|
- !ruby/object:Gem::Version
|
39
53
|
version: '0'
|
40
|
-
|
41
|
-
|
54
|
+
- !ruby/object:Gem::Dependency
|
55
|
+
name: zeitwerk
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
type: :runtime
|
62
|
+
prerelease: false
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
description: This gem provides tools to manage Docker containers and images using
|
69
|
+
MCP.
|
42
70
|
email:
|
43
71
|
- afstanton@gmail.com
|
44
|
-
executables:
|
72
|
+
executables:
|
73
|
+
- docker_mcp
|
45
74
|
extensions: []
|
46
75
|
extra_rdoc_files: []
|
47
76
|
files:
|
77
|
+
- LICENSE.txt
|
48
78
|
- README.md
|
49
79
|
- Rakefile
|
80
|
+
- examples/.keep
|
81
|
+
- exe/docker_mcp
|
50
82
|
- lib/docker_mcp.rb
|
83
|
+
- lib/docker_mcp/build_image.rb
|
84
|
+
- lib/docker_mcp/copy_to_container.rb
|
85
|
+
- lib/docker_mcp/create_container.rb
|
86
|
+
- lib/docker_mcp/create_network.rb
|
87
|
+
- lib/docker_mcp/create_volume.rb
|
88
|
+
- lib/docker_mcp/exec_container.rb
|
89
|
+
- lib/docker_mcp/fetch_container_logs.rb
|
90
|
+
- lib/docker_mcp/list_containers.rb
|
91
|
+
- lib/docker_mcp/list_images.rb
|
92
|
+
- lib/docker_mcp/list_networks.rb
|
93
|
+
- lib/docker_mcp/list_volumes.rb
|
94
|
+
- lib/docker_mcp/pull_image.rb
|
95
|
+
- lib/docker_mcp/push_image.rb
|
96
|
+
- lib/docker_mcp/recreate_container.rb
|
97
|
+
- lib/docker_mcp/remove_container.rb
|
98
|
+
- lib/docker_mcp/remove_image.rb
|
99
|
+
- lib/docker_mcp/remove_network.rb
|
100
|
+
- lib/docker_mcp/remove_volume.rb
|
101
|
+
- lib/docker_mcp/run_container.rb
|
102
|
+
- lib/docker_mcp/server.rb
|
103
|
+
- lib/docker_mcp/start_container.rb
|
104
|
+
- lib/docker_mcp/stop_container.rb
|
105
|
+
- lib/docker_mcp/tag_image.rb
|
51
106
|
- lib/docker_mcp/version.rb
|
52
107
|
- sig/docker_mcp.rbs
|
53
108
|
homepage: https://github.com/afstanton/docker_mcp
|
54
|
-
licenses:
|
109
|
+
licenses:
|
110
|
+
- MIT
|
55
111
|
metadata:
|
56
112
|
allowed_push_host: https://rubygems.org
|
57
113
|
homepage_uri: https://github.com/afstanton/docker_mcp
|
58
114
|
source_code_uri: https://github.com/afstanton/docker_mcp
|
115
|
+
rubygems_mfa_required: 'true'
|
59
116
|
rdoc_options: []
|
60
117
|
require_paths:
|
61
118
|
- lib
|
@@ -72,5 +129,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
129
|
requirements: []
|
73
130
|
rubygems_version: 3.7.2
|
74
131
|
specification_version: 4
|
75
|
-
summary:
|
132
|
+
summary: A gem to manage Docker via MCP.
|
76
133
|
test_files: []
|