# sap-mcp-bridge :: in-container reverse proxy # # Routes a single external port (8080) to five internal supergateway # instances on 127.0.0.1:9001..9005, based on URL path prefix. Tuned # for MCP Streamable HTTP, which uses long-lived streaming responses # (effectively SSE) — so buffering is OFF and timeouts are HOURS, # not seconds. worker_processes 1; pid /tmp/nginx.pid; error_log /dev/stderr warn; events { worker_connections 256; } http { # All temp paths must be writable by the non-root mcp user. client_body_temp_path /tmp/nginx-client-body; proxy_temp_path /tmp/nginx-proxy; fastcgi_temp_path /tmp/nginx-fastcgi; uwsgi_temp_path /tmp/nginx-uwsgi; scgi_temp_path /tmp/nginx-scgi; access_log off; server_tokens off; types_hash_max_size 2048; default_type application/octet-stream; # --- Streaming-HTTP / SSE friendly defaults --------------------- # MCP responses can be long-lived streams. Buffering would break # the stream; default 60s timeouts would kill it mid-flight. proxy_http_version 1.1; proxy_buffering off; proxy_request_buffering off; proxy_read_timeout 24h; proxy_send_timeout 24h; proxy_connect_timeout 10s; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Empty Connection header keeps keepalive to upstream working # (the default would inherit the client's Connection header). proxy_set_header Connection ""; upstream sap_cap { server 127.0.0.1:9001; keepalive 8; } upstream sap_abap { server 127.0.0.1:9002; keepalive 8; } upstream sap_odata { server 127.0.0.1:9003; keepalive 8; } upstream ui5_srv { server 127.0.0.1:9004; keepalive 8; } upstream fiori_srv { server 127.0.0.1:9005; keepalive 8; } server { listen 8080 default_server; # Plain-text landing page so curl / a browser hit on / gives a # cue rather than 404 noise. location = / { default_type text/plain; return 200 "sap-mcp-bridge\nendpoints:\n /cap/mcp\n /abap/mcp\n /odata/mcp\n /ui5/mcp\n /fiori/mcp\n"; } # Aggregate health: probe one upstream. If nginx itself is up # and that gateway answers 200, Traefik will treat the # container as healthy. (Per-gateway probes are exposed below # for finer-grained checks.) location = /healthz { access_log off; proxy_pass http://sap_cap/healthz; } # ---------------- MCP endpoints --------------------------- location = /cap/mcp { proxy_pass http://sap_cap/mcp; } location = /abap/mcp { proxy_pass http://sap_abap/mcp; } location = /odata/mcp { proxy_pass http://sap_odata/mcp; } location = /ui5/mcp { proxy_pass http://ui5_srv/mcp; } location = /fiori/mcp { proxy_pass http://fiori_srv/mcp; } # ---------------- Per-gateway health ---------------------- location = /cap/healthz { access_log off; proxy_pass http://sap_cap/healthz; } location = /abap/healthz { access_log off; proxy_pass http://sap_abap/healthz; } location = /odata/healthz { access_log off; proxy_pass http://sap_odata/healthz; } location = /ui5/healthz { access_log off; proxy_pass http://ui5_srv/healthz; } location = /fiori/healthz { access_log off; proxy_pass http://fiori_srv/healthz; } } }