This project provides Docker wrappers for running Model Context Protocol (MCP) servers that are typically executed with uvx (Python), npx (Node.js), or plain Docker commands. Instead of installing dependencies locally, you can run MCP servers in isolated Docker containers.
MCP servers can be written in different languages and use different package managers. This Docker wrapper supports:
- Python-based servers using
uvx(the successor topipx) - Node.js-based servers using
npx - Plain Docker images for any pre-built MCP servers
These Docker wrappers allow you to:
- Run MCP servers without installing Python dependencies locally
- Maintain isolation between different MCP servers
- Avoid conflicts with local Python environments
- Easily manage and deploy MCP servers across different environments
The easiest way to get started is to use the installation script:
curl -fsSL https://raw.githubusercontent.com/qforge-dev/qmcp/main/install.sh | shThis will:
- Install
qmcp-uvx,qmcp-npx, andqmcpwrapper commands - Pull the necessary Docker images
- Set up everything needed to use QMCP
After installation, you can use qmcp-uvx instead of uvx, qmcp-npx instead of npx, and qmcp for plain Docker images in your MCP configurations.
If you prefer to build the images locally instead of using the pre-built ones:
To build the Python Docker image, run:
./build-uvx.shOr manually:
docker build -f Dockerfile.uvx -t qmcp-uvx .To build the Node.js Docker image, run:
./build-node.shOr manually:
docker build -f Dockerfile.npx -t qmcp-npx .After installation, you can use the wrapper commands directly:
Instead of running:
uvx elevenlabs-mcpYou can now run:
qmcp-uvx elevenlabs-mcpEnvironment variables with the MCP_ prefix are automatically forwarded to the container. For other environment variables, you'll need to prefix them with MCP_ or use the direct Docker approach.
For the plain Docker wrapper qmcp, environment variables with the MCP_ prefix are also automatically forwarded with the prefix removed.
Instead of running:
npx @example/mcp-serverYou can now run:
qmcp-npx @example/mcp-serverInstead of running:
docker run -i --rm -e GITHUB_PERSONAL_ACCESS_TOKEN ghcr.io/github/github-mcp-serverYou can now run:
qmcp ghcr.io/github/github-mcp-serverIf you prefer to use Docker directly without the wrapper commands:
# Basic usage
docker run --rm -i ghcr.io/qforge-dev/qmcp-uvx uvx elevenlabs-mcp
# With environment variables
docker run --rm -i -e ELEVENLABS_API_KEY="your-api-key-here" ghcr.io/qforge-dev/qmcp-uvx uvx elevenlabs-mcp# Basic usage
docker run --rm -i ghcr.io/qforge-dev/qmcp-npx npx @example/mcp-server
# With environment variables
docker run --rm -i -e API_KEY="your-api-key-here" ghcr.io/qforge-dev/qmcp-npx npx @example/mcp-serverIn your MCP client configuration (like Claude Desktop), you can configure the server like this:
Before (using uvx directly):
{
"mcpServers": {
"ElevenLabs": {
"command": "uvx",
"args": ["elevenlabs-mcp"],
"env": {
"ELEVENLABS_API_KEY": "<insert-your-api-key-here>"
}
}
}
}After (using QMCP wrapper):
{
"mcpServers": {
"ElevenLabs": {
"command": "qmcp-uvx",
"args": ["elevenlabs-mcp"],
"env": {
"ELEVENLABS_API_KEY": "<insert-your-api-key-here>"
}
}
}
}That's it! Just replace uvx with qmcp-uvx and everything else stays the same.
Before (using npx directly):
{
"mcpServers": {
"ExampleNodeServer": {
"command": "npx",
"args": ["@example/mcp-server"],
"env": {
"API_KEY": "<insert-your-api-key-here>"
}
}
}
}After (using QMCP wrapper):
{
"mcpServers": {
"ExampleNodeServer": {
"command": "qmcp-npx",
"args": ["@example/mcp-server"],
"env": {
"MCP_API_KEY": "<insert-your-api-key-here>"
}
}
}
}Just replace npx with qmcp-npx and you're done!
Before (using docker directly):
{
"mcpServers": {
"GitHubMCP": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "<insert-your-github-token-here>"
}
}
}
}After (using QMCP wrapper):
{
"mcpServers": {
"GitHubMCP": {
"command": "qmcp",
"args": ["ghcr.io/github/github-mcp-server"],
"env": {
"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "<insert-your-github-token-here>"
}
}
}
}Much simpler! Just use qmcp with the Docker image name and prefix your environment variables with MCP_.
The wrapper commands (qmcp-uvx, qmcp-npx, and qmcp) have a secure approach to environment variable forwarding:
Only environment variables that start with MCP_ are automatically forwarded to the Docker containers. The MCP_ prefix is stripped when forwarding, so MCP_ELEVENLABS_API_KEY becomes ELEVENLABS_API_KEY inside the container. This prevents system environment variables from interfering with the container environment.
Example usage:
# Set your API key with MCP_ prefix
export MCP_ELEVENLABS_API_KEY="your-api-key-here"
# Run the MCP server - the environment variable will be forwarded as ELEVENLABS_API_KEY
qmcp-uvx elevenlabs-mcp
# Or for a plain Docker image
export MCP_GITHUB_PERSONAL_ACCESS_TOKEN="your-token-here"
qmcp ghcr.io/github/github-mcp-serverWhen configuring your MCP servers, you have two options:
Set your environment variables with the MCP_ prefix in your shell:
export MCP_ELEVENLABS_API_KEY="your-key"
export MCP_POSTGRES_HOST="localhost"
export MCP_API_TOKEN="your-token"Then your MCP server configuration becomes much simpler since the variables are automatically forwarded:
{
"mcpServers": {
"ElevenLabs": {
"command": "qmcp-uvx",
"args": ["elevenlabs-mcp"]
},
"GitHubMCP": {
"command": "qmcp",
"args": ["ghcr.io/github/github-mcp-server"]
}
}
}The MCP_ELEVENLABS_API_KEY and MCP_GITHUB_PERSONAL_ACCESS_TOKEN from your environment will automatically be available as ELEVENLABS_API_KEY and GITHUB_PERSONAL_ACCESS_TOKEN inside their respective containers.
{
"mcpServers": {
"ElevenLabs": {
"command": "qmcp-uvx",
"args": ["elevenlabs-mcp"],
"env": {
"MCP_ELEVENLABS_API_KEY": "your-api-key-here"
}
},
"GitHubMCP": {
"command": "qmcp",
"args": ["ghcr.io/github/github-mcp-server"],
"env": {
"MCP_GITHUB_PERSONAL_ACCESS_TOKEN": "your-github-token-here"
}
}
}
}This approach provides several benefits:
- Security: Only explicitly intended environment variables are forwarded
- Isolation: Prevents system paths and configurations from interfering
- Clarity: Makes it obvious which variables are meant for MCP servers
- No Permission Issues: Avoids Docker permission conflicts with system paths
- Base Image: Uses
python:3.13-slimas the base image for a lightweight Python environment - Dependencies: Installs
uv(which includesuvx) and essential system tools - User Security: Runs as a non-root user (
mcpuser) for better security - Entrypoint: Uses a custom entrypoint script that handles
uvxcommand execution - Path Setup: Configures the PATH to include uvx binary locations
- Base Image: Uses
node:24-slimas the base image for a lightweight Node.js environment - Dependencies: Includes npm and npx for package management
- User Security: Runs as a non-root user (
mcpuser) for better security - Entrypoint: Uses a custom entrypoint script that handles
npxcommand execution - Path Setup: Configures npm to install global packages in user directory
This wrapper should work with any Python-based MCP server that can be installed and run with uvx. Examples include:
elevenlabs-mcpfilesystem-mcpbrave-search-mcppostgres-mcp- Any other Python MCP server available on PyPI
This wrapper should work with any Node.js-based MCP server that can be installed and run with npx. Examples include:
@example/mcp-server@nodeserver/filesystem-mcp- Any other Node.js MCP server available on npm
This wrapper works with any pre-built Docker image that implements an MCP server. Examples include:
ghcr.io/github/github-mcp-serverghcr.io/modelcontextprotocol/servers/filesystem- Any other Docker image that provides an MCP server
The containers can also run other commands:
Python container:
docker run --rm qmcp-uvx python --version
docker run --rm qmcp-uvx pip listNode.js container:
docker run --rm qmcp-npx node --version
docker run --rm qmcp-npx npm list -gPlain Docker (qmcp):
# Run any Docker image with MCP environment variable forwarding
qmcp your-registry.com/custom-mcp-server
qmcp ghcr.io/github/github-mcp-server --verboseIf your MCP server needs access to local files:
docker run --rm -v /path/to/data:/data -e DATA_PATH=/data qmcp-uvx uvx your-mcp-serverFor MCP servers that need network access:
docker run --rm --network host qmcp-uvx uvx your-mcp-serverIf you get an error that the MCP server package is not found, ensure:
- The package name is correct
- The package is available on PyPI
- You have internet access in the container
If you encounter permission issues:
- The container runs as user
mcpuser(UID 1000) by default - Ensure any mounted volumes have appropriate permissions
Make sure to:
- Use the
-eflag before each environment variable - Quote values that contain spaces or special characters
- Reference environment variables correctly in your configuration
Feel free to submit issues and pull requests to improve this Docker wrapper.