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,161 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for retrieving Docker container logs.
|
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.
|
9
|
+
#
|
10
|
+
# == Features
|
11
|
+
#
|
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
|
25
|
+
#
|
26
|
+
# == Security Considerations
|
27
|
+
#
|
28
|
+
# 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
|
34
|
+
#
|
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
|
41
|
+
#
|
42
|
+
# == Example Usage
|
43
|
+
#
|
44
|
+
# # Get all logs
|
45
|
+
# FetchContainerLogs.call(
|
46
|
+
# server_context: context,
|
47
|
+
# id: "web-server"
|
48
|
+
# )
|
49
|
+
#
|
50
|
+
# # Get recent logs with timestamps
|
51
|
+
# FetchContainerLogs.call(
|
52
|
+
# server_context: context,
|
53
|
+
# 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
|
+
# stdout: false,
|
63
|
+
# stderr: true
|
64
|
+
# )
|
65
|
+
#
|
66
|
+
# @see ExecContainer
|
67
|
+
# @see Docker::Container#logs
|
68
|
+
# @since 0.1.0
|
69
|
+
class FetchContainerLogs < MCP::Tool
|
70
|
+
description 'Fetch Docker container logs'
|
71
|
+
|
72
|
+
input_schema(
|
73
|
+
properties: {
|
74
|
+
id: {
|
75
|
+
type: 'string',
|
76
|
+
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
|
+
|
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)
|
134
|
+
container = Docker::Container.get(id)
|
135
|
+
|
136
|
+
options = {
|
137
|
+
stdout: stdout,
|
138
|
+
stderr: stderr,
|
139
|
+
timestamps: timestamps
|
140
|
+
}
|
141
|
+
options[:tail] = tail if tail
|
142
|
+
|
143
|
+
logs = container.logs(options)
|
144
|
+
|
145
|
+
MCP::Tool::Response.new([{
|
146
|
+
type: 'text',
|
147
|
+
text: logs
|
148
|
+
}])
|
149
|
+
rescue Docker::Error::NotFoundError
|
150
|
+
MCP::Tool::Response.new([{
|
151
|
+
type: 'text',
|
152
|
+
text: "Container #{id} not found"
|
153
|
+
}])
|
154
|
+
rescue StandardError => e
|
155
|
+
MCP::Tool::Response.new([{
|
156
|
+
type: 'text',
|
157
|
+
text: "Error fetching logs: #{e.message}"
|
158
|
+
}])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for listing Docker containers.
|
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.
|
9
|
+
#
|
10
|
+
# == Security Notes
|
11
|
+
#
|
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.
|
15
|
+
#
|
16
|
+
# == Example Usage
|
17
|
+
#
|
18
|
+
# # List all containers (default behavior)
|
19
|
+
# ListContainers.call(server_context: context)
|
20
|
+
#
|
21
|
+
# # Explicitly request all containers
|
22
|
+
# ListContainers.call(server_context: context, all: true)
|
23
|
+
#
|
24
|
+
# @see Docker::Container.all
|
25
|
+
# @since 0.1.0
|
26
|
+
class ListContainers < MCP::Tool
|
27
|
+
description 'List Docker containers'
|
28
|
+
|
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
|
+
)
|
38
|
+
|
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
|
+
}])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for listing Docker images.
|
5
|
+
#
|
6
|
+
# This tool provides functionality to list all Docker images available on
|
7
|
+
# the local system. It returns comprehensive information about each image
|
8
|
+
# including IDs, tags, sizes, creation dates, and other metadata.
|
9
|
+
#
|
10
|
+
# == Features
|
11
|
+
#
|
12
|
+
# - List all local Docker images
|
13
|
+
# - Comprehensive image metadata
|
14
|
+
# - No configuration required
|
15
|
+
# - Read-only operation
|
16
|
+
# - Includes both tagged and untagged images
|
17
|
+
#
|
18
|
+
# == Image Information Included
|
19
|
+
#
|
20
|
+
# The response typically includes:
|
21
|
+
# - **Image ID**: Unique identifier for the image
|
22
|
+
# - **Repository Tags**: All tags associated with the image
|
23
|
+
# - **Size**: Virtual and actual size of the image
|
24
|
+
# - **Created**: Timestamp when image was created
|
25
|
+
# - **Parent ID**: Base image information
|
26
|
+
# - **RepoDigests**: Content-addressable identifiers
|
27
|
+
#
|
28
|
+
# == Security Considerations
|
29
|
+
#
|
30
|
+
# This is a read-only operation that reveals system information:
|
31
|
+
# - Exposes available images and versions
|
32
|
+
# - May reveal internal application details
|
33
|
+
# - Shows image sources and repositories
|
34
|
+
# - Could aid in reconnaissance activities
|
35
|
+
#
|
36
|
+
# While generally safe, consider access control:
|
37
|
+
# - Limit exposure of image inventory
|
38
|
+
# - Be cautious with sensitive image names
|
39
|
+
# - Monitor for unauthorized image access attempts
|
40
|
+
#
|
41
|
+
# == Example Usage
|
42
|
+
#
|
43
|
+
# # List all images
|
44
|
+
# ListImages.call(server_context: context)
|
45
|
+
#
|
46
|
+
# @example Usage in container management
|
47
|
+
# # Get available images before container creation
|
48
|
+
# images_response = ListImages.call(server_context: context)
|
49
|
+
# # Use image information to select appropriate base images
|
50
|
+
#
|
51
|
+
# @see PullImage
|
52
|
+
# @see BuildImage
|
53
|
+
# @see Docker::Image.all
|
54
|
+
# @since 0.1.0
|
55
|
+
class ListImages < MCP::Tool
|
56
|
+
description 'List Docker images'
|
57
|
+
|
58
|
+
# List all Docker images available on the local system.
|
59
|
+
#
|
60
|
+
# This method retrieves information about all Docker images stored
|
61
|
+
# locally, including both tagged and untagged images. The information
|
62
|
+
# includes comprehensive metadata for each image.
|
63
|
+
#
|
64
|
+
# @param args [Array] variable arguments (unused but accepted for compatibility)
|
65
|
+
#
|
66
|
+
# @return [MCP::Tool::Response] comprehensive image information
|
67
|
+
#
|
68
|
+
# @example List all local images
|
69
|
+
# response = ListImages.call
|
70
|
+
# # Returns detailed info for all local Docker images
|
71
|
+
#
|
72
|
+
# @see Docker::Image.all
|
73
|
+
def self.call(*)
|
74
|
+
MCP::Tool::Response.new([{
|
75
|
+
type: 'text',
|
76
|
+
text: Docker::Image.all.map(&:info).to_s
|
77
|
+
}])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for listing Docker networks.
|
5
|
+
#
|
6
|
+
# This tool provides functionality to list all Docker networks available on
|
7
|
+
# the system, including built-in networks (bridge, host, none) and custom
|
8
|
+
# user-defined networks. It returns comprehensive information about network
|
9
|
+
# configuration, drivers, and connected containers.
|
10
|
+
#
|
11
|
+
# == Features
|
12
|
+
#
|
13
|
+
# - List all Docker networks on the system
|
14
|
+
# - Comprehensive network metadata
|
15
|
+
# - No configuration required
|
16
|
+
# - Read-only operation
|
17
|
+
# - Includes built-in and custom networks
|
18
|
+
#
|
19
|
+
# == Network Information Included
|
20
|
+
#
|
21
|
+
# The response typically includes:
|
22
|
+
# - **Network ID**: Unique identifier for the network
|
23
|
+
# - **Name**: Human-readable network name
|
24
|
+
# - **Driver**: Network driver (bridge, host, overlay, etc.)
|
25
|
+
# - **Scope**: Network scope (local, global, swarm)
|
26
|
+
# - **IPAM**: IP Address Management configuration
|
27
|
+
# - **Connected Containers**: Containers attached to the network
|
28
|
+
# - **Options**: Driver-specific configuration options
|
29
|
+
#
|
30
|
+
# == Security Considerations
|
31
|
+
#
|
32
|
+
# This is a read-only operation that reveals network topology:
|
33
|
+
# - Exposes network architecture and segmentation
|
34
|
+
# - Shows container connectivity patterns
|
35
|
+
# - May reveal internal network design
|
36
|
+
# - Could aid in network reconnaissance
|
37
|
+
#
|
38
|
+
# While generally safe, consider access control:
|
39
|
+
# - Limit exposure of network topology information
|
40
|
+
# - Be cautious with sensitive network names
|
41
|
+
# - Monitor for unauthorized network discovery
|
42
|
+
# - Consider network isolation requirements
|
43
|
+
#
|
44
|
+
# == Example Usage
|
45
|
+
#
|
46
|
+
# # List all networks
|
47
|
+
# ListNetworks.call(server_context: context)
|
48
|
+
#
|
49
|
+
# @example Usage in network management
|
50
|
+
# # Get available networks before container creation
|
51
|
+
# networks_response = ListNetworks.call(server_context: context)
|
52
|
+
# # Use network information to select appropriate networks
|
53
|
+
#
|
54
|
+
# @see CreateNetwork
|
55
|
+
# @see RemoveNetwork
|
56
|
+
# @see Docker::Network.all
|
57
|
+
# @since 0.1.0
|
58
|
+
class ListNetworks < MCP::Tool
|
59
|
+
description 'List Docker networks'
|
60
|
+
|
61
|
+
# List all Docker networks available on the system.
|
62
|
+
#
|
63
|
+
# This method retrieves information about all Docker networks, including
|
64
|
+
# both system-created networks (bridge, host, none) and user-defined
|
65
|
+
# custom networks. The information includes comprehensive metadata for
|
66
|
+
# each network.
|
67
|
+
#
|
68
|
+
# @param args [Array] variable arguments (unused but accepted for compatibility)
|
69
|
+
#
|
70
|
+
# @return [MCP::Tool::Response] comprehensive network information
|
71
|
+
#
|
72
|
+
# @example List all networks
|
73
|
+
# response = ListNetworks.call
|
74
|
+
# # Returns detailed info for all Docker networks
|
75
|
+
#
|
76
|
+
# @see Docker::Network.all
|
77
|
+
def self.call(*)
|
78
|
+
MCP::Tool::Response.new([{
|
79
|
+
type: 'text',
|
80
|
+
text: Docker::Network.all.map(&:info).to_s
|
81
|
+
}])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for listing Docker volumes.
|
5
|
+
#
|
6
|
+
# This tool provides functionality to list all Docker volumes on the system,
|
7
|
+
# including both named volumes and anonymous volumes. It returns comprehensive
|
8
|
+
# information about volume configuration, drivers, mount points, and usage.
|
9
|
+
#
|
10
|
+
# == Features
|
11
|
+
#
|
12
|
+
# - List all Docker volumes on the system
|
13
|
+
# - Comprehensive volume metadata
|
14
|
+
# - No configuration required
|
15
|
+
# - Read-only operation
|
16
|
+
# - Includes named and anonymous volumes
|
17
|
+
#
|
18
|
+
# == Volume Information Included
|
19
|
+
#
|
20
|
+
# The response typically includes:
|
21
|
+
# - **Volume Name**: Unique identifier for the volume
|
22
|
+
# - **Driver**: Volume driver (local, nfs, etc.)
|
23
|
+
# - **Mountpoint**: Physical location on host filesystem
|
24
|
+
# - **Labels**: User-defined metadata labels
|
25
|
+
# - **Options**: Driver-specific configuration options
|
26
|
+
# - **Scope**: Volume scope (local, global)
|
27
|
+
# - **CreatedAt**: Volume creation timestamp
|
28
|
+
#
|
29
|
+
# == Volume Types
|
30
|
+
#
|
31
|
+
# Docker manages different types of volumes:
|
32
|
+
# - **Named Volumes**: User-created persistent volumes
|
33
|
+
# - **Anonymous Volumes**: Automatically created temporary volumes
|
34
|
+
# - **Bind Mounts**: Direct host directory mounts (not shown in volume list)
|
35
|
+
# - **tmpfs Mounts**: Memory-based temporary filesystems (not shown)
|
36
|
+
#
|
37
|
+
# == Security Considerations
|
38
|
+
#
|
39
|
+
# This is a read-only operation that reveals storage information:
|
40
|
+
# - Exposes data storage architecture
|
41
|
+
# - Shows volume naming patterns
|
42
|
+
# - May reveal application data locations
|
43
|
+
# - Could aid in data discovery attacks
|
44
|
+
#
|
45
|
+
# While generally safe, consider access control:
|
46
|
+
# - Limit exposure of volume inventory
|
47
|
+
# - Be cautious with sensitive volume names
|
48
|
+
# - Monitor for unauthorized volume discovery
|
49
|
+
# - Consider data classification implications
|
50
|
+
#
|
51
|
+
# == Example Usage
|
52
|
+
#
|
53
|
+
# # List all volumes
|
54
|
+
# ListVolumes.call(server_context: context)
|
55
|
+
#
|
56
|
+
# @example Usage in data management
|
57
|
+
# # Get available volumes before container creation
|
58
|
+
# volumes_response = ListVolumes.call(server_context: context)
|
59
|
+
# # Use volume information to select appropriate storage
|
60
|
+
#
|
61
|
+
# @see CreateVolume
|
62
|
+
# @see RemoveVolume
|
63
|
+
# @see Docker::Volume.all
|
64
|
+
# @since 0.1.0
|
65
|
+
class ListVolumes < MCP::Tool
|
66
|
+
description 'List Docker volumes'
|
67
|
+
|
68
|
+
# List all Docker volumes available on the system.
|
69
|
+
#
|
70
|
+
# This method retrieves information about all Docker volumes, including
|
71
|
+
# both named volumes created by users and anonymous volumes created
|
72
|
+
# automatically by containers. The information includes comprehensive
|
73
|
+
# metadata for each volume.
|
74
|
+
#
|
75
|
+
# @param args [Array] variable arguments (unused but accepted for compatibility)
|
76
|
+
#
|
77
|
+
# @return [MCP::Tool::Response] comprehensive volume information
|
78
|
+
#
|
79
|
+
# @example List all volumes
|
80
|
+
# response = ListVolumes.call
|
81
|
+
# # Returns detailed info for all Docker volumes
|
82
|
+
#
|
83
|
+
# @see Docker::Volume.all
|
84
|
+
def self.call(*)
|
85
|
+
MCP::Tool::Response.new([{
|
86
|
+
type: 'text',
|
87
|
+
text: Docker::Volume.all.map(&:info).to_s
|
88
|
+
}])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DockerMCP
|
4
|
+
# MCP tool for pulling Docker images from registries.
|
5
|
+
#
|
6
|
+
# This tool provides the ability to download Docker images from Docker
|
7
|
+
# registries (like Docker Hub) to the local system. It supports flexible
|
8
|
+
# tag specification and handles various image naming conventions.
|
9
|
+
#
|
10
|
+
# == Features
|
11
|
+
#
|
12
|
+
# - Pull images from any accessible Docker registry
|
13
|
+
# - Flexible tag specification (explicit or default)
|
14
|
+
# - Support for official and user repositories
|
15
|
+
# - Automatic latest tag handling
|
16
|
+
# - Comprehensive error handling
|
17
|
+
# - Progress tracking through Docker daemon
|
18
|
+
#
|
19
|
+
# == Security Considerations
|
20
|
+
#
|
21
|
+
# Pulling images can introduce security risks:
|
22
|
+
# - **Malicious Images**: Images may contain malware or backdoors
|
23
|
+
# - **Vulnerable Software**: Images may have known security vulnerabilities
|
24
|
+
# - **Untrusted Sources**: Images from unknown publishers may be compromised
|
25
|
+
# - **Supply Chain Attacks**: Legitimate-looking images may be malicious
|
26
|
+
# - **Resource Consumption**: Large images can consume significant disk space
|
27
|
+
#
|
28
|
+
# Security recommendations:
|
29
|
+
# - Only pull images from trusted registries and publishers
|
30
|
+
# - Verify image signatures when available
|
31
|
+
# - Scan pulled images for vulnerabilities
|
32
|
+
# - Use specific tags rather than 'latest'
|
33
|
+
# - Monitor registry access and authentication
|
34
|
+
# - Regularly update and patch images
|
35
|
+
#
|
36
|
+
# == Tag Handling
|
37
|
+
#
|
38
|
+
# The tool handles tags intelligently:
|
39
|
+
# - If image includes tag (e.g., "nginx:1.21"), use as specified
|
40
|
+
# - If separate tag provided, append to image name
|
41
|
+
# - If no tag specified, default to "latest"
|
42
|
+
# - Supports all Docker tag conventions
|
43
|
+
#
|
44
|
+
# == Example Usage
|
45
|
+
#
|
46
|
+
# # Pull latest version
|
47
|
+
# PullImage.call(
|
48
|
+
# server_context: context,
|
49
|
+
# from_image: "nginx"
|
50
|
+
# )
|
51
|
+
#
|
52
|
+
# # Pull specific version
|
53
|
+
# PullImage.call(
|
54
|
+
# server_context: context,
|
55
|
+
# from_image: "postgres:13"
|
56
|
+
# )
|
57
|
+
#
|
58
|
+
# # Pull with separate tag parameter
|
59
|
+
# PullImage.call(
|
60
|
+
# server_context: context,
|
61
|
+
# from_image: "redis",
|
62
|
+
# tag: "7-alpine"
|
63
|
+
# )
|
64
|
+
#
|
65
|
+
# @see BuildImage
|
66
|
+
# @see ListImages
|
67
|
+
# @see Docker::Image.create
|
68
|
+
# @since 0.1.0
|
69
|
+
class PullImage < MCP::Tool
|
70
|
+
description 'Pull a Docker image'
|
71
|
+
|
72
|
+
input_schema(
|
73
|
+
properties: {
|
74
|
+
from_image: {
|
75
|
+
type: 'string',
|
76
|
+
description: 'Image name to pull (e.g., "ubuntu" or "ubuntu:22.04")'
|
77
|
+
},
|
78
|
+
tag: {
|
79
|
+
type: 'string',
|
80
|
+
description: 'Tag to pull (optional, defaults to "latest" if not specified in from_image)'
|
81
|
+
}
|
82
|
+
},
|
83
|
+
required: ['from_image']
|
84
|
+
)
|
85
|
+
|
86
|
+
# Pull a Docker image from a registry.
|
87
|
+
#
|
88
|
+
# This method downloads the specified image from a Docker registry to
|
89
|
+
# the local system. It handles tag resolution automatically and provides
|
90
|
+
# feedback on the pull operation status.
|
91
|
+
#
|
92
|
+
# @param from_image [String] image name (may include registry and tag)
|
93
|
+
# @param server_context [Object] MCP server context (unused but required)
|
94
|
+
# @param tag [String, nil] specific tag to pull (overrides tag in from_image)
|
95
|
+
#
|
96
|
+
# @return [MCP::Tool::Response] pull operation results with image ID
|
97
|
+
#
|
98
|
+
# @raise [Docker::Error::NotFoundError] if image doesn't exist in registry
|
99
|
+
# @raise [StandardError] for network or authentication failures
|
100
|
+
#
|
101
|
+
# @example Pull official image
|
102
|
+
# response = PullImage.call(
|
103
|
+
# server_context: context,
|
104
|
+
# from_image: "ubuntu:22.04"
|
105
|
+
# )
|
106
|
+
#
|
107
|
+
# @example Pull from custom registry
|
108
|
+
# response = PullImage.call(
|
109
|
+
# server_context: context,
|
110
|
+
# from_image: "registry.example.com/myapp",
|
111
|
+
# tag: "v1.0"
|
112
|
+
# )
|
113
|
+
#
|
114
|
+
# @see Docker::Image.create
|
115
|
+
def self.call(from_image:, server_context:, tag: nil)
|
116
|
+
# If tag is provided separately, append it to from_image
|
117
|
+
# If from_image already has a tag (contains :), use as-is
|
118
|
+
# Otherwise default to :latest
|
119
|
+
image_with_tag = if tag
|
120
|
+
"#{from_image}:#{tag}"
|
121
|
+
elsif from_image.include?(':')
|
122
|
+
from_image
|
123
|
+
else
|
124
|
+
"#{from_image}:latest"
|
125
|
+
end
|
126
|
+
|
127
|
+
image = Docker::Image.create('fromImage' => image_with_tag)
|
128
|
+
|
129
|
+
MCP::Tool::Response.new([{
|
130
|
+
type: 'text',
|
131
|
+
text: "Image #{image_with_tag} pulled successfully. ID: #{image.id}"
|
132
|
+
}])
|
133
|
+
rescue Docker::Error::NotFoundError
|
134
|
+
MCP::Tool::Response.new([{
|
135
|
+
type: 'text',
|
136
|
+
text: "Image #{image_with_tag} not found"
|
137
|
+
}])
|
138
|
+
rescue StandardError => e
|
139
|
+
MCP::Tool::Response.new([{
|
140
|
+
type: 'text',
|
141
|
+
text: "Error pulling image: #{e.message}"
|
142
|
+
}])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|