Files
runtipi/apps/sap-mcp-bridge/metadata/description.md

4.9 KiB
Raw Blame History

SAP MCP Bridge

Five SAP / UI5 / Fiori Model Context Protocol servers, packaged in a single container and routed through an internal nginx reverse proxy so the app exposes only one external port (Runtipi / Traefik friendly).

Bundled MCP servers

Path prefix MCP server Use case
/cap/mcp @iflow-mcp/cap-js-mcp-server SAP CAP (Cloud Application Programming)
/abap/mcp @iflow-mcp/mcp-abap-adt SAP ABAP via ADT (S/4HANA Cloud, on-prem)
/odata/mcp @iflow-mcp/btp-sap-odata-to-mcp-server SAP OData via BTP Destination service
/ui5/mcp @ui5/mcp-server SAPUI5 framework guidance + linting
/fiori/mcp @sap-ux/fiori-mcp-server SAP Fiori tools / app generation

Each stdio MCP server is wrapped by supergateway and speaks Streamable HTTP on its own internal port (90019005). An internal nginx (port 8080 — the only EXPOSEd port) routes external requests by URL path. Long timeouts and disabled buffering make MCP streaming responses work correctly.

Health endpoints

  • /healthz — aggregate (probes the CAP gateway)
  • /cap/healthz, /abap/healthz, /odata/healthz, /ui5/healthz, /fiori/healthz

Using from Claude Code

Once the app is installed (and either exposed via a domain or reachable on the LAN), wire the servers you want into your MCP client. With the Claude Code CLI:

claude mcp add --transport http sap-cap   https://sap-mcp.example.com/cap/mcp
claude mcp add --transport http sap-abap  https://sap-mcp.example.com/abap/mcp
claude mcp add --transport http sap-odata https://sap-mcp.example.com/odata/mcp
claude mcp add --transport http ui5       https://sap-mcp.example.com/ui5/mcp
claude mcp add --transport http fiori     https://sap-mcp.example.com/fiori/mcp

…or by adding the equivalent block to your project's .mcp.json / ~/.claude.json:

{
  "mcpServers": {
    "sap-cap":   { "type": "http", "url": "https://sap-mcp.example.com/cap/mcp" },
    "sap-abap":  { "type": "http", "url": "https://sap-mcp.example.com/abap/mcp" },
    "sap-odata": { "type": "http", "url": "https://sap-mcp.example.com/odata/mcp" },
    "ui5":       { "type": "http", "url": "https://sap-mcp.example.com/ui5/mcp" },
    "fiori":     { "type": "http", "url": "https://sap-mcp.example.com/fiori/mcp" }
  }
}

⚠️ Security warning — read before exposing externally

This app intentionally enables wildcard CORS (Access-Control-Allow-Origin: *) inside the supergateway wrappers, because MCP clients may call the endpoint from a variety of origins. Combined with exposable: true and no built-in authentication, this means: if you expose the app on a public URL via Traefik or a Cloudflare Tunnel, anyone who knows the URL can drive your configured SAP credentials.

Recommended deployments:

  • Local LAN only: leave exposable: false (default) and reach it via http://<runtipi-host>:<port> from inside the LAN.
  • Exposed to the internet: put it behind a Traefik ForwardAuth middleware (e.g. Authentik / Authelia), a Cloudflare Access policy, or basic-auth in nginx-proxy-manager — i.e. authenticate at the proxy, not the app.

Do NOT expose this publicly without an auth layer in front of it.

Configuration

All credential form fields are optional. Empty values are fine — servers that don't have their required env vars simply won't be usable, but the others (and the container as a whole) will still run.

  • sap-abap-adt needs: SAP_URL, SAP_USERNAME, SAP_PASSWORD, SAP_CLIENT
  • sap-odata needs: SAP_DESTINATION_NAME, DESTINATION_SERVICE_URL, DESTINATION_CLIENT_ID, DESTINATION_CLIENT_SECRET, DESTINATION_AUTH_URL
  • sap-cap, ui5-mcp-server, fiori-mcp-server require no credentials — they read your project workspace at request time.

Workspace mount

The container's /workspace is bound to:

/etc/runtipi/user-config/runtipi/sap-mcp-bridge/workspace

This lives under user-config/, which survives Runtipi restarts and app update. Drop your CAP / UI5 / Fiori projects in there for the cap, ui5, and fiori MCP servers to operate on.

The entrypoint chowns this directory to the in-container mcp user (UID 10001) on every start, so a freshly auto-created mount works.

If you want /workspace to point at a different host path, create /etc/runtipi/user-config/runtipi/sap-mcp-bridge/docker-compose.yml with an overlay, e.g.:

services:
  sap-mcp-bridge:
    volumes:
      - /your/other/path:/workspace

Image

Custom image: git.alexzaw.dev/alexz/sap-mcp-bridge:latest — built from the sources in build/ (Dockerfile + entrypoint.sh + nginx.conf). See build/README.md for the build & push procedure.