# sap-mcp-bridge — build sources This directory contains the Docker build context for the **`git.alexzaw.dev/alexz/sap-mcp-bridge`** image that the Runtipi app references. The same files are mirrored under `~/projects/sap-mcp-bridge/` so you can iterate on the image outside the Runtipi tree if you prefer; treat the two locations as copies-in-sync. ## Files | File | Role | | -------------- | ----------------------------------------------------------------------------------- | | `Dockerfile` | Node 24 + nginx + gosu + tini, installs 5 MCP servers + supergateway globally. | | `entrypoint.sh`| Boots as root → chowns `/workspace` → drops to `mcp` via gosu → launches 5 gateways on 127.0.0.1:9001–9005 → execs nginx on :8080. | | `nginx.conf` | Path-prefixed reverse proxy (`/cap/mcp`, `/abap/mcp`, …) with SSE/streaming-safe defaults (no buffering, 24h timeouts). | | `build.sh` | `docker build && docker push` to `git.alexzaw.dev/alexz/sap-mcp-bridge:`. | ## How it works The MCP servers are stdio-only. `supergateway` wraps each one as a small HTTP server speaking the MCP "Streamable HTTP" transport. Each gateway binds its own port (9001–9005) on the loopback interface, inside the container only. An internal **nginx** is the only thing that listens on the EXPOSEd port (8080) and routes requests by URL path: ``` 8080/cap/mcp -> 127.0.0.1:9001/mcp 8080/abap/mcp -> 127.0.0.1:9002/mcp 8080/odata/mcp -> 127.0.0.1:9003/mcp 8080/ui5/mcp -> 127.0.0.1:9004/mcp 8080/fiori/mcp -> 127.0.0.1:9005/mcp 8080/healthz -> 127.0.0.1:9001/healthz (aggregate probe) ``` This single-port design is what makes the container Runtipi-deployable behind Traefik, which only routes one port per app. ## Build & push ```bash cd /etc/runtipi/repos/runtipi/apps/sap-mcp-bridge/build ./build.sh # builds + pushes :latest IMAGE_TAG=1.0.0 ./build.sh # tag a specific version ./build.sh --no-cache # forwarded to docker build ``` You must be logged in to the Gitea Docker registry: ```bash docker login git.alexzaw.dev ``` ## Deploy to Runtipi After `build.sh` succeeds: ```bash cd /etc/runtipi/repos/runtipi sudo git add apps/sap-mcp-bridge sudo git commit -m "sap-mcp-bridge: " sudo git push origin main cd /etc/runtipi sudo ./runtipi-cli appstore update sudo ./runtipi-cli app update sap-mcp-bridge:runtipi # for an already-installed app # (first time: install via the Runtipi dashboard so form fields are written) ``` ## Local sanity check (no Runtipi) ```bash docker run --rm -p 8080:8080 \ -v "$PWD/workspace:/workspace" \ git.alexzaw.dev/alexz/sap-mcp-bridge:latest # In another terminal: curl http://127.0.0.1:8080/ # landing page lists endpoints curl http://127.0.0.1:8080/healthz # 200 curl http://127.0.0.1:8080/cap/healthz # 200 once cap-js-mcp-server boots ``` ## Image dependencies (pinned in the Dockerfile) - Base: `node:24-bookworm-slim` - `supergateway@latest` - `@iflow-mcp/cap-js-mcp-server@latest` - `@iflow-mcp/mcp-abap-adt@1.1.0` - `@iflow-mcp/btp-sap-odata-to-mcp-server@1.0.0` - `@ui5/mcp-server@0.2.11` - `@sap-ux/fiori-mcp-server@0.6.49` - OS packages: `tini ca-certificates curl nginx gosu` Bump the pinned versions in `Dockerfile` then rebuild.