Skip to main content
Glama
romankorim

sap-mcp-server

by romankorim

sap-mcp-server

An MCP server that gives Claude (Desktop, Code, API) read access and approval-gated write access to SAP ECC and S/4HANA through OData and RFC/BAPI, without the proprietary SAP NetWeaver RFC SDK. The OData side talks to the SAP Gateway over HTTP. The RFC side runs through a small Node bridge on open-rfc, an Apache-2.0 licensed package that implements the RFC protocol without the SAP SDK. Every call is written to an audit log.

Why

SAP Joule ships with S/4HANA Cloud and with recent S/4HANA on-premise releases connected to BTP. ECC 6.0 has no Joule, and the only supported route to one is a migration. This server is the sidecar pattern: SAP stays as it is, the model runs where you choose (Claude Desktop, Claude Code, the Claude API, Amazon Bedrock), and the only thing between them is this process. It uses the two interfaces most SAP systems already expose, OData on the Gateway and RFC on the application server, and writes every call to an audit log.

Related MCP server: abap-adt-mcp

Tools

Tool

Path

What it does

sap_ping()

OData

Reads the Gateway service catalog; connection test

list_services(filter_text)

OData

Lists OData services registered on the Gateway, optionally filtered by substring

odata_query(service, entity_set, filter, select, top, orderby)

OData

Reads any entity set ($filter, $select, $top capped at 200, $orderby)

get_material(material)

OData

Material master. S/4HANA API_PRODUCT_SRV by default; on ECC point SAP_SVC_MATERIAL to a Z service

list_production_orders(plant, top)

OData

Production orders. S/4HANA API_PRODUCTION_ORDER_2_SRV by default; on ECC a Z service

list_purchase_orders(supplier, top)

OData

Purchase orders. S/4HANA API_PURCHASEORDER_PROCESS_SRV by default; on ECC a Z service

create_purchase_requisition(material, quantity, plant, confirm)

write

Without confirm=True returns a proposal only. The SAP write itself (BAPI_PR_CREATE) is not implemented yet

rfc_ping()

RFC

RFC_SYSTEM_INFO: SID, host, release, database

read_table(table, fields, where, max_rows, skip_rows)

RFC

RFC_READ_TABLE on any table the RFC user is authorized to read. One row is limited to 512 bytes, so pass a field list on wide tables

table_fields(table)

RFC

DDIF_FIELDINFO_GET: field names, types, lengths, descriptions

bapi_call(name, params)

RFC

Calls a BAPI or function module from the read-only allowlist in rfc_tools.py (GETLIST, GETDETAIL, GETOPENITEMS and similar). The server rejects names outside the list

ted_search(preset, cpv, days, country, only_open, limit)

TED

Searches EU public tenders on Tenders Electronic Daily by CPV code. Needs no SAP connection

ted_notice(publication_number)

TED

Details of one TED notice: lots, deadlines, estimated values, CPV codes, place of performance

Requirements

  • Python 3.10 or newer

  • Node.js 22.14 or newer for the RFC tools (open-rfc requires it). The OData and TED tools work without Node

  • An SAP user with the authorizations you intend to grant: Gateway service access for OData; S_RFC plus S_TABU_DIS or S_TABU_NAM for read_table

  • Network access from the machine running this server to the Gateway HTTP(S) port and to the application server RFC port (33NN, where NN is the system number)

Install

Clone the repository (git clone https://github.com/romankorim/sap-mcp-server.git), then:

cd sap-mcp-server
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
cd rfc-bridge && npm install && cd ..
chmod +x run.sh

Configure

cp .env.example .env

Edit .env:

Variable

Meaning

SAP_BASE_URL

OData root on the Gateway, usually https://<host>:<port>/sap/opu/odata/sap

SAP_CLIENT

SAP client number

SAP_USER, SAP_PASSWORD

SAP user for OData and, unless SAP_RFC_USER is set, for RFC

SAP_VERIFY_TLS

1 (default) verifies the server certificate; 0 only for test systems with self-signed certificates

SAP_ASHOST, SAP_SYSNR

Application server host and system number for RFC

SAP_LANG

RFC logon language, default EN

SAP_RFC_CLIENT, SAP_RFC_USER, SAP_RFC_PASSWORD

Optional separate technical user for RFC

AUDIT_LOG_PATH

Audit log file; a relative path is resolved next to server.py. Default audit.jsonl

NODE_BIN

Path to the node binary when it is not on PATH. Claude Desktop starts servers with a minimal PATH, so on macOS this is usually needed

TED_LANG

Preferred language of multilingual TED fields, default eng

SAP_ALLOW_SENSITIVE_TABLES

1 disables the sensitive-table denylist in read_table; leave unset in production

SAP_SVC_*, SAP_ES_*

OData service and entity set names behind the three convenience tools; see .env.example

.env is re-read on every tool call, so a changed host or password takes effect without restarting the client. Values in .env take precedence over the process environment. Single-quote values that contain spaces or shell characters.

Run

./run.sh

run.sh loads .env, picks .venv/bin/python when it exists (otherwise $PYTHON or python3) and starts server.py on stdio. MCP clients start it the same way; you only run it by hand to see startup errors. On Windows call the venv interpreter directly with server.py as the argument; the server reads .env itself.

Claude Desktop

Quit Claude Desktop completely before editing the config file. The app rewrites claude_desktop_config.json from memory when it quits, so it overwrites any edit made while it is running.

File location: macOS ~/Library/Application Support/Claude/claude_desktop_config.json, Windows %APPDATA%\Claude\claude_desktop_config.json.

{
  "mcpServers": {
    "sap": {
      "command": "/absolute/path/to/sap-mcp-server/run.sh",
      "args": []
    }
  }
}

Start the app again. The sap tools appear in the tools list; sap_ping and rfc_ping are the first calls to try.

Claude Code

claude mcp add sap -- /absolute/path/to/sap-mcp-server/run.sh

Security model

  • Read-only by default. All OData tools use GET. All RFC tools call read-only function modules.

  • bapi_call accepts only names in the READ_BAPIS set in rfc_tools.py. Extending the list is a code change, not a runtime option.

  • read_table reads whatever the RFC user is authorized to read, except tables that hold credentials, secrets or personal data: USR*, USH*, RSEC*, SEC*, PA0*, PA9*, HRP*, T77*, RFCDES, USRBAPI, SECSTORE and the SSF_PSE tables are refused unless SAP_ALLOW_SENSITIVE_TABLES=1 is set for an audited admin session. Restrict the user with S_TABU_DIS or S_TABU_NAM on the SAP side as well.

  • Writes are two-step. create_purchase_requisition returns a proposal unless confirm=True is passed; the intended flow is that a person reviews the proposal and the client calls again with confirm=True. The SAP write itself is not implemented yet.

  • Credentials come from .env or the environment; the server never logs them. The audit record stores the SAP user name, not the password.

  • TLS certificate verification is on by default.

  • The audit log is one JSON line per call, appended to AUDIT_LOG_PATH:

{"ts": "2026-10-01T09:12:44+00:00", "user": "SAPUSER", "tool": "read_table", "args": {"table": "MARA", "fields": "MATNR,MTART,MATKL", "where": "MTART = 'FERT'", "max_rows": 20, "skip_rows": 0}, "status": "ok", "ms": 412, "note": "rfc_user=SAPUSER"}

Fields: ts (UTC), user (SAP_USER), tool, args (the call arguments, so filters and WHERE clauses end up in the log), status (ok, error, proposed, not_implemented, or http_<code> for failed OData requests), ms, note. Treat the file as sensitive: it contains every query sent to SAP.

Known limits

  • RFC_READ_TABLE returns each row as one character line of at most 512 bytes. Wide tables need an explicit field list. Selecting RPRCTR from FAGLFLEXT fails on the systems we tested.

  • The where argument is split into 72-character OPTIONS lines on whitespace. A single token longer than 72 characters is rejected.

  • odata_query caps top at 200.

  • On ECC the S/4HANA API_* OData services do not exist. Point SAP_SVC_* and SAP_ES_* to your own Z services, or use the RFC tools.

  • create_purchase_requisition does not write to SAP yet.

  • The TED API answers with HTTP 429 above roughly 10 requests per minute.

  • OData V2 only.

  • The RFC bridge starts a Node process per call, with no connection pooling. Each call opens a new logon, which adds latency.

Roadmap

  • BAPI_PR_CREATE write path behind the existing confirm=True gate

  • S/4HANA API_* style read services on ECC through Z Gateway services

  • OData V4

Maintainer

Maintained by iteractive.ai, AI implementation for SAP and enterprise systems. Commercial support and production deployments: https://iteractive.ai/services/claude-sap-mcp

License

MIT, see LICENSE.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to integrate with SAP systems via OData REST APIs for querying entity sets, performing CRUD operations, and executing function imports. It features automatic service discovery, CSRF token management, and smart connection handling without requiring the SAP RFC SDK.
    11
    12
    -
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants like Claude Code to directly connect to SAP ABAP systems via the ADT REST API with read/write capabilities, featuring AI-friendly high-level tools and built-in safety measures such as read-only mode, prefix whitelisting, and automatic locking.
    9
    313 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants and n8n workflows to interact with SAP S/4HANA and ECC systems via OData, IDoc, and RFC/BAPI, with governed read-only-by-default access and multiple authentication types.
    3
    ISC
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to discover, inspect, and call SAP RFC-enabled function modules (BAPIs/RFCs) with configurable read/write policies, transaction support, audit logging, and ABAP source retrieval.
    6
    MIT