GitHub - kenforthewin/docker-mcp-server: Add agentic coding capabilities to any AI that supports MCP

9 min read Original article ↗

Docker MCP Server

A Model Context Protocol (MCP) server that runs entirely inside a Docker container, providing secure command execution and file operations through HTTP with bearer token authentication.

🚀 Features

  • Containerized MCP Server: Runs entirely inside Docker with no host dependencies
  • HTTP Transport: Network-based communication with bearer token authentication
  • Secure Command Execution: Run shell commands in isolated container environment
  • File Operations: Read, write, edit, and search files within container workspace
  • Process Management: Track long-running processes with unique IDs
  • Interactive Input: Send input to running processes
  • Smart Timeouts: Intelligent process timeout handling based on output activity

🏗️ Architecture

The MCP server runs inside a Docker container and communicates with clients over HTTP:

MCP Client (via HTTP) ↔ Docker Container (Port 3000)
                              ↓
                        MCP Server (Node.js)
                              ↓
                    Workspace (/app/workspace)
                              ↓
                    Host ./tmp directory (mounted)

Core Components

  • Containerized MCP Server - TypeScript server using @modelcontextprotocol/sdk with StreamableHTTPServerTransport
  • HTTP API - Network-based communication on port 3000
  • Bearer Token Auth - Secure authentication for all requests
  • Docker Container - Debian-based with Node.js, Playwright, and development tools
  • Workspace Mount - Host ./tmp directory mounted to /app/workspace
  • Process Tracking - Background process management with unique IDs

Key Differences from Traditional MCP Servers

  • No Host Installation: Server runs entirely in container
  • Network Access: HTTP-based instead of stdio transport
  • Authentication Required: Bearer token for all requests
  • Self-Contained: All dependencies bundled in container image
  • Direct Execution: No docker exec overhead

📋 Prerequisites

🚀 Quick Start

1. Clone and Setup

git clone <your-repository-url>
cd docker-mcp

2. Start the Server

# Quick start: reset environment and start server
./reset-docker.sh

# Or manually:
npm run docker:build    # Build container with server code
npm run docker:up       # Start container
npm run docker:logs     # View logs and get auth token

3. Get Connection Info

The server logs display the authentication token and connection details:

Look for output like:

============================================================
Docker MCP Server Starting
============================================================
Port: 3000
Auth Token: abc123-def456-ghi789
============================================================

4. Test Connection

# Test with curl
curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
     http://localhost:3000

# View server logs
npm run docker:logs

🔧 Development Commands

Docker Operations

# Build the container image with server code
npm run docker:build

# Start the containerized MCP server
npm run docker:up

# Stop the container
npm run docker:down

# View server logs (includes auth token)
npm run docker:logs

# Rebuild and restart (after code changes)
npm run docker:restart

# Open bash shell in container
npm run docker:shell

# Complete reset (clean workspace and rebuild)
./reset-docker.sh

Local Development

# Build TypeScript (for development/testing only)
npm run build

# Install/update dependencies
npm install

⚙️ MCP Client Configuration

Configuration Format

MCP clients need to connect via HTTP with bearer token authentication:

{
  "url": "http://localhost:3000",
  "headers": {
    "Authorization": "Bearer YOUR_TOKEN_FROM_LOGS"
  }
}

Important:

  • Get the auth token from container logs: npm run docker:logs
  • Token is auto-generated on each container start
  • Token must be included in the Authorization header with Bearer prefix

Claude Desktop Configuration

Add to your Claude Desktop configuration file:

Location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json

Configuration:

{
  "mcpServers": {
    "docker-mcp": {
      "url": "http://localhost:3000",
      "headers": {
        "Authorization": "Bearer YOUR_TOKEN_FROM_LOGS"
      }
    }
  }
}

Note: Replace YOUR_TOKEN_FROM_LOGS with the actual token from npm run docker:logs

Getting Your Authentication Token

  1. Start the server: npm run docker:up
  2. View logs: npm run docker:logs
  3. Copy the token from the output
  4. Update your client configuration with the token
  5. Restart your MCP client

Verification

After configuration:

  1. Restart your MCP client (e.g., Claude Desktop)
  2. Check that the Docker MCP server shows as connected
  3. Verify access to all available tools

🛠️ Available MCP Tools

🚀 Command Execution

execute_command

Execute shell commands inside the container

Execute any shell command within the container environment with intelligent process tracking.

Parameters:

  • command (string) - The shell command to execute
  • rationale (string) - Explanation of why this command is being executed
  • maxWaitTime (number, optional) - Maximum seconds to wait before returning (default: 20)

Features:

  • Automatic backgrounding for long-running processes
  • Smart timeout based on output activity
  • Process ID returned for monitoring
  • Real-time output capture

check_process

Monitor background processes by ID

Check the status and output of background processes started by execute_command.

Parameters:

  • processId (string) - The process ID returned by a long-running command
  • rationale (string) - Explanation of why you need to check this process

Returns:

  • Process status (running/completed)
  • Current output (stdout/stderr)
  • Exit code (if completed)
  • Runtime duration

send_input

Send input to running background processes

Send input data to interactive processes waiting for user input.

Parameters:

  • processId (string) - The process ID of the running process
  • input (string) - The input to send to the process
  • rationale (string) - Explanation of why you need to send input
  • autoNewline (boolean, optional) - Auto-add newline (default: true)

📁 File Operations

All file operations work within /app/workspace which is mounted from host ./tmp.

file_read

Read files from container filesystem

Read file contents with support for large files through pagination.

Parameters:

  • filePath (string) - Path relative to /app/workspace
  • rationale (string) - Explanation of why you need to read this file
  • offset (number, optional) - Starting line number (default: 0)
  • limit (number, optional) - Maximum lines to read (default: 2000)

file_write

Create or overwrite files

Write content to files with automatic directory creation.

Parameters:

  • filePath (string) - Path relative to /app/workspace
  • content (string) - The content to write
  • rationale (string) - Explanation of why you need to write this file

Important: Use file_read first to understand current state.

file_edit

Perform exact string replacements

Edit files using precise string matching with backup protection.

Parameters:

  • filePath (string) - Path relative to /app/workspace
  • oldString (string) - The exact text to replace
  • newString (string) - The replacement text
  • rationale (string) - Explanation of why you need to edit this file
  • replaceAll (boolean, optional) - Replace all occurrences (default: false)

Important: Use file_read first to get the exact text to match.

file_ls

List directory contents

List files and directories with intelligent filtering.

Parameters:

  • path (string, optional) - Directory path (default: current directory)
  • rationale (string) - Explanation of why you need to list this directory
  • ignore (array, optional) - Glob patterns to ignore

file_grep

Search file contents

Search for patterns in files using grep with regex support.

Parameters:

  • pattern (string) - Search pattern (supports regex)
  • rationale (string) - Explanation of why you need to search
  • path (string, optional) - Directory to search (default: current)
  • include (string, optional) - File pattern filter (e.g., '*.js')
  • caseInsensitive (boolean, optional) - Case insensitive (default: false)
  • maxResults (number, optional) - Result limit (default: 100)

📊 Process Management

Commands run with intelligent timeout handling:

  • Default timeout: 20 seconds of inactivity before backgrounding
  • Maximum timeout: 10 minutes absolute limit
  • Process tracking: Background processes get unique IDs for monitoring
  • Smart waiting: Based on output activity, not fixed intervals

Example Process Flow

// Long-running command gets backgrounded automatically
const result1 = execute_command({
  command: "npm install",
  rationale: "Installing dependencies"
});
// Returns process ID if backgrounded

// Check status later
const result2 = check_process({
  processId: result1.processId,
  rationale: "Checking installation progress"
});

// Send input to interactive processes
send_input({
  processId: result1.processId,
  input: "y",
  rationale: "Confirming prompt"
});

🔒 Security Considerations

Authentication

  • Bearer Token Required: All requests must include valid bearer token
  • Auto-Generated Token: New token generated on each container start
  • Token Rotation: Restart container to generate new token
  • CORS Enabled: Allows cross-origin requests (consider restricting in production)

Container Isolation

  • Network Isolation: Container exposed only on port 3000
  • Workspace Mount: Only ./tmp directory accessible from host
  • User Permissions: Commands run with container-level permissions
  • No Host Access: Server cannot access host filesystem outside mount

Recommended Security Practices

  1. Token Management: Keep authentication tokens secure and private
  2. Network Restrictions: Use firewall rules to limit access to port 3000
  3. Workspace Isolation: Regularly audit ./tmp directory contents
  4. Resource Limits: Add CPU and memory constraints in docker-compose.yml
  5. Access Logs: Monitor container logs for suspicious activity

🚨 Troubleshooting

Server Won't Start

# Check Docker is running
docker info

# View container logs for errors
npm run docker:logs

# Verify port 3000 is available
lsof -i :3000  # macOS/Linux
netstat -ano | findstr :3000  # Windows

# Complete reset
npm run docker:down
./reset-docker.sh

Can't Connect to Server

# Verify container is running
docker ps | grep mcp-container

# Check server logs for auth token
npm run docker:logs

# Ensure correct URL
curl -H "Authorization: Bearer YOUR_TOKEN" http://localhost:3000

# Restart container
npm run docker:restart

Code Changes Not Reflected

# Remember: server code is built into container image
# After changing TypeScript code, you MUST rebuild:
npm run docker:restart

# Or manually:
npm run docker:down
npm run docker:build
npm run docker:up

Authentication Failed

# Get current auth token from logs
npm run docker:logs

# Verify token format in client config
# Must be: "Bearer YOUR_TOKEN" (with "Bearer " prefix)

# Token changes on restart - update client config

Permission Errors in Workspace

# Ensure tmp directory exists and is writable
mkdir -p tmp
chmod 755 tmp

# Reset workspace
rm -rf tmp && mkdir tmp

Process Timeout Issues

  • Increase maxWaitTime parameter in execute_command
  • Use check_process to monitor long-running operations
  • Break complex operations into smaller steps
  • Check container resources: docker stats mcp-container

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes in src/
  4. Test with npm run docker:restart
  5. Commit your changes (git commit -m 'Add amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Development Guidelines

  • Follow TypeScript best practices
  • Add comprehensive error handling
  • Include rationale parameters for all tool operations
  • Test with both quick and long-running commands
  • Document any new MCP tools or capabilities
  • Test authentication and security features

📦 Deployment

Local Deployment

# Production deployment
docker-compose up -d

# View production logs
docker-compose logs -f mcp-container

# Auto-restart on failure
# (already configured with restart: unless-stopped)

Custom Configuration

# docker-compose.yml
services:
  mcp-container:
    environment:
      - NODE_ENV=production
      - AUTH_TOKEN=your-custom-token  # Optional: set custom token
    ports:
      - "3000:3000"  # Change port mapping if needed
    volumes:
      - ./custom-workspace:/app/workspace

Environment Variables

  • NODE_ENV: Set to production for production deployment
  • Port: Configure via CLI flag --port 3000
  • Token: Set via CLI flag --token your-token (auto-generated if not set)

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙋‍♂️ Support

  • 🐛 Bug Reports: Open an issue with detailed reproduction steps
  • 💡 Feature Requests: Open an issue with your use case
  • 📖 Documentation: Check CLAUDE.md for AI assistant specific guidance
  • 💬 Questions: Open a discussion for general questions

📚 Additional Resources


Built for the Model Context Protocol ecosystem 🤖

Features:

  • ✅ HTTP Transport with Bearer Token Auth
  • ✅ Containerized Architecture
  • ✅ Process Management
  • ✅ File Operations
  • ✅ Network Accessible
  • ✅ Production Ready