A powerful, production-ready dynamic proxy server for the Model Context Protocol (MCP) and LLM APIs, built with Python and FastMCP. This service enables MCP clients and LLM-compatible applications to seamlessly connect to multiple backend MCP servers and LLM providers through a unified, scalable interface with advanced features including authentication, CORS support, and environment-based configuration.
drunk-mcp-proxy acts as a central gateway for both Model Context Protocol (MCP) services and LLM providers, providing:
Get up and running with drunk-mcp-proxy using the pre-built Docker image from Docker Hub.
Create a data/ directory with the required configuration files:
mkdir -p data/mcp data/openapi data/skills
data/config.yaml - Unified ConfigurationDefine authentication, LLM providers, and MCP/OpenAPI services in a single file:
# Authentication configuration (optional)
auth:
defaultProvider: basic
basic:
base_url: null
token: $API_KEY
jwt:
base_url: null
jwks_uri: "https://login.microsoftonline.com/common/discovery/keys"
issuer: "https://sts.windows.net/$AZURE_TENANT_ID/"
audience: "api://your-client-id"
# LLM provider configuration (optional)
llm:
- enabled: true
websocket: true
provider: openai
base_url: "https://api.openai.com/v1"
api_key: $OPENAI_API_KEY
# MCP and OpenAPI service configuration
mcp:
- path: /
spec_type: mcp
skill_dir: skills
mcp_servers:
my-server:
enabled: true
command: npx
args: ["@playwright/[email protected]"]
transport: stdio
- path: /api
spec_file: openapi/petstore.yaml
spec_type: openapi
base_url: "https://api.example.com"
Note:
- Bearer auth (
defaultProvider: "bearer") is the simplest option for API key authentication, commonly used by API proxies and gateways.- Environment variables like
$API_KEYor$AZURE_CLIENT_IDare automatically resolved when the config is loaded.
See the samples in the repositoryโ for more configuration examples.
Create a docker-compose.yml file:
services:
mcp-proxy:
image: baoduy2412/mcp-proxy:latest
container_name: mcp-proxy-server
ports:
- "${FASTMCP_PORT:-9123}:${FASTMCP_PORT:-9123}"
volumes:
- ./data:/drunk-proxy/data
env_file:
- .env
environment:
- FASTMCP_HOST=0.0.0.0
- FASTMCP_PORT=${FASTMCP_PORT:-9123}
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9123/health"]
interval: 30s
timeout: 10s
retries: 3
Note: The
./datadirectory is mounted to/drunk-proxy/datain the container. All configuration files should be placed in this directory.
Create a .env file from the sample:
cp .env.sample .env
Edit .env with your settings. Key environment variables:
# Server Configuration
FASTMCP_PORT=9123
FASTMCP_LOG_LEVEL=INFO
FASTMCP_AUTH_ENABLED=false
# Bearer Authentication (API Key)
API_KEY=your-api-key-here
# OAuth Storage (required if using OAuth)
FASTMCP_OAUTH_STORAGE_ENCRYPTION_KEY=your-44-character-encryption-key
# Azure Authentication (if using Azure OAuth)
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
AZURE_TENANT_ID=your-tenant-id
Tip: See .env.sampleโ for the complete list of available environment variables.
Now start the server:
docker-compose up -d
Verify it's running:
curl http://localhost:9123/health
The full docker-compose.ymlโ in the repository includes optional services:
git clone https://github.com/baoduy/drunk-mcp-proxy.git
cd drunk-mcp-proxy
docker build -t drunk-mcp-proxy .
docker run -d -p 9123:9123 -v $(pwd)/data:/drunk-proxy/data drunk-mcp-proxy
# Setup environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -e ".[dev]"
# Run the server
python src/main.py
The server will start on http://0.0.0.0:9123 by default.
data/
โโโ config.yaml # Unified configuration (auth, LLM, and MCP/OpenAPI services)
โโโ mcp/ # MCP server specifications (optional, for external spec files)
โ โโโ stock.mcp.json
โ โโโ wiki.mcp.json
โโโ openapi/ # OpenAPI specifications
โ โโโ petstore.yaml
โโโ skills/ # Skill directories (optional)
config.yaml)The proxy uses a unified YAML configuration file to define authentication, LLM providers, and MCP/OpenAPI services:
# Authentication configuration
auth:
defaultProvider: basic
basic:
token: $API_KEY
# MCP service configuration
mcp:
- path: /stock
spec_file: mcp/stock.mcp.json
spec_type: mcp
- path: /api
spec_file: openapi/petstore.yaml
spec_type: openapi
base_url: "https://api.example.com"
filters:
methods: ["GET", "POST"]
tags: ["public"]
Key environment variables (see .env.sampleโ for complete list):
| Variable | Description | Default |
|---|---|---|
FASTMCP_PORT | Server port | 9123 |
FASTMCP_HOST | Server host | 0.0.0.0 |
FASTMCP_LOG_LEVEL | Log level (DEBUG, INFO, WARNING, ERROR) | INFO |
FASTMCP_AUTH_ENABLED | Enable authentication | false |
FASTMCP_CONFIG_DIR | Configuration directory | data |
FASTMCP_CORS_ALLOW_ORIGINS | CORS allowed origins | * |
API_KEY | API key for bearer authentication | - |
FASTMCP_OAUTH_STORAGE_ENCRYPTION_KEY | Fernet key for OAuth token encryption | - |
See Environment Variablesโ for complete list.
Getting Started
Configuration
Features
Architecture
API Reference
Deployment
Development
For comprehensive documentation, see the Documentation Indexโ .
MCP Client / LLM Client / Anthropic Client
โ (HTTP/SSE/WebSocket + Authorization)
โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ drunk-mcp-proxy Server โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Starlette ASGI Application โ โ
โ โ โข CORS Middleware โ โ
โ โ โข Auth Validation โ โ
โ โ โข Rate Limiting โ โ
โ โ โข Health Check: /health โ โ
โ โ โข Root FastMCP Server (/) โ โ
โ โ โข MCP Sub-services: โ โ
โ โ - /stock (MCP) โ โ
โ โ - /wiki (MCP) โ โ
โ โ - /api (OpenAPI) โ โ
โ โ โข LLM Proxy (/api/v1): โ โ
โ โ - POST /chat/completions โ โ
โ โ - POST /messages (Anthropic API) โ โ
โ โ - WS /responses (WebSocket) โ โ
โ โ - POST /embeddings โ โ
โ โ - POST /images/generations โ โ
โ โ - POST /audio/transcriptions โ โ
โ โ - POST /audio/translations โ โ
โ โ - GET /models โ โ
โ โ - GET /providers โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
[Backend MCP/OpenAPI/LLM Services]
See System Architectureโ for detailed diagrams.
drunk-mcp-proxy supports 14+ authentication providers:
The simplest option for API key authentication, commonly used by API proxies and gateways:
auth:
defaultProvider: basic
basic:
token: $API_KEY
Set the API_KEY environment variable in your .env file.
auth:
defaultProvider: azure
azure:
client_id: $AZURE_CLIENT_ID
client_secret: $AZURE_CLIENT_SECRET
tenant_id: $AZURE_TENANT_ID
See Authentication Guideโ for details.
# Run all tests
python -m pytest
# Run specific test file
python -m pytest tests/test_server.py
# Run with coverage
python -m pytest --cov=src --cov-report=html
When LLM providers are configured, drunk-mcp-proxy exposes a full OpenAI-compatible LLM gateway at /api/v1. All endpoints use the model ID format provider_modelname (e.g., openai_gpt-4o, lms_llama3.2) to route requests to the appropriate backend.
Add providers to the llm section of config.yaml:
llm:
- enabled: true
websocket: true # Enable for providers that support native WebSocket Responses API
# When false, HTTP Responses API is used as fallback
provider: openai # Short provider name used as prefix in model IDs
base_url: "https://api.openai.com/v1"
api_key: $OPENAI_API_KEY
- enabled: true
websocket: false
provider: lms # LM Studio
base_url: "http://host.docker.internal:1234/v1"
- enabled: false
provider: oll # Ollama
base_url: "http://host.docker.internal:11434/v1"
All LLM endpoints expect the model ID to include a provider prefix separated by an underscore:
{provider}_{model_name}
Examples:
openai_gpt-4o โ routes to the openai provider, model gpt-4olms_llama3.2 โ routes to the lms (LM Studio) provider, model llama3.2ort_claude-3-5-sonnet โ routes to the ort (OpenRouter) provider, model claude-3-5-sonnetAll endpoints are mounted at /api/v1 (configurable via FASTMCP_LLM_ROUTE_PREFIX):
| Method | Endpoint | Description |
|---|---|---|
POST | /api/v1/chat/completions | OpenAI-compatible chat completions |
POST | /api/v1/messages | Anthropic Messages API (see below) |
WS | /api/v1/responses | OpenAI WebSocket Responses API |
POST | /api/v1/embeddings | Text embeddings |
POST | /api/v1/images/generations | Image generation |
POST | /api/v1/audio/transcriptions | Audio transcription (Whisper) |
POST | /api/v1/audio/translations | Audio translation |
GET | /api/v1/models | List all available models across providers |
GET | /api/v1/providers | List all configured providers |
Standard OpenAI-compatible chat completions:
curl -X POST http://localhost:9123/api/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "openai_gpt-4o",
"messages": [{"role": "user", "content": "Hello!"}],
"stream": false
}'
The /messages endpoint accepts Anthropic Messages API format and transparently converts to/from the OpenAI format, letting Anthropic/Claude clients use any OpenAI-compatible backend:
curl -X POST http://localhost:9123/api/v1/messages \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "lms_llama3.2",
"messages": [{"role": "user", "content": "Hello!"}],
"max_tokens": 1024
}'
Supported conversions:
stop_sequences โ stop, metadata.user_id โ user, finish reason mappingPoint the Claude Code CLI at the proxy to use any backend model with the Anthropic-compatible endpoint:
export ANTHROPIC_BASE_URL=http://localhost:9123/api/v1
export ANTHROPIC_AUTH_TOKEN=YOUR_API_KEY_HERE
claude --model lms_llama3.2
The /responses WebSocket endpoint provides OpenAI Responses API streaming. Clients connect via WebSocket and exchange JSON messages using the OpenAI Responses API protocol.
Connection URL: ws://localhost:9123/api/v1/responses
Message flow:
Authorization: Bearer <token> headerresponse.create event with model: "provider_modelname"websocket: true, native WebSocket is used for lowest latencyconst ws = new WebSocket("ws://localhost:9123/api/v1/responses", {
headers: { "Authorization": "Bearer YOUR_API_KEY" }
});
ws.send(JSON.stringify({
type: "response.create",
response: {
model: "openai_gpt-4o",
instructions: "You are a helpful assistant.",
input: [{ type: "message", role: "user", content: "Hello!" }]
}
}));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data.type, data); // response.created, response.output_text.delta, response.done, etc.
};
Provider WebSocket support: Set websocket: true in the provider config for providers that natively support the /responses WebSocket endpoint (e.g., OpenAI). For all other providers, the HTTP Responses API is used as a fallback.
Note: The
previous_response_idcontinuation feature is only supported for providers with native WebSocket (websocket: true). Using it with HTTP fallback providers returns an error.
# List all models across all configured providers
curl http://localhost:9123/api/v1/models \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by provider
curl "http://localhost:9123/api/v1/models?provider=openai" \
-H "Authorization: Bearer YOUR_API_KEY"
# List configured providers
curl http://localhost:9123/api/v1/providers \
-H "Authorization: Bearer YOUR_API_KEY"
Contributions are welcome! Please:
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)This project is licensed under the MIT License - see the LICENSEโ file for details.
Note: For detailed technical documentation, API references, and advanced configuration, please refer to the comprehensive documentationโ .
Content type
Image
Digest
sha256:3c0530954โฆ
Size
285.7 MB
Last updated
6 months ago
docker pull baoduy2412/mcp-proxy