listSystems
List Systems
List the configured ABAP systems (destinations) this server can reach. Call this first to pick the destination to pass to all other tools.
Takes no parameters.

io.github.williansaezPublished by GitHub account williansaezv2.8.2Updated Nov 3, 2026
ABAP development from Claude and other MCP hosts: source, transports, tests, ATC, debugger
MCP server that gives an assistant Eclipse-ADT-style access to configured SAP ABAP systems: read, edit, activate, test and transport ABAP code.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Follow the launch instructions in the repository.
Let Claude read, write, test and check ABAP code on your SAP systems.
English · Português (Brasil) · Deutsch · Project site
[npm version] [CI] [License: MIT] [Node.js] [MCP Registry] [Project site]
You type a sentence in Claude. You get back an activated class, green unit tests and a transport number. abap-adt-mcp is the server in between: a Model Context Protocol server that gives Claude Desktop, Claude Code, VS Code or any other MCP host the same ADT services Eclipse uses, on every SAP system you configure, S/4HANA Cloud and on-prem alike. 173 tools, one process, and guard rails the server enforces itself: a destination marked read-only refuses every write before it reaches SAP, whatever the host approves.
See it in motion. The project site has seven short films, the setup in three steps and what to ask the model.
Before you connect a production system
- The model acts as your SAP user and can do nothing Eclipse would refuse you. What it reads (source, dumps, table rows where you open them) is sent to the model.
- A destination without a
policyblock is writable in every package your user may edit; table data stays closed until you open it.- Recommended: development and test systems only. If a production destination must exist, give it the
PRDpolicy of step 4: the server enforces it before any SAP call, whatever the host approves, so a careless prompt cannot write where the policy forbids it (For administrators).
That is the whole idea. You type a sentence. The model picks the tools, the server locks the object, writes, activates and unlocks it, and the unit tests come back green with a transport number attached. Ask for the same change on a production system and the answer is policyDenied before a single SAP call goes out: the guard rails live in the server, not in the chat window.
Seven short films show this and the single jobs behind it, a short dump traced to its line, an ATC run with its quickfixes, a transport review, a class created with its test, an ABAP Cloud readiness check. They are on the project site.
Three prerequisites:
SAP_BR_DEVELOPER in the standard delivery); on-prem, ask your Basis team for the /sap/bc/adt service in SICF and the usual ADT authorizations.authType: sso, the default); not needed for basic, oauth or sso2.Create the folder .abap-adt-mcp in your home directory and the file systems.json inside it, one entry per system (a "destination"):
C:\Users\<your user name>\.abap-adt-mcp. Paste the JSON into Notepad and in Save As set "Save as type" to "All files" and the name to systems.json, otherwise Notepad saves systems.json.txt and the server finds nothing./Users/<you>/.abap-adt-mcp (Finder, Shift-Cmd-G, ~); any editor.DEV is your name for the system and the word you will use in chats; "default": true lets you omit it.url: the address you open the launchpad or Eclipse with, without a path.client: the client your SSO session logs on to (About in the launchpad's user menu shows it). A wrong client shows up later as "not authorized" on objects you can open in Eclipse.authType defaults to sso: a browser window opens once for the login, like Eclipse ADT. Other modes: Authentication.policy.allowedPackages: the packages the model may write to, exact names or patterns (ZFIN, Z*). Leave it out and every package you can edit in Eclipse is writable; start with one.Production and on-prem systems come in step 4, after the first successful call.
The package is on npm as abap-adt-mcp; npx fetches it. Claude Desktop, no terminal: first block. Claude Code: one command. VS Code, Cursor and others: pointer below. Every entry passes the server two settings: SAP_SYSTEMS_FILE (where systems.json is) and MCP_TOOLSETS=focused, which publishes the 114 everyday development tools instead of all 173 so the tool schemas do not eat the chat's context (drop it when you need the debugger, traces, abapGit, RAP or refactoring).
Claude Desktop, no terminal needed:
claude_desktop_config.json; open the file in Notepad or any editor. If Settings has no Developer tab, your Claude Desktop is managed by IT: ask them to add the entry below."mcpServers", add only the "abap-adt-mcp" entry inside it; if it is empty, paste the whole block.<you> with your user name (macOS: /Users/<you>/.abap-adt-mcp/systems.json). The forward slashes in the Windows path are deliberate: JSON needs \\ for every backslash, forward slashes need nothing.Claude Code, one line in a terminal (-s user registers the server for every project, not only the current folder):
The same on Windows PowerShell:
VS Code with GitHub Copilot: the same entry in .vscode/mcp.json under a top-level servers key instead of mcpServers; docs/HOSTS.md has the file as tested, with ${input:} for secrets.
abap-adt-mcp: it is the name the host shows, the prefix of every tool, and what this project's agent skills look for.Open a new chat and type (replace DEV with the key you chose; the class is standard SAP, so the prompt is read-only and safe on any system):
List my SAP systems, log in to DEV and show me the source of class CL_ABAP_CHAR_UTILITIES.
A browser window opens for the SSO login (tick "stay signed in" and later logins are silent); the model then calls listSystems, searchObject and getObjectSource, and the reply names your destinations and ends with the class source. The host asks before running a tool you have not approved permanently: that dialog is a courtesy of the host, the policy block is the guarantee. If the server does not appear in the host, Troubleshooting names the log to read.
Two things worth knowing before the first edit:
kind: "policyDenied", Policy: setObjectSource blocked on destination PRD (readOnly).objectDiff and revisions show it, and nothing leaves DEV without a transport release you approve.The same file with a production entry and an on-prem entry (systems.example.json has every option):
PRD is its minimum policy: readOnly refuses every write, whatever the model is asked; allowDataPreview: false keeps table data closed even where the environment opens it for other destinations; deniedTools closes exportPackageSources, the one read that copies whole packages to disk.${env:VAR} reads a secret from the environment, so it never sits in the file; add the variable where the host starts the server: -e ONPREM_PASSWORD=... on claude mcp add (or export it in the shell that starts Claude Code), a "ONPREM_PASSWORD": "..." line in the env block of Claude Desktop, which does not pass your shell environment on. A file with an inline password must be readable by you only (chmod 600 ~/.abap-adt-mcp/systems.json on macOS and Linux; on Windows your profile folder is already private); an SSO-only file needs nothing.tls.ca names a corporate CA certificate. Verification can be relaxed per destination only (insecureTls: true, announced at startup), never for the whole process."transport": "rfc" and an rfc block, and install the SAP NetWeaver RFC SDK, which you download from SAP with your own S-user because SAP does not allow it to be bundled. docs/RFC.md has the steps.That is the whole setup. Next: What to ask the model.
The server is a toolbox the model picks from: ask in plain language and it chooses the sequence.
What the server does on its own, so you do not have to spell it out:
activate=true activates in the same call.kind, hint and nextTools, so the model recovers instead of retrying blindly; an expired session is re-authenticated and the call retried once.hasMore; long calls send progress notifications.tableContents by name needs allowDataPreview, runQuery needs allowFreeSql.instructions field, and six ready-made workflows ship as MCP prompts (create-object, safe-edit, review-transport, fix-atc, clean-core-check, debug-dump; in Claude Code /mcp__abap-adt-mcp__safe-edit DEV ZCL_ORDER_SERVICE "return early when the input table is empty").readOnlyHint/destructiveHint annotations, so hosts that gate approval by annotation ask only on writes.The tool-by-tool sequences, argument shapes and recipes are in docs/WORKFLOWS.md.
What the server is, in the terms a landscape owner asks about:
sso and sso2 that user is the person at the keyboard; basic and oauth carry stored credentials, so prefer named users where accountability matters. The authorizations of a display-only SAP user are listed in docs/CONFIGURATION.md.raw.githubusercontent.com for SAP's cloudification repository when apiReleaseState runs (cached 24 hours; deniedTools: ["apiReleaseState"] keeps that off the network). No telemetry, no update checks; npx itself contacts the npm registry."transport": "rfc" load native code: the SAP NetWeaver RFC SDK the user installs, through koffi, an optional dependency with prebuilt binaries; its install script checks that the binary loads and, only where it does not, tries a build from source with CMake, which is skipped without harm when it fails. An installation used for HTTP destinations only may leave it out with npm install --omit=optional (docs/RFC.md).readOnly, deniedTables and deniedTools bound that set per destination.~/.abap-adt-mcp/: systems.json (yours), the SSO browser profile per host (sso/<host>, mode 0700), the cloudification cache, package exports (exports/, only where exportPackageSources may write), the HTTP token, when enabled the audit log, and with RFC destinations the SAP RFC SDK's own log (rfc/, mode 0700). SAP session cookies are never written to disk.${env:VAR} works in every string of systems.json; a file readable by others is refused when it holds inline passwords. Error messages pass through a redaction step (bearer tokens, cookies, passwords, user:password@host URLs); successful tool results are not redacted, so readOnly, deniedTables and deniedTools are what bounds them. reentranceTicket (a logon ticket the model could carry elsewhere) stays disabled unless SAP_ALLOW_REENTRANCE_TICKET=1.runSnippet, runClass, unitTestRun) executes with the user's authorizations; deniedTables scans the snippet text, but dynamic SQL and whatever the code calls are not inspected. Where code execution is unacceptable, list those tools in deniedTools or use readOnly.MCP_AUDIT_FILE=/var/log/abap-adt-mcp/audit.jsonl appends one JSON line per call: tool, destination, outcome, duration, the policy gate that refused it, and the arguments with secrets redacted. The file is written per workstation by the user's own process; central collection and tamper protection are yours to arrange. docs/CONFIGURATION.md has the record format.npx -y abap-adt-mcp of the setup (Other ways to install). Tested modes: sso, sso2 and on-prem basic; oauth and Communication-User basic are not (Authentication). Vulnerabilities: SECURITY.md, Reporting a vulnerability.Enforced in the server before any SAP call, per destination in systems.json:
Refusals come back as kind: "policyDenied" naming the gate; listSystems shows every policy and the effective dataAccess. The threat model and the residual risks are in SECURITY.md; the gates tool by tool, with recipes, in docs/CONFIGURATION.md; the standing under SAP's API Policy in docs/API-POLICY.md.
Every destination picks its own authType. Details and the SAP-side steps are in docs/AUTH.md.
sso, or you create a Communication User. oauth and basic with a Communication User follow SAP's documentation for technical users but were not exercised by this project against a live tenant; confirm on yours before relying on them.~/.abap-adt-mcp/sso/<host>.tls.ca adds a corporate CA, tls.servername names the certificate of a system reached by IP address, tls.cert + key (or pfx + passphrase) present a client certificate, and insecureTls: true is announced at startup. Optional gitUser/gitPassword keep abapGit credentials out of the conversation.systemProfile(destination) reports whether a destination is cloud or on-prem and which toolsets the backend lacks; those tools are refused before calling SAP. What docs/TESTPLAN.md recorded on a Public Cloud tenant:
More in docs/CLOUD.md and, from real sessions, docs/FIELD-NOTES.md.
npx -y abap-adt-mcp fetches the newest release at every start; for a controlled rollout pin it (npx -y [email protected], or the vX.Y.Z container tag). Releases carry an npm provenance attestation, verifiable with npm audit signatures.abap-adt-mcp teaches the development flow, abap-adt-mcp-setup walks through installation): /plugin marketplace add williansaez/abap-adt-mcp, then /plugin install abap-adt-mcp@abap-adt-mcp. The plugin pins the release it ships with and publishes every toolset; systems.json from step 1 is still yours to write.ghcr.io/williansaez/abap-adt-mcp:latest (also vX.Y.Z), built from node:22-alpine, runs as uid 1000. Mount systems.json read-only and pass referenced secrets through; browser SSO needs a local browser, so run sso destinations from npm on the workstation. docs/HOSTS.md has the docker run line and the file-ownership pitfalls.io.github.williansaez/abap-adt-mcp for hosts that browse the registry.git clone https://github.com/williansaez/abap-adt-mcp.git, npm ci, npm run build, then point the host at node /absolute/path/abap-adt-mcp/dist/index.js. A systems.json next to the checkout is picked up automatically.SAP_SYSTEMS (inline JSON), SAP_SYSTEMS_FILE, a systems.json next to the install, then the legacy single-system variables (SAP_URL, SAP_CLIENT, SAP_USER, SAP_PASSWORD, ...).url, client, language, authType, default, user/password, sso2, oauth, insecureTls, gitUser/gitPassword, policy, tls, transport/rfc; any string may be ${env:VAR}.deniedTools, deniedTables or allowedPackages: those are repeated per entry.The variables you are most likely to set:
Every variable, with its default and what it touches, the HTTP transport (token, session and body limits, DNS-rebinding protection, what a shared instance means) and the audit record format are in docs/CONFIGURATION.md.
The per-tool reference (description, parameters, read-only/destructive annotations) is docs/TOOLS.md, generated from the live tools/list response and verified by a contract test in CI. Every tool except listSystems and healthcheck accepts an optional destination.
Tool schemas cost context. MCP_TOOLSETS takes a preset (all, the default, or focused = 114 development tools) or a comma list of the toolset names below; MCP_DISABLED_TOOLSETS removes some; core is always published.
Names in bold carry destructiveHint: true (23 tools): they overwrite, delete, release or run something, and hosts that gate approval by annotation ask before each one.
In the focused preset (114 tools)
Only with MCP_TOOLSETS=all or by toolset name (59 tools)
A tool can be missing for two reasons: its toolset is not published (the refusal names the toolset), or the destination cannot serve it (systemProfile reports what is missing).
SAP's ADT MCP Server ships with ADT for VS Code and Eclipse and publishes under the server key abap-adt with its own tool names. This project publishes under abap-adt-mcp, serves many destinations from one process, enforces policies server-side, and adds compositions such as resolveTransport, editObjectSource, grepPackage, apiReleaseState, runSnippet and objectDiff. The two can run side by side in the same host; docs/ROUTING.md maps SAP's names to ours.
Names as the SAP Help page "Model Context Protocol Tools" lists them (September 2026). SAP's server creates, activates, tests, checks and transports; it does not read or search source, write source, lock, or show dumps: those come only from this server.
/sap/bc/adt) are the ones Eclipse ADT uses; SAP does not list them on the SAP Business Accelerator Hub. The SAP API Policy (April 2026) restricts unpublished interfaces and the use of APIs by AI agents outside the architectures SAP endorses. SAP's FAQ on the policy calls the ADT APIs internal, for development through endorsed channels only, and a third-party MCP server is not among the channels it lists; the same FAQ allows third-party MCP servers in general and says unpublished interfaces are used at own risk.What the server does on its side: it runs as the SAP user who logged on and removes no SAP authorization check, it reads no table data until a destination allows it, it runs the calls to a destination one at a time, and apiReleaseState marks every SAP object it checks as released, classic, notReleased or prohibited. docs/API-POLICY.md has the policy section by section, the questions to put to SAP and a conservative configuration.
mcp.log and mcp-server-abap-adt-mcp.log to ~/Library/Logs/Claude on macOS and %APPDATA%\Claude\logs on Windows; Claude Code shows the state with /mcp. Claude Desktop reads the config only at start: quit and reopen it after every change.
spawn npx ENOENT: Node.js is not installed, or not on the PATH the app sees. Install it, or put the absolute path to npx in command (C:/Program Files/nodejs/npx.cmd on Windows, /usr/local/bin/npx or /opt/homebrew/bin/npx on macOS).EBADENGINE: the Node the host found is older than 22.12.No ABAP systems configured: SAP_SYSTEMS_FILE points at a missing file (on Windows, check for systems.json.txt).is not valid JSON: a stray comma, or a Windows path written with single backslashes.SAP_BROWSER_PATH points at it when auto-detection fails. To log out of a tenant completely delete the folder sso/<host> under .abap-adt-mcp in your home directory (C:\Users\<you> on Windows). On a machine without a display (a CI runner, a container) the login refuses at once and names oauth or sso2 instead.client says: set client to the tenant's logon client.kind: "sessionExpired" keeps coming back. The server already re-authenticated and retried once; ask the model to call login for that destination. Lock handles from the old session are invalid: lock again.kind: "locked" by another session. listLocks shows the server's own locks; if the object is not there, the lock belongs to another session (Eclipse or another user) and only that session or SM12 releases it.kind: "policyDenied". The destination's policy forbids the call and the message names the gate: the guard rail is working. tableContents and runQuery are refused on every destination that has not opened them, a destination without a policy included; the message names the key to set.systemProfile shows it). "Belongs to toolset ... which is not enabled": add the toolset to MCP_TOOLSETS or use MCP_TOOLSETS=all.kind: "tlsCertificate"). The hint names the destination and the fix: tls.ca for an unknown issuer (the hint carries the openssl line), tls.servername for a name mismatch, renewal in STRUST for an expired certificate.invalid lock handle on an older on-prem system, although the lock succeeded. SAP_BASIS below 7.51 does not keep a lock between HTTP requests. Switch the destination to the RFC transport: docs/RFC.md.editObjectSource reports 0 matches, or several. Nothing was written. The anchor must be the exact current text on SAP, indentation included; for several matches include more surrounding lines.runQuery fails on a table the user can display. The data preview refuses tables with restricted dataMaintenance; use tableContents.More cases, with the exact messages, in docs/TROUBLESHOOTING.md.
npm run tools:docs and commit the regenerated docs/TOOLS.md, snapshot and README catalog (the translated READMEs included).npm run docs:check is the documentation gate: no customer identifiers, no em-dashes, no dead links, every environment variable declared in server.json.The English README is the reference for the Portuguese and German versions. The roadmap is in docs/ROADMAP.md and every release in CHANGELOG.md.
This server grows with the people who run it against real landscapes and send back what they found.
sso2 mode (a named on-prem user who already authenticates through SNC connects without a browser and without a stored password) and tightened the cookie client, which now refuses any request that would carry the SAP session off its configured origin.mcp-abap-abap-adt-api server by mario-andreschak is where this project started.Found something, fixed something, or ran a mode on a landscape nobody here has? Open an issue or a pull request, and see CONTRIBUTING.md.
MIT. Built on abap-adt-api by Marcello Urbani. If the project saves you time, you can sponsor the author.
Source: README.md at commit d4617c4
List Systems
List the configured ABAP systems (destinations) this server can reach. Call this first to pick the destination to pass to all other tools.
Takes no parameters.
Healthcheck
Check server health and list configured destinations.
Takes no parameters.
90% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
{ "DEV": { "url": "https://myXXXXXX.s4hana.cloud.sap", "client": "080", "authType": "sso", "default": true, "policy": { "allowedPackages": ["ZFIN"] } }}{ "mcpServers": { "abap-adt-mcp": { "command": "npx", "args": ["-y", "abap-adt-mcp"], "env": { "SAP_SYSTEMS_FILE": "C:/Users/<you>/.abap-adt-mcp/systems.json", "MCP_TOOLSETS": "focused" } } }}claude mcp add -s user abap-adt-mcp -e SAP_SYSTEMS_FILE=$HOME/.abap-adt-mcp/systems.json -e MCP_TOOLSETS=focused -- npx -y abap-adt-mcpclaude mcp add -s user abap-adt-mcp -e SAP_SYSTEMS_FILE=$env:USERPROFILE\.abap-adt-mcp\systems.json -e MCP_TOOLSETS=focused -- npx -y abap-adt-mcp{ "DEV": { "url": "https://myXXXXXX.s4hana.cloud.sap", "client": "080", "authType": "sso", "default": true, "policy": { "allowedPackages": ["Z*"] } }, "PRD": { "url": "https://myYYYYYY.s4hana.cloud.sap", "client": "100", "authType": "sso", "policy": { "readOnly": true, "allowDataPreview": false, "deniedTools": ["exportPackageSources"] } }, "ONPREM": { "url": "https://sap.example.com:44300", "client": "100", "authType": "basic", "user": "DEVELOPER", "password": "${env:ONPREM_PASSWORD}", "policy": { "allowedPackages": ["Z*", "$*"] }, "tls": { "ca": "/etc/ssl/corp-ca.pem" } }}git clone https://github.com/williansaez/abap-adt-mcp.gitcd abap-adt-mcpnpm cinpm run buildnpm test