Docker Deployment¶
pvl-webtools provides a Docker image for running the MCP server with Streamable HTTP transport, suitable for production deployments and integration with AI assistants over the network.
Quick Start¶
# Pull the latest image
docker pull ghcr.io/pvliesdonk/pvl-webtools:latest
# Run with SearXNG configured
docker run -d \
--name pvl-webtools \
-p 8000:8000 \
-e SEARXNG_URL="http://your-searxng-instance:8888" \
ghcr.io/pvliesdonk/pvl-webtools:latest
The MCP server is now available at http://localhost:8000/mcp.
Image Tags¶
| Tag | Description |
|---|---|
latest |
Latest stable release |
vX.Y.Z |
Specific version (e.g., v0.2.0) |
vX.Y |
Latest patch for minor version (e.g., v0.2) |
vX |
Latest for major version (e.g., v0) |
Configuration¶
Environment Variables¶
| Variable | Default | Description |
|---|---|---|
SEARXNG_URL |
(none) | SearXNG instance URL for web search |
MCP_HOST |
0.0.0.0 |
Host to bind the server to |
MCP_PORT |
8000 |
Port to listen on |
LOG_LEVEL |
(none) | Optional logging level for the MCP server (DEBUG, INFO, TRACE, etc.). TRACE disables dependency log filtering. |
VERBOSE |
(none) | Convenience flag; set to 1/true for debug logging without dependency noise. |
Example: Custom Port¶
docker run -d \
-p 9000:9000 \
-e MCP_PORT=9000 \
-e LOG_LEVEL=DEBUG \
-e SEARXNG_URL="http://searxng:8888" \
ghcr.io/pvliesdonk/pvl-webtools:latest
Docker Compose¶
Here's a complete example with SearXNG:
# docker-compose.yml
services:
pvl-webtools:
image: ghcr.io/pvliesdonk/pvl-webtools:latest
ports:
- "8000:8000"
environment:
- SEARXNG_URL=http://searxng:8888
depends_on:
- searxng
restart: unless-stopped
searxng:
image: searxng/searxng:latest
ports:
- "8888:8080"
volumes:
- ./searxng:/etc/searxng:rw
environment:
- SEARXNG_BASE_URL=http://localhost:8888/
restart: unless-stopped
Connecting MCP Clients¶
Claude Desktop¶
Add to your Claude Desktop configuration (claude_desktop_config.json):
FastMCP Client¶
from fastmcp import Client
async with Client("http://localhost:8000/mcp") as client:
# Search the web
results = await client.call_tool("search", {
"query": "python best practices",
"max_results": 5
})
# Fetch a URL
content = await client.call_tool("fetch", {
"url": "https://example.com",
"extract_mode": "markdown"
})
Building Locally¶
# Clone the repository
git clone https://github.com/pvliesdonk/pvl-webtools.git
cd pvl-webtools
# Build the image
docker build -t pvl-webtools:local .
# Run locally built image
docker run -p 8000:8000 -e SEARXNG_URL="http://your-searxng:8888" pvl-webtools:local
Multi-Architecture Support¶
The published images support both linux/amd64 and linux/arm64 architectures, making them compatible with:
- Standard x86_64 servers
- Apple Silicon Macs (M1/M2/M3)
- ARM-based cloud instances (AWS Graviton, etc.)
Health Checks¶
The container includes a health check that verifies the MCP endpoint is responding:
Security Notes¶
- The container runs as a non-root user (
appuser) - Only the MCP port (8000 by default) is exposed
- No sensitive data is stored in the image
- Use environment variables for configuration (never bake secrets into images)
Troubleshooting¶
Search not working¶
Ensure SEARXNG_URL is set and the SearXNG instance is reachable from the container:
docker exec pvl-webtools python -c "from pvlwebtools.mcp_server import check_status; print(check_status())"
Connection refused¶
Check if the container is running and healthy:
Port conflicts¶
If port 8000 is in use, map to a different port: