SAP MCP-RFC Bridge
MCP-RFC bridge for SAP ABAP (RFC-only / SAProuter / ECC R3)
An MCP server that lets an MCP client (e.g. Claude Code) work with SAP ABAP objects over RFC instead of ADT/HTTP. Because it speaks RFC + SAProuter, it reaches systems that expose no HTTP/ADT endpoint — including classic ECC / R/3.
Inspired by the SAP Community blog "Using Claude for SAP ABAP development on RFC-only / SAProuter systems (even ECC R/3)". This is an independent, prototype implementation — not an official SAP or Anthropic product.
Architecture
Claude Code --stdio/MCP--> server.py (FastMCP)
|
sap/tools.py (wraps standard SAP FMs)
|
sap/connection.py (pyrfc Connection, reconnect)
|
sap/config.py (.env -> conn params, SAProuter)
|
pyrfc --RFC/SAProuter--> SAP systemTools exposed
Tool | Purpose | Needs write? |
| Test connection, system info | no |
| Read a table (RFC_READ_TABLE) | no |
| Read ABAP report source | no |
| Read FM source + interface | no |
| Read class/interface source | no |
| Read ONE method of a class | no |
| Public API only (+ dependency APIs) | no |
| Unused-method scan for a package | no |
| Search TADIR for repository objects | no |
| Describe table/structure fields | no |
| Recent ST22 runtime errors | no |
| List transport requests (E070) | no |
| One transport + its object list | no |
| Where-used via WBCROSSGT index | no |
| Read Dynpro definition (via Z-FM) | no |
| Read GUI status/CUA (via Z-FM) | no |
| Syntax-check source, no save (Z-FM) | no |
| Read CDS/DDL source (Z-FM) | no |
| Read program text elements (Z-FM) | no |
| Run ABAP Unit for a class (Z-FM) | no |
| Run ATC check (Z-FM stub) | no |
| Raw ZMCP_ADT_DISPATCH call | read: no / write: yes |
| Activate inactive objects (Z-FM) | yes |
| Write program text elements (Z-FM) | yes |
| Create/update program (INACTIVE) | yes |
| Call an arbitrary RFC-enabled FM | yes |
Custom dispatcher ZMCP_ADT_DISPATCH
The Z-FM tools above route through a custom RFC-enabled FM ZMCP_ADT_DISPATCH
(function group ZMCP_ADT_UTILS) installed on the SAP system — the escape hatch
for features no standard RFC FM exposes. It runs inside SAP, so it can call
non-remote workbench APIs (SYNTAX-CHECK, RS_WORKING_OBJECTS_ACTIVATE,
READ/INSERT TEXTPOOL, DDDDLSRC, ABAP Unit, ATC) and return JSON.
Install the two FMs from abap/ on any SAP system you want to drive
(see abap/README.md for the interfaces and step-by-step
setup). Action → tool map:
Action | Tool | Underlying ABAP |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
RUN_UNIT_TESTS and ATC_CHECK use release-sensitive class APIs — verify/adjust
the ABAP in SE24 for your system (ATC_CHECK ships as an explicit stub). Every
write action goes through the same SAP_ALLOW_WRITE guard.
Text elements use a separate dedicated FM, ZMCP_ADT_TEXTPOOL (same
function group), driven by sap_textpool_read / sap_textpool_write. Flag it
Remote-Enabled in SE37 to use it. sap_textpool_write defaults to
WRITE_INACTIVE (staged; published on program activation), matching the
"nothing goes live until activate" model; pass active=true to write directly.
Write tools are disabled unless SAP_ALLOW_WRITE=true.
Sensitive-table policy: sap_read_table refuses tables holding
credentials/PII (USR02, PA0*, SECSTORE*, …). Override the pattern list via
SAP_TABLE_BLOCKLIST (comma-separated, * wildcards) in .env.
Package whitelist for writes: set SAP_ALLOWED_PACKAGES (e.g.
$TMP,ZPK_SANDBOX*) to restrict sap_write_program to specific packages.
Unset = no package restriction (only SAP_ALLOW_WRITE applies).
FM deny list: sap_run_rfc refuses high-risk function modules (OS command
execution, arbitrary ABAP, mass delete, raw SQL, user admin, file transfer,
kernel admin) even with SAP_ALLOW_WRITE=true. Override the pattern list via
SAP_FM_DENYLIST (comma-separated, * wildcards).
Project layout
MCP_SAP_PRIVATE/
bootstrap.bat copy to a new machine: clones repo + runs setup
setup.ps1 / setup.bat installer + MCP registration
README.md
mcp/ the MCP server (everything it needs to run)
server.py MCP server entrypoint (FastMCP, stdio)
test_connection.py standalone connectivity check
requirements.txt
.env / .env.example base/shared settings (real .env is git-ignored)
profiles/ one <name>.env per SAP system (multi-system)
ds4.env.example per-system profile template
sap/ Python package (the bridge)
config.py .env -> pyrfc params, SAProuter, SDK discovery
connection.py pyrfc wrapper, reconnect, DLL registration
tools.py FM wrappers behind each MCP tool
vendor/ third-party / licensed binaries
nwrfcsdk/ SAP NW RFC SDK (bundled, auto-detected)
pyrfc-3.3.1-*.whl prebuilt pyrfc wheel (offline install)
abap/ ABAP to install on the SAP system (reusable)
README.md install guide + FM interfaces
zmcp_adt_dispatch.abap ZMCP_ADT_DISPATCH (screens, syntax, activate, …)
zmcp_adt_textpool.abap ZMCP_ADT_TEXTPOOL (text elements)Deploy via git (clone-and-go)
This repo is meant for a private git remote: the SAP NW RFC SDK
(mcp/vendor/nwrfcsdk) and the pyrfc wheel are committed, so a fresh clone runs
without any SAP-portal download. Secrets are not committed — .env and
mcp/profiles/*.env are git-ignored; each machine fills them in locally.
First push (once, from this folder)
git init
git add .
git commit -m "SAP MCP-RFC bridge"
git remote add origin https://github.com/ChinhHN-DEV/MCP_SAP_PRIVATE.git
git push -u origin mainThe commit includes the ~60 MB SDK. Keep the remote private — the SDK is licensed and must not be public.
On a new machine (one command)
Edit the REPO= line in bootstrap.bat, copy just that one file to the new
machine, and run it (or bootstrap.bat <git-url>). It clones the repo and runs
setup.ps1. Afterwards, create your connection config:
# single system:
copy mcp\.env.example mcp\.env # then edit
# or multi-system:
copy mcp\profiles\ds4.env.example mcp\profiles\ds4.env # then edit, re-run setup.ps1Quick install on a new machine
Copy the whole folder over, then from inside it run one of:
# Windows (PowerShell)
powershell -ExecutionPolicy Bypass -File .\setup.ps1…or just double-click setup.bat.
setup.ps1 finds Python, installs python-dotenv + mcp, installs the
matching pyrfc wheel (from vendor/, or downloads the right one), verifies
the bundled SDK, creates .env from the template, and registers the sap-rfc
MCP server with Claude Code using this folder's current absolute path — so it
works no matter where the folder was moved to. Afterwards just edit .env and
run python mcp\test_connection.py. The manual steps below are the same thing by
hand.
Multiple SAP systems
Run one MCP server per system, each selected by a profile file. Claude Code
then sees separate, namespaced tool sets (mcp__sap-ds4__…, mcp__sap-qa4__…)
and picks the right system by server name.
Put per-system logon in
mcp/profiles/<name>.env(copymcp/profiles/ds4.env.example):profiles/ds4.env # DEV, SAP_ALLOW_WRITE=true profiles/qa4.env # QA, read-only profiles/prd.env # PROD, read-onlyShared policy (
SAP_TABLE_BLOCKLIST,SAP_FM_DENYLIST, …) stays in the base.env; each profile overrides the base and holds that system's credentials +SAP_ALLOW_WRITE.Run
setup.ps1— it registers one serversap-<name>per profile file (falls back to a singlesap-rfcfrom.envwhen no profiles exist).Test a specific system:
python mcp\test_connection.py --profile qa4
Profile selection precedence: --env-file <path> > --profile <name> >
SAP_PROFILE env var > base .env. sap_ping reports which profile answered.
Keep DEV writable and QA/PROD read-only (SAP_ALLOW_WRITE=false) so the deny
guards differ per system automatically.
Setup (manual)
1. SAP NW RFC SDK (prerequisite for pyrfc)
pyrfc wraps the SAP NetWeaver RFC SDK (licensed; from the SAP Support
Portal). This repo bundles the Windows SDK at mcp/vendor/nwrfcsdk, auto-detected
and registered at runtime (via os.add_dll_directory). No PATH edits needed. To
use a different SDK location, set SAPNWRFC_HOME — it takes precedence over the
bundled copy.
OS runtime prerequisite for the SDK (SAP Note 2573790)
The NW RFC SDK DLL needs the Microsoft Visual C++ 2015-2022 Redistributable
x64 (vcruntime140.dll) present — without it, import pyrfc fails with a
cryptic load error. setup.ps1 warns and links the installer if it is missing.
Patch level of an installed SDK: findstr Patch sapnwrfc.dll.
2. Install Python dependencies
pyrfc has no PyPI wheel for recent Python, so a matching prebuilt wheel is
vendored in mcp/vendor/:
python -m pip install python-dotenv mcp
python -m pip install mcp/vendor/pyrfc-3.3.1-cp312-cp312-win_amd64.whlThe wheel is cp312 / win_amd64 (Python 3.12, Windows 64-bit) from the
SAP-archive/PyRFC GitHub releases. For a different Python version, fetch the
matching wheel from there.
3. Configure the connection
Copy-Item mcp\.env.example mcp\.env
# then edit .envSAProuter example — either put the full route in SAP_ASHOST:
SAP_ASHOST=/H/saprouter.example.com/S/3299/H/sapappserver.internal
SAP_SYSNR=00…or keep a plain host and set the router prefix separately:
SAP_ASHOST=sapappserver.internal
SAP_SYSNR=00
SAP_SAPROUTER=/H/saprouter.example.com/S/32994. Test connectivity (no MCP needed)
python mcp\test_connection.py5. Register the server with Claude Code
claude mcp add sap-rfc -- python "c:\Users\Administrator\Desktop\MCP_SAP_PRIVATE\mcp\server.py"Or add to your MCP client config:
{
"mcpServers": {
"sap-rfc": {
"command": "python",
"args": ["c:\\Users\\Administrator\\Desktop\\MCP_SAP_PRIVATE\\mcp\\server.py"]
}
}
}Safety
Read-only by default. Keep
SAP_ALLOW_WRITE=falseunless you intend to modify objects, and only enable writes against a DEV system.Writes are saved INACTIVE — nothing goes live until you activate it in SAP.
Use an RFC user with the minimum authorizations required.
.envholds credentials — it is git-ignored; never commit it.
Verified on
Read tools (sap_ping, sap_read_table, sap_read_program,
sap_read_function_module, sap_read_class, sap_search_objects) verified
end-to-end against an S/4HANA system (SAP_BASIS 758) reached through a
SAProuter. Class source uses the remote-enabled SIW_RFC_READ_CLIF_SOURCE.
Caveats / limits over pure RFC
Only remote-enabled function modules are callable over RFC. Many workbench FMs (e.g. the
SEO_*class APIs, the ABAPSYNTAX-CHECK) are not RFC- enabled, so some ADT-style features simply aren't reachable this way.CDS/DDL source read is not available over pure RFC on the tested system — there is no remote-enabled FM that returns DDL source text. Use ADT for that.
Object activation and syntax check are likewise not wired up: no clean remote-enabled FM was found on the tested release. Writes therefore stay INACTIVE; activate in SAP GUI/ADT.
RFC_READ_TABLEcannot select rows wider than 512 bytes or long/deep fields; long WHERE clauses are auto-wrapped to the 72-char OPTIONS line limit.FM availability/interfaces can still vary by release — validate on your target.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ChinhHN-DEV/MCP_SAP_PRIVATE'
If you have feedback or need assistance with the MCP directory API, please join our Discord server