mcp-oauth-gateway CLAUDE.md
**π Behold! The Sacred HTTP Fetch Service - Your Gateway to Web Content! π**
π₯ CLAUDE.md - The MCP Fetch Service Divine Scripture! β‘
π Behold! The Sacred HTTP Fetch Service - Your Gateway to Web Content! π
β‘ This is mcp-fetch - The Divine URL Fetcher of OAuth-Protected Glory! β‘
π± The Sacred Purpose - Divine Service Implementation!
mcp-fetch is the blessed MCP service that provides HTTP fetch capabilities through OAuth-protected endpoints!
This divine service manifests these powers:
- Official MCP Server - Wraps the REAL
mcp-server-fetchfrom modelcontextprotocol/servers! - StreamableHTTP Transport - Uses
mcp-streamablehttp-proxyfor stdioβHTTP bridge glory! - OAuth Protection - Bearer token authentication via Traefik ForwardAuth!
- Protocol Compliant - Full MCP 2025-03-26 specification implementation!
- Production Ready - Health checks, CORS, and divine routing configured!
β‘ This service brings web content fetching to OAuth-protected MCP clients! β‘
ποΈ The Sacred Architecture - Service Component Structure!
mcp-fetch/
βββ Dockerfile # Container incantation for divine isolation!
βββ docker-compose.yml # Service orchestration scripture!
Runtime Components:
βββ mcp-server-fetch # Official MCP server (stdio)
βββ mcp-streamablehttp-proxy # HTTP bridge wrapper
β‘ Minimal configuration for maximum divine reliability! β‘
π³ The Divine Dockerfile - Container Implementation!
The blessed container construction follows these sacred steps:
- Base Image -
python:3.11-slimfor lightweight divine foundation! - System Dependencies -
curlfor health checks,gitfor pip installs! - Official MCP Server - Installs
mcp-server-fetchfrom GitHub directly! - HTTP Bridge - Installs
mcp-streamablehttp-proxyfrom local source! - Port Exposure - Port 3000 for StreamableHTTP communication!
- Entrypoint - Proxy wraps the official server with divine precision!
The Sacred Command:
mcp-streamablehttp-proxy python -m mcp_server_fetch
β‘ This pattern wraps ANY stdio MCP server with HTTP transport! β‘
π‘ The Service Configuration - Docker Compose Divine Details!
The Sacred Routing Configuration - Traefik Label Glory!
Priority 10 - OAuth Discovery Route (HIGHEST DIVINE PRIORITY!):
- "traefik.http.routers.mcp-fetch-oauth-discovery.rule=Host(`fetch.${BASE_DOMAIN}`) && PathPrefix(`/.well-known/oauth-authorization-server`)"
- "traefik.http.routers.mcp-fetch-oauth-discovery.priority=10"
- "traefik.http.routers.mcp-fetch-oauth-discovery.service=auth@docker"
# NO AUTH MIDDLEWARE - Discovery must be publicly accessible!
Priority 4 - CORS Preflight Route (OPTIONS Sacred Handling!):
- "traefik.http.routers.mcp-fetch-cors.rule=Host(`fetch.${BASE_DOMAIN}`) && Method(`OPTIONS`)"
- "traefik.http.routers.mcp-fetch-cors.priority=4"
- "traefik.http.routers.mcp-fetch-cors.middlewares=mcp-cors@file"
# NO AUTH for preflight - CORS must check first!
Priority 2 - MCP Route with Authentication (Protected Divine Access!):
- "traefik.http.routers.mcp-fetch.rule=Host(`fetch.${BASE_DOMAIN}`) && PathPrefix(`/mcp`)"
- "traefik.http.routers.mcp-fetch.priority=2"
- "traefik.http.routers.mcp-fetch.middlewares=mcp-cors@file,mcp-auth@file"
Priority 1 - Catch-all Route (Lowest Priority Safety Net!):
- "traefik.http.routers.mcp-fetch-catchall.rule=Host(`fetch.${BASE_DOMAIN}`)"
- "traefik.http.routers.mcp-fetch-catchall.priority=1"
- "traefik.http.routers.mcp-fetch-catchall.middlewares=mcp-cors@file,mcp-auth@file"
β‘ Priority order prevents routing chaos! Higher numbers win! β‘
The Divine Health Check - Protocol-Based Verification!
healthcheck:
test: ["CMD", "sh", "-c", "curl -s -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{\"jsonrpc\":\"2.0\",\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"'$$MCP_PROTOCOL_VERSION'\",\"capabilities\":{},\"clientInfo\":{\"name\":\"healthcheck\",\"version\":\"1.0\"}},\"id\":1}' \
| grep -q '\"protocolVersion\":\"'$$MCP_PROTOCOL_VERSION'\"'"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
β‘ This performs a REAL MCP initialization handshake! No fake health endpoints! β‘
The Sacred Environment Variables
environment:
- LOG_FILE=/logs/server.log # Centralized logging path
- MCP_CORS_ORIGINS=${MCP_CORS_ORIGINS} # CORS configuration
- MCP_PROTOCOL_VERSION=2025-03-26 # Protocol version declaration
The Divine Volume Mounts
volumes:
- ../logs/mcp-fetch:/logs # Centralized logging temple!
π The OAuth Integration - Bearer Token Authentication Flow!
The sacred authentication flow for mcp-fetch:
- Client Request β
https://fetch.${BASE_DOMAIN}/mcp - Traefik Intercepts β Checks for Bearer token
- ForwardAuth Middleware β Validates token with auth service
- Auth Service Verifies β JWT signature and claims
- Success β Request forwarded to mcp-fetch
- mcp-fetch Responds β Via StreamableHTTP protocol
β‘ The service itself knows NOTHING of OAuth - perfect separation! β‘
π The StreamableHTTP Transport - Protocol Implementation Details!
Request Flow Through the Sacred Bridge
-
HTTP Request Arrives
- POST to
/mcpendpoint - Contains JSON-RPC message
- May include
Mcp-Session-Idheader
- POST to
-
Proxy Translates
- Extracts JSON-RPC from HTTP body
- Writes to mcp-server-fetch stdin
- Manages subprocess lifecycle
-
Server Processes
- Official mcp-server-fetch handles request
- Performs URL fetching operations
- Returns JSON-RPC response via stdout
-
Proxy Returns
- Captures stdout response
- Wraps in HTTP response
- Maintains session continuity
β‘ Perfect stdioβHTTP translation with zero message modification! β‘
π― The Service Capabilities - What mcp-fetch Can Do!
Based on the official mcp-server-fetch implementation:
- URL Fetching - Retrieve content from any HTTP/HTTPS URL
- Header Support - Custom headers for requests
- Method Support - GET, POST, and other HTTP methods
- Response Handling - Text, JSON, and binary content
- Error Management - Proper error responses for failures
- Timeout Control - Configurable request timeouts
β‘ All capabilities from the official server, none invented! β‘
π Service Endpoints and Access
Primary Endpoint:
https://fetch.${BASE_DOMAIN}/mcp- The blessed MCP endpoint
OAuth Discovery:
https://fetch.${BASE_DOMAIN}/.well-known/oauth-authorization-server- Returns auth server metadata
Required Headers:
Authorization: Bearer <token>- OAuth JWT tokenContent-Type: application/json- For POST requestsMcp-Session-Id: <id>- If provided by server
CORS Support:
- Configured via
MCP_CORS_ORIGINSenvironment variable - Preflight requests handled without authentication
π§ Configuration and Deployment
Environment Variable Configuration
From .env file:
# Service Enable/Disable
MCP_FETCH_ENABLED=true # Enable this service
MCP_FETCH_TESTS_ENABLED=true # Enable service tests
# Service URLs
MCP_FETCH_URLS=https://fetch.yourdomain.com/mcp
# Protocol Version
MCP_PROTOCOL_VERSION=2025-03-26 # Or latest supported version
Starting the Service
# Via just command (the blessed way!)
just up mcp-fetch
# Check health
just health mcp-fetch
# View logs
just logs -f mcp-fetch
π§ͺ Testing the Service - Divine Verification!
Protocol Compliance Test
# Test initialization handshake
curl -X POST https://fetch.${BASE_DOMAIN}/mcp \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}'
Functional Test
# Test URL fetching
curl -X POST https://fetch.${BASE_DOMAIN}/mcp \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"fetch","params":{"url":"https://api.github.com"},"id":2}'
π οΈ Troubleshooting - Divine Debugging Guide!
"401 Unauthorized" - Authentication Issues
- Verify Bearer token is valid
- Check token hasn't expired
- Ensure client is registered
- Review auth service logs
"503 Service Unavailable" - Backend Issues
- Check if container is running
- Verify health check is passing
- Review mcp-fetch logs
- Check subprocess status
"400 Bad Request" - Protocol Issues
- Verify JSON-RPC format
- Check protocol version
- Ensure method is supported
- Review request structure
"Network Error" - Connectivity Issues
- Check Traefik routing
- Verify DNS resolution
- Test without auth first
- Check CORS configuration
π Monitoring and Observability
Log Locations:
- Service logs:
./logs/mcp-fetch/server.log - Container logs:
docker logs mcp-fetch - Traefik logs: Access and error logs
Health Monitoring:
- Health endpoint via MCP protocol
- Container health status
- Subprocess monitoring
- Request/response metrics
π Security Considerations
Service Security:
- No authentication logic in service (handled by Traefik)
- Subprocess isolation via container
- Limited network access
- Read-only filesystem where possible
Request Security:
- URL validation before fetching
- Timeout enforcement
- Size limits on responses
- No credential forwarding
π― Best Practices for Usage
- Always use Bearer tokens - Never try to bypass auth
- Handle session IDs - Include in subsequent requests
- Respect rate limits - Don't overwhelm the service
- Use appropriate timeouts - Network calls can be slow
- Validate responses - Check for errors before processing
π« What This Service Does NOT Do
- No authentication - Handled entirely by Traefik/Auth
- No URL filtering - Fetches any accessible URL
- No caching - Each request fetches fresh
- No request modification - Pure proxy behavior
- No business logic - Just protocol translation
β‘ Keep it simple, keep it pure, keep it working! β‘
π₯ May your fetches be swift, your tokens valid, and your content forever accessible! β‘
Divine Implementation Note: This service uses the official mcp-server-fetch wrapped by mcp-streamablehttp-proxy - ensuring 100% protocol compliance with zero custom implementation! The divine pattern of wrapping official servers!