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/sdkwithStreamableHTTPServerTransport - 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
./tmpdirectory 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
- Docker installed and running
- Docker Compose for container management
- Node.js (v18 or higher) for local development only
🚀 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
Authorizationheader withBearerprefix
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
- Start the server:
npm run docker:up - View logs:
npm run docker:logs - Copy the token from the output
- Update your client configuration with the token
- Restart your MCP client
Verification
After configuration:
- Restart your MCP client (e.g., Claude Desktop)
- Check that the Docker MCP server shows as connected
- 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 executerationale(string) - Explanation of why this command is being executedmaxWaitTime(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 commandrationale(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 processinput(string) - The input to send to the processrationale(string) - Explanation of why you need to send inputautoNewline(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/workspacerationale(string) - Explanation of why you need to read this fileoffset(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/workspacecontent(string) - The content to writerationale(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/workspaceoldString(string) - The exact text to replacenewString(string) - The replacement textrationale(string) - Explanation of why you need to edit this filereplaceAll(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 directoryignore(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 searchpath(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
./tmpdirectory accessible from host - User Permissions: Commands run with container-level permissions
- No Host Access: Server cannot access host filesystem outside mount
Recommended Security Practices
- Token Management: Keep authentication tokens secure and private
- Network Restrictions: Use firewall rules to limit access to port 3000
- Workspace Isolation: Regularly audit
./tmpdirectory contents - Resource Limits: Add CPU and memory constraints in docker-compose.yml
- 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
maxWaitTimeparameter inexecute_command - Use
check_processto monitor long-running operations - Break complex operations into smaller steps
- Check container resources:
docker stats mcp-container
🤝 Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes in
src/ - Test with
npm run docker:restart - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - 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 toproductionfor 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.mdfor 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