Skip to main content
Glama
hugoconsulting

SAP MCP Server

README.md
# sap-mcp-server

**English** | [ζ—₯本θͺž](README.ja.md)

> Securely operate SAP ABAP and BTP services from MCP-compatible AI clients.

Connect to SAP **ABAP** and **BTP services** from general MCP-compatible AI clients such as
**Claude Code**, **Codex**, and **Gemini CLI**. Distributed as a single self-contained binary
(Node.js SEA) for Linux.

> This tool is **not standalone**: it requires a backend service deployed on **SAP BTP, Cloud Foundry**.
> Through strong, multi-layered security it accesses **on-premise / RISE** SAP environments.

> **πŸ“¦ Binaries have moved.** Releases are now published from
> [sap-support/sap-mcp-server](https://github.com/sap-support/sap-mcp-server). This repository holds
> the source and is where development happens; it no longer publishes binaries. Releases up to
> v0.14.2 remain available here for reference.

---

## πŸ”’ Security

Security is enforced in **multiple layers (defense in depth)**, so AI-driven access to SAP
stays controlled and auditable.

| Layer | Control |
|---|---|
| **Access scope** | Restrict access to **Full**, **Reference-only (read-only)** or **Development-only**. |
| **Landscape** | Per-landscape access control for **DEV / QAS / PRD**. |
| **Authentication** | Connects only over a secure, authenticated channel; SAP credentials are never held by the client. |
| **Secret handling** | Connection secrets are kept **local only** and are **never** committed or embedded in the binary. |

### Security pattern: role-based authorization

Three scopes β€” `mcp` (**Full**), `mcp_readonly` (**Reference-only**) and `mcp_developer` (**Development-only**) β€” are enforced in layers (the reference backend implements this; bring-your-own backends are encouraged to follow it):

1. **Scope gate (app level)** β€” every MCP route is mounted behind "require `mcp` *or* `mcp_readonly` *or* `mcp_developer`"; a token with none of these scopes is rejected (403) before any handler runs.
2. **Environment gate (per destination)** β€” each destination is tagged `DEV` / `QAS` / `PRD`. `mcp_developer` may reach only `DEV`/`QAS`; `mcp_readonly` may also reach `PRD` but for reads only. Untagged destinations are denied for restricted scopes (fail-closed). `mcp` reaches all.
3. **Method gate (REST relays)** β€” `mcp_readonly` may use any method on `DEV`/`QAS` and only `GET` on `PRD`. `mcp_developer` is limited to `GET` (external app relays allow any method on `DEV`/`QAS`).
4. **No function modules in production** β€” `mcp_readonly` is denied `sap_call_fm` against `PRD` **regardless of the `commit` flag**. Many function modules write without an explicit commit, so "read-only" cannot be delegated to a caller-supplied flag.
5. **Hard-deny** β€” PII tools (IAS / IPS) and CLI execution are `mcp`-only, regardless of environment.
6. **ABAP writes stay in development** β€” write / delete / transport / activate target `DEV`-tagged destinations only, for every scope. `QAS` and `PRD` are not modifiable under standard SAP practice; changes arrive by transport.

| Tool | Full (`mcp`) | Reference-only (`mcp_readonly`) | Development-only (`mcp_developer`) |
|---|---|---|---|
| `sap_list_destinations` | all | all | DEV/QAS only |
| `sap_use_destination` / `sap_current_destination` | all envs | all envs | all envs |
| `sap_select_table` | all envs | all envs (read) | DEV/QAS only |
| `sap_adt_freestyle` / `osql` / `ddic` | all envs | all envs (read) | DEV/QAS only |
| `sap_abap_read_source` | all envs | all envs (read) | DEV/QAS only |
| `sap_call_fm` (incl. `commit`) | all envs | DEV/QAS only (**PRD denied**) | DEV/QAS only |
| `sap_abap_write_source` / `write_fm` / `delete_source` / `activate` (writes) | DEV-role destinations only | DEV-role destinations only | DEV-role destinations only |
| `sap_create_transport` / `sap_release_transport` | DEV-role destinations only | DEV-role destinations only | DEV-role destinations only |
| `sap_call_ias_admin` (IAS Β· PII) | all envs | **denied** | **denied** |
| `sap_call_ips_job` (IPS Β· PII) | all envs | **denied** | **denied** |
| `sap_call_cf_api` / `bwz_content` / `ctms_api` / `forms_api` / `cis_api` / `cpi_api` / `ans_api` / `sbpa_api` / `datasphere_api` / `calm_api` | all envs, any method | any method on DEV/QAS, `GET` on PRD | `GET` + DEV/QAS only |
| `sap_call_s4_api` / `sap_call_soap` (S/4 OData Β· REST Β· SOAP) | all envs, any method | any method on DEV/QAS, `GET` on PRD | `GET` + DEV/QAS only |
| `app_call_jira_api` / `app_call_smartdb_api` / `sap_call_ibp_api` | all envs, any method | any method on DEV/QAS, `GET` on PRD | any method on DEV/QAS |
| `sap_call_btp_cli` / `cf_cli` / `datasphere_cli` | all envs | **denied** | **denied** |

Operational controls (defense in depth): (1) MCP key issuance, (2) scope `mcp` / `mcp_readonly` / `mcp_developer`, (3) key revoke, (4) audit log of every call, (5) per-destination environment tag.

## Capabilities

**35 tools.** The authoritative list β€” per-tool descriptions, official API references and per-scope
permissions β€” is [`src/toolCatalog.json`](src/toolCatalog.json).

- **Connection**
  - List destinations, switch the active destination, show the current one
- **SAP ABAP**
  - **Run any remote-enabled Function Module / BAPI without cumbersome web service configuration.**
  - Function Modules (RFC / BAPI)
  - Table read (RFC_READ_TABLE-equivalent)
  - ADT SQL / Open SQL / DDIC preview
  - **Add-on development** β€” read / write / activate / delete reports and function modules (SE37) via ADT
  - **Transport management** β€” create / release transport requests (CTS)
  - **S/4HANA APIs** β€” OData V2 / V4, REST and SOAP services published on the system
    (the transport for [SAP Business Accelerator Hub](https://api.sap.com/) APIs)
- **SAP BTP services**
  - Cloud Identity Services (IAS) Admin / SCIM
  - Identity Provisioning (IPS) Jobs / JobLogs
  - Cloud Foundry API v3
  - Build Work Zone (Content API)
  - Cloud Transport Management (cTMS) v2
  - Forms Service by Adobe
  - Cloud Information Service (CIS Central)
  - Integration Suite (CPI) Audit / Monitoring
  - Alert Notification Service (ANS)
  - Build Process Automation (SBPA)
  - Datasphere (public REST / OData API)
  - Cloud ALM (REST API)
- **SAP applications**
  - Integrated Business Planning (IBP) OData API
- **CLI execution** (`mcp` scope only)
  - `btp` CLI / `cf` CLI / `datasphere` CLI
- **External app relays**
  - JIRA REST API v3
  - SmartDB REST API v3

## Install

Download the Linux binary from the GitHub Releases of
[sap-support/sap-mcp-server](https://github.com/sap-support/sap-mcp-server/releases).

```bash
curl -fsSL https://github.com/sap-support/sap-mcp-server/releases/latest/download/install-sap-mcp.sh | bash
```

### Verifying a download

Every binary ships with a `*.sha256` checksum and a GitHub build provenance attestation. The binary
is additionally signed with [sigstore](https://www.sigstore.dev/) β€” keyless, so there is no
long-lived private key to protect; the signing identity is the release workflow itself.

```bash
sha256sum -c sap-mcp-server-linux.sha256

# sigstore signature (requires cosign)
cosign verify-blob sap-mcp-server-linux \
  --bundle sap-mcp-server-linux.cosign.bundle \
  --certificate-identity-regexp '^https://github.com/sap-support/sap-mcp-server/' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

# build provenance (requires GitHub CLI 2.49 or later)
gh attestation verify sap-mcp-server-linux --repo sap-support/sap-mcp-server
```

> Binaries released here up to **v0.14.2** were signed under the
> `hugoconsulting/sap-mcp-server` identity β€” use that identity when verifying those older assets.

## Configuration

The binary reads a `connections.json` describing one or more backend connections. It is read by the
**binary itself** (independent of the AI client), in this lookup order:

`$SAP_MCP_CONFIG` β†’ `~/.config/sap-mcp-server/connections.json` β†’ next to the executable.

### connections.json format

```json
{
  "defaultConnection": "primary",
  "connections": {
    "primary": {
      "defaultDestination": "AC1",
      "relayUrl": "https://your-backend.example.com",
      "relayBasePath": "/api/tableread/mcp",
      "clientId": "sb-xxxxxxxx",
      "clientSecret": "xxxxxxxx",
      "tokenUrl": "https://<subdomain>.authentication.<region>.hana.ondemand.com/oauth/token"
    }
  }
}
```

| Field | Required | Description |
|---|---|---|
| `defaultConnection` | optional | Connection used when a tool call omits `connection`. Defaults to the first entry. |
| `defaultDestination` | optional | SAP destination (SID / Destination name) used when a tool call omits `destination`. |
| `relayUrl` | **required** | Base URL of the **backend** (the backend host itself, **not** the approuter). No trailing slash. |
| `relayBasePath` | **required*** | Path where the backend mounts the MCP relay. **It must match your backend.** The provided reference backend mounts it at **`/api/tableread/mcp`**. |
| `clientId` / `clientSecret` | **required** | OAuth2 `client_credentials` of the XSUAA service key that protects the backend. |
| `tokenUrl` | **required** | XSUAA token endpoint (ends with `/oauth/token`). |

> ⚠ **Most common failure β€” "cannot connect / tools return 404".**
> If `relayBasePath` is omitted it defaults to `/api/mcp`, which does **not** match the reference
> backend (mounted at `/api/tableread/mcp`), so every relay call 404s. Always set `relayBasePath`
> to your backend's actual MCP mount path.

### Getting the values (recommended)

Ask your backend administrator to issue you an MCP key. In the reference backend's **MCP admin** app,
open your approved request and click **"Get credentials"**. The dialog shows every field and provides:

- **Copy all** β€” copies the complete `connections.json` to the clipboard, and
- **Download connections.json** β€” saves a ready-to-use file.

`relayUrl`, `relayBasePath`, `clientId`, `clientSecret`, and `tokenUrl` are already filled in; you only
set **`defaultDestination`** (and optionally the connection name) in the dialog before copying/downloading.

> Credentials are shown **once**. If you miss them, ask the admin to **rotate** the key.

### Create / update the file

```bash
mkdir -p ~/.config/sap-mcp-server
# New install β€” move the downloaded file into place:
mv ~/Downloads/connections.json ~/.config/sap-mcp-server/connections.json
chmod 600 ~/.config/sap-mcp-server/connections.json
```

To add another landscape, add a second entry under `connections` (e.g. `"dev"`, `"prd"`), then either
set `defaultConnection` or pass the `connection` argument per tool call. Keep secrets **local only** β€”
never commit `connections.json`.

## Client Configuration

Register the binary in your AI client, then **restart the client** (or reconnect its MCP servers) so it
reloads. The MCP server name is arbitrary; `sap-mcp-server` is used below.

### Claude Code (CLI)

`install-sap-mcp.sh` auto-registers the server in `~/.claude.json`. To register manually:

```bash
claude mcp add sap-mcp-server -- /path/to/sap-mcp-server-linux
```

…or edit `~/.claude.json` directly:

```json
{ "mcpServers": { "sap-mcp-server": { "command": "/path/to/sap-mcp-server-linux", "args": [] } } }
```

Verify with **`/mcp`** inside Claude Code β€” it should list `sap-mcp-server` as connected. After you
**update the binary or `connections.json`**, run `/mcp` β†’ reconnect (or restart Claude Code) to pick up
the change.

### Claude Desktop

- **Linux:** `~/.config/Claude/claude_desktop_config.json`

```json
{ "mcpServers": { "sap-mcp-server": { "command": "/path/to/sap-mcp-server-linux", "args": [] } } }
```

Restart Claude Desktop after editing.

### Gemini CLI (`~/.gemini/settings.json`)

```json
{ "mcpServers": { "sap-mcp-server": { "command": "/path/to/sap-mcp-server-linux", "args": [] } } }
```

Restart the Gemini CLI session after editing. (The binary still reads `connections.json` from the lookup
order above β€” the client config only points at the binary.)

## Build (developers)

```bash
npm ci
npm run build:bundle    # esbuild β†’ CJS bundle
npm run build:bin:linux # Node SEA blob + postject β†’ single binary
```

## Backend

Actual SAP communication and the security controls above are performed by a **backend** that this
server connects to over a secure channel. A **compatible backend is required** (Bring Your Own Backend).

- The REST contract a backend must satisfy is defined in [docs/BACKEND-CONTRACT.md](docs/BACKEND-CONTRACT.md).
- A reference backend is **not** included in this repository. A production-ready backend
  (setup, connection configuration, and operation) is **provided separately under a consulting engagement**.
  Contact: contact@hugoconsulting.com

## Security Policy

Please report vulnerabilities via [SECURITY.md](SECURITY.md).

## License

[Apache License 2.0](LICENSE).
"SAP" and SAP product names are trademarks of SAP SE. This project is not affiliated with,
endorsed by, or sponsored by SAP SE. See [NOTICE](NOTICE).