This guide explains how to authenticate MCP servers that require OAuth when running Claude Code inside a Docker container.
MCP servers (like GitHub, Gmail, etc.) use OAuth authentication which requires:
- Opening a browser to authenticate
- Redirecting back to
http://localhost:[random-port]/callback
Issue: The Docker container can't receive these callbacks because:
- The browser runs on your host machine
- The callback URL points to
localhoston the host - The Docker container has a different network namespace
We've created an OAuth proxy that runs on your host machine and forwards callbacks into the container.
The OAuth proxy requires aiohttp:
pip install aiohttpOr if using the project virtualenv:
cd claude-code-api
pip install -e .
pip install aiohttpIn a separate terminal (keep it running), start the OAuth proxy:
python3 oauth-proxy.pyYou should see:
Starting OAuth Proxy on port 8888
Forwarding to container at localhost:8000
OAuth callback URL: http://localhost:8888/oauth/callback
Press Ctrl+C to stop
Optional: Run on a different port:
python3 oauth-proxy.py --port 9999In your main terminal:
docker-compose up -dWhen configuring MCP servers that require OAuth, you'll need to set the callback URL to use the proxy.
-
Run
claudeinside the container:docker exec -it claude-code-api claude -
When Claude prompts you to authenticate an MCP server:
- Copy the authentication URL
- Open it in your host browser (not container)
- Complete the OAuth flow
- The callback will automatically be forwarded through the proxy
If you need to manually configure callback URLs in MCP server settings:
Use: http://localhost:8888/oauth/callback
Instead of the default random port that Claude Code generates.
Check that both services are running:
# Check API server
curl http://localhost:8000/health
# Check OAuth proxy
curl http://localhost:8888/healthBoth should return healthy status.
┌─────────────────┐
│ Your Browser │
│ (on host) │
└────────┬────────┘
│ 1. OAuth redirect
│ http://localhost:8888/oauth/callback?code=...
▼
┌─────────────────┐
│ OAuth Proxy │
│ (on host) │ Runs: oauth-proxy.py
│ Port: 8888 │
└────────┬────────┘
│ 2. Forward callback
│ http://localhost:8000/...
▼
┌─────────────────┐
│ Docker Container│
│ Claude Code │ Receives callback
│ Port: 8000 │ Completes auth
└─────────────────┘
Solution: Make sure the Docker container is running:
docker ps | grep claude-code-apiSolution: Check that port 8888 is exposed in docker-compose.yml:
ports:
- "127.0.0.1:8000:8000"
- "127.0.0.1:8888:8888" # Should be presentSolution: OAuth proxy isn't running. Start it in a separate terminal:
python3 oauth-proxy.pySolution: Check container logs:
docker logs claude-code-apiLook for errors in the OAuth flow.
If running Docker on a different machine:
python3 oauth-proxy.py --container-host 192.168.1.100 --container-port 8000Run multiple proxies on different ports:
# Terminal 1 - Container 1
python3 oauth-proxy.py --port 8888 --container-port 8000
# Terminal 2 - Container 2
python3 oauth-proxy.py --port 8889 --container-port 8001For production, run the OAuth proxy as a systemd service:
- Create
/etc/systemd/system/claude-oauth-proxy.service:
[Unit]
Description=OAuth Proxy for Claude Code
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/claude-code-api
ExecStart=/usr/bin/python3 /path/to/claude-code-api/oauth-proxy.py
Restart=always
[Install]
WantedBy=multi-user.target- Enable and start:
sudo systemctl enable claude-oauth-proxy
sudo systemctl start claude-oauth-proxyIf you're on Linux or Mac, you can use host network mode instead of the proxy:
Edit docker-compose.yml:
services:
claude-code-api:
network_mode: "host"
# Remove 'ports' section when using host modePros: No proxy needed, simpler setup Cons: Less isolation, Linux/Mac only, not recommended for production
- The OAuth proxy only forwards callbacks, it doesn't store credentials
- All communication is local (localhost only by default)
- For production, consider:
- Adding authentication to the proxy
- Using HTTPS
- Restricting which containers can be targeted
- Running behind a reverse proxy
Test the complete flow:
# 1. Start OAuth proxy
python3 oauth-proxy.py
# 2. In another terminal, start container
docker-compose up -d
# 3. Test callback forwarding
curl "http://localhost:8888/oauth/callback?code=test123&state=test-session"
# Should return a success pageIf you encounter issues:
-
Check all services are running:
- OAuth proxy:
curl http://localhost:8888/health - API server:
curl http://localhost:8000/health - Container:
docker ps
- OAuth proxy:
-
Check logs:
# OAuth proxy logs (in terminal where it's running) # Container logs docker logs claude-code-api
-
Verify network connectivity:
# From host to container curl http://localhost:8000/health
Q: Do I need to run the OAuth proxy all the time? A: Only when authenticating MCP servers. Once authenticated, credentials are stored and the proxy isn't needed.
Q: Can I use this with existing authenticated MCP servers?
A: Yes! If you already authenticated MCP servers on your host, just mount your ~/.config/claude directory:
volumes:
- ~/.config/claude:/home/claudeuser/.config/claudeQ: Does this work on Windows?
A: Yes! The OAuth proxy runs on any platform. Just use python instead of python3 on Windows.
Q: How do I stop everything? A:
# Stop OAuth proxy: Ctrl+C in its terminal
# Stop container
docker-compose down