sap-mcp-bridge: new app — five SAP MCP servers behind one nginx-proxied port
This commit is contained in:
95
apps/sap-mcp-bridge/build/README.md
Normal file
95
apps/sap-mcp-bridge/build/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# 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:<tag>`. |
|
||||
|
||||
## 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: <what changed>"
|
||||
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.
|
||||
Reference in New Issue
Block a user