Skip to content

Commit e427caa

Browse files
committed
feat: add sandbox_stop tool for managing container lifecycle
- Introduce `sandbox_stop` tool to stop and remove running container sandboxes. - Update README.md to document the new tool and its parameters. - Implement functionality in `stop-container.go` to handle container stopping and removal with error handling.
1 parent 4c42291 commit e427caa

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,15 @@ Copy a single file to the sandboxed filesystem.
9595
- `local_src_file` (string, required): Path to a file in the local file system
9696
- `dest_path` (string, optional): Path to save the file in the sandbox environment
9797

98+
#### `sandbox_stop`
99+
Stop and remove a running container sandbox.
100+
101+
**Parameters:**
102+
- `container_id` (string, required): ID of the container to stop and remove
103+
104+
**Description:**
105+
Gracefully stops the specified container with a 10-second timeout and removes it along with its volumes.
106+
98107
#### Container Logs Resource
99108
A dynamic resource that provides access to container logs.
100109

src/code-sandbox-mcp/main.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ func main() {
142142
),
143143
)
144144

145+
// Stop and remove a container
146+
stopContainerTool := mcp.NewTool("sandbox_stop",
147+
mcp.WithDescription(
148+
"Stop and remove a running container sandbox. \n"+
149+
"Gracefully stops the specified container and removes it along with its volumes.",
150+
),
151+
mcp.WithString("container_id",
152+
mcp.Required(),
153+
mcp.Description("ID of the container to stop and remove"),
154+
),
155+
)
156+
145157
// Register dynamic resource for container logs
146158
// Dynamic resource example - Container Logs by ID
147159
containerLogsTemplate := mcp.NewResourceTemplate(
@@ -158,6 +170,7 @@ func main() {
158170
s.AddTool(writeFileTool, tools.WriteFile)
159171
s.AddTool(execTool, tools.Exec)
160172
s.AddTool(copyFileTool, tools.CopyFile)
173+
s.AddTool(stopContainerTool, tools.StopContainer)
161174
switch *transport {
162175
case "stdio":
163176
if err := server.ServeStdio(s); err != nil {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package tools
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/docker/docker/api/types/container"
8+
"github.com/docker/docker/client"
9+
"github.com/mark3labs/mcp-go/mcp"
10+
)
11+
12+
// StopContainer stops and removes a container by its ID
13+
func StopContainer(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
14+
// Get the container ID from the request
15+
containerId, ok := request.Params.Arguments["container_id"].(string)
16+
if !ok || containerId == "" {
17+
return mcp.NewToolResultText("Error: container_id is required"), nil
18+
}
19+
20+
// Stop and remove the container
21+
if err := stopAndRemoveContainer(ctx, containerId); err != nil {
22+
return mcp.NewToolResultText(fmt.Sprintf("Error: %v", err)), nil
23+
}
24+
25+
return mcp.NewToolResultText(fmt.Sprintf("Successfully stopped and removed container: %s", containerId)), nil
26+
}
27+
28+
// stopAndRemoveContainer stops and removes a Docker container
29+
func stopAndRemoveContainer(ctx context.Context, containerId string) error {
30+
cli, err := client.NewClientWithOpts(
31+
client.FromEnv,
32+
client.WithAPIVersionNegotiation(),
33+
)
34+
if err != nil {
35+
return fmt.Errorf("failed to create Docker client: %w", err)
36+
}
37+
defer cli.Close()
38+
39+
// Stop the container with a timeout
40+
timeout := 10 // seconds
41+
if err := cli.ContainerStop(ctx, containerId, container.StopOptions{Timeout: &timeout}); err != nil {
42+
return fmt.Errorf("failed to stop container: %w", err)
43+
}
44+
45+
// Remove the container
46+
if err := cli.ContainerRemove(ctx, containerId, container.RemoveOptions{
47+
RemoveVolumes: true,
48+
Force: true,
49+
}); err != nil {
50+
return fmt.Errorf("failed to remove container: %w", err)
51+
}
52+
53+
return nil
54+
}

0 commit comments

Comments
 (0)