This document explains how to run the Arbitrum MCP server using Docker for maximum compatibility with MCP clients.
# Build and run with Docker Compose
npm run docker:compose:build
# Or just run (if already built)
npm run docker:compose# Build the Docker image
npm run docker:build
# Run the container
npm run docker:run# Build the image
docker build -t arbitrum-mcp .
# Run interactively
docker run -it --rm arbitrum-mcpAdd this to your Claude Desktop configuration:
{
"mcpServers": {
"arbitrum-mcp": {
"command": "docker",
"args": ["run", "-i", "--rm", "arbitrum-mcp"]
}
}
}Use this general configuration:
servers:
arbitrum-mcp:
command: docker
args:
- run
- -i
- --rm
- arbitrum-mcp- Base Image:
node:18-alpine(lightweight Linux) - Security: Runs as non-root user
- Size: ~50MB (optimized with Alpine Linux)
- Transport: STDIO (standard input/output for MCP)
npm run docker:build # Build Docker image
npm run docker:run # Run container interactively
npm run docker:compose # Start with Docker Compose
npm run docker:compose:build # Build and start with Docker Compose
npm run docker:compose:down # Stop Docker Compose services- Ensure your MCP client is connecting via STDIO
- Check that the container has
-i(interactive) flag
- The Docker container runs as non-root user
mcp - All application files are owned by this user
- The MCP server uses STDIO, not network ports
- No port mapping is required for MCP communication
When using the MCP server from within Docker containers to connect to local testnodes, you cannot use 127.0.0.1 or localhost because these refer to the container's localhost, not the host machine.
❌ This will fail:
{
"rpcUrl": "http://127.0.0.1:8547"
}✅ Use this instead:
{
"rpcUrl": "http://host.docker.internal:8547"
}Common scenarios:
- Arbitrum local testnode: Use
http://host.docker.internal:8547 - Local Ethereum node: Use
http://host.docker.internal:8545 - Local Hardhat node: Use
http://host.docker.internal:8545
Error symptoms:
- "MCP error -32603: fetch failed"
- "Connection refused" errors
- Tools timing out when trying to connect
Testing connectivity:
# Test from inside container
docker exec <container-name> wget -qO- --post-data='{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' --header='Content-Type:application/json' http://host.docker.internal:8547# Make sure to build TypeScript first
npm run build
# Then build Docker image
npm run docker:buildFor production environments:
# Build production image
docker build -t arbitrum-mcp:latest .
# Run with restart policy
docker run -d --name arbitrum-mcp --restart unless-stopped arbitrum-mcp:latest
# Or use Docker Compose for production
docker-compose -f docker-compose.yml up -dThe container supports these environment variables:
NODE_ENV=production(set by default in docker-compose.yml)
The Docker Compose configuration includes health checks to monitor container status:
# Check container health
docker-compose ps{
"mcpServers": {
"arbitrum-mcp": {
"command": "docker",
"args": ["run", "-i", "--rm", "arbitrum-mcp"]
}
}
}{
"mcp": {
"arbitrum-mcp": {
"command": ["docker", "run", "-i", "--rm", "arbitrum-mcp"]
}
}
}This Docker setup ensures maximum compatibility across different MCP clients and operating systems.