README.md•7.63 kB
# MCP Docker Server
A Python-based MCP (Model Context Protocol) server that provides secure Docker command execution for language models or other clients running in isolated environments like containers.
## Overview
This MCP server runs on a host system and provides access to its Docker daemon via the MCP protocol. It implements security filtering and command validation to ensure safe operation, only allowing `docker` and `docker-compose` commands to be executed.
## Features
- **Docker Command Execution**: Executes `docker` and `docker-compose` commands on the host.
- **Docker Compose Support**: Handles both legacy `docker-compose` and modern `docker compose` syntax.
- **Security Validation**: An explicit allowlist restricts executable commands to `docker` and `docker-compose` only.
- **Async I/O**: Built with `asyncio` for non-blocking command execution.
- **Multiple Transports**: Supports `stdio`, `sse`, and `streamable-http` MCP transports.
- **Rich Toolset**: Provides specific tools for common operations like listing containers, images, and checking system info.
- **Error Handling**: Returns detailed error messages for failed commands.
## Architecture
```
┌─────────────────┐    MCP Protocol     ┌──────────────┐
│ Client          │ ─────────────────► │ MCP Server   │
│ (e.g. Container)│                     │ (Host)       │
│                 │ ◄─────────────────  │              │
│ - Calls Tools   │    Command Results  │ - Docker CLI │
└─────────────────┘                     │ - Security   │
                                        └──────────────┘
                                               │
                                               ▼
                                        ┌──────────────┐
                                        │ Docker Daemon│
                                        │ (Host)       │
                                        └──────────────┘
```
## Installation
1.  **Python**: Requires Python 3.12 or newer.
2.  **Docker**: Docker must be installed and the daemon must be running on the host system.
3.  **Dependencies**: Install the required Python packages using `uv` or `pip` from `pyproject.toml`.
    ```bash
    # Using uv
    uv pip install -r requirements.txt
    # Or directly from the pyproject.toml
    uv pip install .
    ```
## Usage
### Starting the Server
The server can be started with different MCP transports.
```bash
# Start with the default stdio transport
uv run main.py
# Start with the Streamable HTTP transport
uv run main.py streamable-http
# Start with the SSE (Server-Sent Events) transport
uv run main.py sse
```
### Environment Variables
Configure the server's network binding with these environment variables.
-   `FASTMCP_HOST`: Server bind address (default: `0.0.0.0` for container access).
-   `FASTMCP_PORT`: Server port (default: `3000`).
You can create a `.env` file to manage these variables:
```
FASTMCP_HOST=0.0.0.0
FASTMCP_PORT=3000
```
Then run the server with:
```bash
# Example with a custom .env file
uv run --env-file=.env main.py streamable-http
```
## MCP Protocol
The server uses the `mcp` library to expose tools. The available transports are `stdio`, `sse`, and `streamable-http`.
### Available Methods (Tools)
The following tools are exposed by the server:
-   `execute_docker_command(command: str, working_directory: str = None) -> str`
    -   **Description**: Executes a general Docker or Docker Compose command. The command is validated against an allowlist.
    -   **Example**: `session.call_tool("execute_docker_command", {"command": "docker ps -a"})`
-   `docker_system_info() -> str`
    -   **Description**: Retrieves Docker version and system disk usage information.
    -   **Example**: `session.call_tool("docker_system_info", {})`
-   `list_containers(all: bool = False) -> str`
    -   **Description**: Lists Docker containers.
    -   **Args**: `all` (boolean) - If true, shows all containers (including stopped ones). Defaults to `False`.
    -   **Example**: `session.call_tool("list_containers", {"all": True})`
-   `list_images(all: bool = False) -> str`
    -   **Description**: Lists Docker images.
    -   **Args**: `all` (boolean) - If true, shows all images (including intermediate ones). Defaults to `False`.
    -   **Example**: `session.call_tool("list_images", {})`
-   `docker_compose_status(working_directory: str = None) -> str`
    -   **Description**: Gets the status of services defined in a `docker-compose.yml` file.
    -   **Args**: `working_directory` (string) - The path to the directory containing the compose file.
    -   **Example**: `session.call_tool("docker_compose_status", {"working_directory": "/path/to/project"})`
## Security Features
### Command Validation
The server uses an allowlist-based approach for security. The `is_allowed_command` method in `main.py` ensures that only commands beginning with `docker` or `docker-compose` (including `docker compose`) are processed. All other commands are rejected.
### Error Handling
If a command fails to execute, the server captures `stdout`, `stderr`, and the exit code, returning a detailed error message to the client. The `execute_command` function contains a `try...except` block to handle exceptions during subprocess execution.
## Troubleshooting
### Common Issues
1.  **Docker Not Available**:
    -   Ensure Docker is installed: `docker --version`
    -   Check that the Docker daemon is running: `docker info`
    -   Verify your user has permissions to access the Docker socket.
2.  **Port Already in Use**:
    -   If you see an error like `address already in use`, the port (default `3000`) is occupied.
    -   Change the port using the `FASTMCP_PORT` environment variable.
    -   Find the process using the port: `lsof -i :3000` or `netstat -tulnp | grep 3000`.
3.  **Permission Denied (Docker Socket)**:
    -   If you get a "permission denied" error when running Docker commands, add your user to the `docker` group: `sudo usermod -aG docker $USER`.
    -   You will need to start a new shell session for this change to take effect.
4.  **Connection Refused**:
    -   Verify the MCP server is running and listening on the correct host and port.
    -   Check for firewall rules that might be blocking the connection.
    -   Ensure your client configuration matches the server's `FASTMCP_HOST` and `FASTMCP_PORT`.
## Development
### Project Structure
```
/workspace/mcp_docker/
├── .python-version
├── main.py           # Main server implementation
├── pyproject.toml    # Project metadata and dependencies
├── README.md         # This documentation
└── test/
    └── test_client.py # Example client for testing
```
### Testing
Run the example test client to connect to a running server, list its tools, and execute a sample command.
```bash
# Make sure the server is running in another terminal
# Then run the client
uv run test/test_client.py
```
## License
This project is open-source and available for modification and distribution.
## Support
For issues and questions:
1.  Check the Troubleshooting section.
2.  Verify your Docker installation and permissions.
3.  Review the server logs for error details.
4.  Test connectivity with simple commands first (e.g., `docker_system_info`).