MCP server for SAP ABAP ADT over HTTP, RFC or SNC: repository analysis and RAP/classic ABAP CRUD
mcp-abap-adt is an MCP server for ABAP ADT in SAP ECC/S/4HANA (on-premise) and SAP BTP ABAP Cloud systems. It gives agents controlled access to real ABAP repositories through ADT, so analysis and changes are grounded in system data instead of assumptions. It is built for AI-assisted pair programming (AIPNV: AI Pairing, Not Vibing), not autopilot vibe coding.
Primary workflows:
Why teams use it:
parked/legacy-support branch until it can be tried against a live legacy systemAuthorization & Destinations (Important): A destination is the filename of a service key stored locally. You place service keys in the service-keys directory, and use --mcp=<destination> to select which one to use. This is the primary auth model for on‑prem and BTP systems. See Authentication & Destinations.
You can configure MCP clients either manually (JSON/TOML) or via the configurator CLI (@mcp-abap-adt/configurator, repo: mcp-abap-adt-conf).
Install the server and configure your client using the configurator:
npm install -g @mcp-abap-adt/core
npm install -g @mcp-abap-adt/configurator
# stdio (destination)
mcp-conf --client cline --name abap --mcp TRIAL
# HTTP (streamable HTTP)
mcp-conf --client copilot --name abap --transport http --url http://localhost:3000/mcp/stream/http --mcp trial
Full configurator usage (separate repo): CLIENT_INSTALLERS.md.
Destination: a local service key filename. You store service keys in the standard service-keys directory, and pass the filename (without extension) via --mcp=<destination> to select which system to use.
See docs/user-guide/TERMINOLOGY.md for the full list.
Destination-based auth is the default. Drop service keys into the standard platform folder and use the filename as your destination:
mcp-abap-adt --transport=stdio --mcp=TRIAL
Standard service key paths:
~/.config/mcp-abap-adt/service-keys/<destination>.json%USERPROFILE%\\Documents\\mcp-abap-adt\\service-keys\\<destination>.jsonFor full details (paths, .env, direct headers), see Authentication & Destinations.
The project ships as two packages, because the two usage patterns want different licences. Embedding the tools in a network service should not drag in the obligations of a server that service never runs.
| Package | Licence | What it is |
|---|---|---|
@mcp-abap-adt/lib | Apache-2.0 | The ADT tool handlers and the embeddable MCP server. No transport: the host supplies one. |
@mcp-abap-adt/core | AGPL-3.0-only | The standalone server — stdio, SSE and streamable HTTP, the launcher and the mcp-abap-adt CLI. Depends on the library. |
Install @mcp-abap-adt/core to run a server. Install @mcp-abap-adt/lib to
embed the tools in your own application.
Run as a standalone MCP server with stdio, HTTP, or SSE transport:
mcp-abap-adt # stdio (default)
mcp-abap-adt --transport=http # HTTP mode
mcp-abap-adt --transport=sse # SSE mode
Embed MCP server into existing applications (e.g., SAP CAP/CDS, Express).
This needs @mcp-abap-adt/lib only — not the AGPL server:
npm install @mcp-abap-adt/lib
import {
EmbeddableMcpServer,
NoDedupStrategy, // optional: expose both Read<X> and Get<X>
} from '@mcp-abap-adt/lib/embeddable';
const server = new EmbeddableMcpServer({
connection, // Your AbapConnection instance
logger, // Optional logger
exposition: ['readonly', 'high'], // Handler groups to expose
// Default hides Read<X> when Get<X> is exposed (ReadVsGetDedupStrategy).
// Pass NoDedupStrategy to expose both variants instead.
// readOnlyDedupStrategy: new NoDedupStrategy(),
});
await server.connect(transport);
See Handlers Management → EmbeddableMcpServer dedup strategies for how readonly tools are deduped against high/low, how to opt out with NoDedupStrategy, and how to plug a custom IReadOnlyDedupStrategy for role-based rules.
mcp-conf from @mcp-abap-adt/configurator (repo: mcp-abap-adt-conf, docs: CLIENT_INSTALLERS.md)Key examples of high-value workflows and tools:
GetWhereUsed, DescribeByList, GetObjectStructure, GetObjectInfo, SearchObject, GetPackageTree, GetPackageContentsGetAbapAST, GetAbapSemanticAnalysis, GetIncludesListCreateBehaviorDefinition, UpdateBehaviorDefinition, CreateBehaviorImplementation, UpdateBehaviorImplementation, CreateServiceDefinition, UpdateServiceDefinition, CreateMetadataExtension, UpdateMetadataExtensionCreateView, UpdateView, GetView, DeleteViewCreateClass, UpdateClass, GetClass, DeleteClass, CreateInterface, UpdateInterface, GetInterface, DeleteInterfaceCreateFunctionGroup, UpdateFunctionGroup, GetFunctionGroup, DeleteFunctionGroup, CreateFunctionModule, UpdateFunctionModule, GetFunctionModule, DeleteFunctionModuleCreateTransport, GetTransport, ActivateObjectRunATC, GetATCRunStatus, GetATCFindings (ABAP Test Cockpit — one run over several objects, findings read back by worklist), ABAP Unit per test carrier — CreateUnitTest/UpdateUnitTest/DeleteUnitTest/RunUnitTest for a class, CreateCdsUnitTest/RunCdsUnitTest for a CDS view, CreateProgramUnitTest/RunProgramUnitTest for a report, CreateFunctionGroupUnitTest/RunFunctionGroupUnitTest/RunFunctionModuleUnitTest for a function group (a run waits for its result; GetUnitTestResult for one that outlasts the wait) — CheckClass and the rest of the Check* familyPublished in the official MCP Registry and listed on Glama.ai.
MCP Registry: docs/deployment/MCP_REGISTRY.md
GetDomain, CreateDomain, UpdateDomain - Create, retrieve, and update ABAP domainsGetDataElement, CreateDataElement, UpdateDataElement - Create, retrieve, and update ABAP data elementsGetTable, CreateTable, GetTableContents - Create and retrieve ABAP database tables with data previewGetStructure, CreateStructure - Create and retrieve ABAP structuresGetView, CreateView, UpdateView - Create and manage CDS Views and Classic ViewsGetClass, CreateClass, UpdateClass - Create, retrieve, and update ABAP classesGetProgram, CreateProgram, UpdateProgram - Create, retrieve, and update ABAP programsGetBehaviorDefinition, CreateBehaviorDefinition, UpdateBehaviorDefinition - Create and manage ABAP Behavior Definitions with support for Managed, Unmanaged, Abstract, and Projection typesCreateMetadataExtension, UpdateMetadataExtension - Create and manage ABAP Metadata ExtensionsActivateObject - Universal activation for any ABAP objectCreateTransport, GetTransport - Create and retrieve transport requestsGetEnhancements, GetEnhancementImpl, GetEnhancementSpot - Enhancement discovery and analysisGetIncludesList - Recursive include discoveryGetInactiveObjects - Monitor inactive objects waiting for activationGetServiceBindingPreviewUrl - The browser URL that opens a published service binding's Fiori preview, beside its OData service and $metadata URLs. Composed from the binding, its service definition and the exposed root view — no document carries it. OData V2 and V4; a Web API binding has no preview and says so. On SAP BTP the preview URL carries the browser host (abap-web), where the BTP logon answers, while the service URLs keep the ADT hostRuntimeCreateProfilerTraceParameters, RuntimeListProfilerTraceFiles, RuntimeGetProfilerTraceData, RuntimeGetDumpById - Profiling and dump analysis with JSON payloadsRuntimeListFeeds, RuntimeListSystemMessages, RuntimeGetGatewayErrorLog - Feed reader (dumps — filtered by user, runtime error, exception, object, package or component, and read past SAP's 100 entries per request — system messages, gateway errors), SM02 system messages, Gateway error logGetSqlQuery - Execute custom SQL queries via ADT Data Preview APIℹ️ ABAP Cloud limitation: Direct ADT data preview of database tables is blocked by SAP BTP backend policies. The server returns a descriptive error when attempting such operations. On-premise systems continue to support data preview.
@mcp-abap-adt/configurator (repo: mcp-abap-adt-conf) provides the mcp-conf CLI to auto-configure clients--exposition=compact became the mcp-abap-adt-compact commandTwo packages do the work:
and six packages declare the contracts both of them and this project are written against — @mcp-abap-adt/interfaces-adt, -adt-connection (where IAbapConnection and IAdtWireResponse live), -network, -auth, -auth-sap and -utils. They replace the single @mcp-abap-adt/interfaces umbrella, which is no longer published: a consumer naming a contract package directly gets one copy of it in the tree and takes its majors one domain at a time.
The verdict on an ADT answer is a strategy, not a default: since adt-clients 23 no member judges its own answer, and @mcp-abap-adt/adt-strategies holds the readings this project passes to every call. That is what keeps a refusal ADT embeds in an HTTP 200 — an activation that did not activate, a delete that was refused — from reaching a caller as success.
Everything above is installed by npm install and published to npm. @mcp-abap-adt/sap-rfc-lite is optional and only needed for the RFC transport, which also requires the SAP NW RFC SDK on the machine.
After installing globally with npm install -g, you can run from any directory:
# Show help
mcp-abap-adt --help
# Default stdio mode (for MCP clients; requires .env file or --mcp parameter)
mcp-abap-adt
# stdio mode (explicit; default when --transport is omitted)
mcp-abap-adt --transport=stdio
# HTTP mode on custom port (HTTP requires --transport=http)
mcp-abap-adt --transport=http --port=8080
# Use stdio mode with auth-broker (--mcp parameter)
mcp-abap-adt --transport=stdio --mcp=TRIAL
# Use env destination from platform sessions store
mcp-abap-adt --env=trial
# Use explicit .env file path
mcp-abap-adt --env-path=/path/to/my.env
# SSE mode (requires .env file or --mcp parameter)
mcp-abap-adt --transport=sse --port=3001
# SSE mode with auth-broker (--mcp parameter)
mcp-abap-adt --transport=sse --mcp=TRIAL
# Build and run locally
npm run build
npm start
# HTTP mode
npm run start:http
# SSE mode
npm run start:sse
Env resolution:
--env-path=<path|file> (or MCP_ENV_PATH) for explicit .env file.
my.env): resolved from current working directory.--env=<destination> for destination file in standard sessions store:
~/.config/mcp-abap-adt/sessions/<destination>.env%USERPROFILE%\\Documents\\mcp-abap-adt\\sessions\\<destination>.env.env in current working directory.Example .env file:
SAP_URL=https://your-sap-system.com
SAP_CLIENT=100
SAP_AUTH_TYPE=basic
SAP_USERNAME=your-username
SAP_PASSWORD=your-password
For JWT authentication (SAP BTP):
SAP_URL=https://your-btp-system.com
SAP_CLIENT=100
SAP_AUTH_TYPE=jwt
SAP_JWT_TOKEN=your-jwt-token
For RFC connection:
SAP_URL=https://your-onprem-system.com
SAP_CLIENT=100
SAP_AUTH_TYPE=basic
SAP_USERNAME=your-username
SAP_PASSWORD=your-password
SAP_CONNECTION_TYPE=rfc
See RFC Setup Guide for prerequisites (SAP NW RFC SDK).
For client certificate (mTLS) authentication — on-prem HTTP only:
SAP_URL=https://your-sap-system.com
SAP_AUTH_TYPE=certificate
# PEM format (provide both files):
SAP_CERT_PATH=/path/to/client.crt
SAP_CERT_KEY_PATH=/path/to/client.key
# Or PKCS#12 format (alternative to PEM):
# SAP_CERT_PFX_PATH=/path/to/client.pfx
# SAP_CERT_PASSPHRASE=your-passphrase
For Kerberos (SPNEGO) authentication — on-prem HTTP only:
SAP_URL=https://your-sap-system.com
SAP_AUTH_TYPE=kerberos
# Optional: explicit SPN (default: HTTP@<host>)
# SAP_KERBEROS_SPN=HTTP@mysaphost.corp.example
# Optional: service class used to derive the SPN when SAP_KERBEROS_SPN is unset (default: HTTP)
# SAP_KERBEROS_SERVICE=HTTP
Certificate auth notes:
SAP_USERNAME / SAP_PASSWORD required.SAP_CERT_PATH + SAP_CERT_KEY_PATH) or a PKCS#12 file (SAP_CERT_PFX_PATH), not both.SAP_CONNECTION_TYPE=rfc is not supported).Kerberos auth notes:
kinit or a keytab.kerberos npm package must be installed (needs GSSAPI dev libs on Linux / build tools on Windows): npm i kerberos.SAP_USERNAME / SAP_PASSWORD required — identity comes from the TGT..env directly.⚠️ Help wanted — not yet validated on a live system. Certificate and Kerberos auth pass full unit coverage but have not been tested against a real SAP system. If you have on-prem client-certificate or Kerberos/SPNEGO SSO, please try it and open an issue with results — especially whether Kerberos succeeds with a single-leg Negotiate token or your system needs mutual-auth continuation.
Generate .env from Service Key (JWT):
# Install the auth broker globally (one-time setup) — it ships the mcp-auth CLI
npm install -g @mcp-abap-adt/auth-broker
# Generate .env file from service key JSON
mcp-auth --service-key path/to/service-key.json --output .env
This will automatically create/update .env file with JWT tokens and connection details.
.env comments rule: only full-line comments are supported (lines that start with #).
Inline comments are not parsed, so keep comments on separate lines.
Claude recommendation: place the service key in the service-keys directory and use --mcp=<destination> (avoid manual JWT tokens).
Authentication:
--auth-broker - Force use of auth-broker (service keys), ignore .env file--auth-broker-path=<path> - Custom path for auth-broker service keys and sessions--browser-auth-port=<port> - Override OAuth browser callback port (default: 5000 for HTTP, 4000 for SSE, 4001 for stdio)--connection-type=<http|rfc> - SAP connection transport: http (default) or rfc--unsafe - Enable file-based session storage (persists tokens to disk). By default, sessions are stored in-memory (secure, lost on restart)When --mcp=<destination> is specified, automatic fallback loading of ./.env is skipped.
Examples:
# Use auth-broker with file-based session storage (persists tokens)
mcp-abap-adt --auth-broker --unsafe
# Use auth-broker with in-memory session storage (default, secure)
mcp-abap-adt --auth-broker
# Custom path for service keys and sessions
mcp-abap-adt --auth-broker --auth-broker-path=~/prj/tmp/ --unsafe
See Client Configuration for complete configuration options.
AUTH_LOG_LEVEL=error|warn|info|debug — sets base log level for handler logger; DEBUG_AUTH_LOG=true also enables debug.HANDLER_LOG_SILENT=true — fully disables handler logging.DEBUG_CONNECTORS=true — verbose connection logging in high-level handlers.DEBUG_HANDLERS=true — enables verbose logs for selected read-only/system handlers.npm test
TEST_LOG_LEVEL=error|warn|info|debug — controls test logger verbosity (DEBUG_TESTS/DEBUG_ADT_TESTS/DEBUG_CONNECTORS force debug).TEST_LOG_FILE=/tmp/adt-tests.log — writes test logs to a file (best-effort).TEST_LOG_SILENT=true — disables test logging pipeline (console output muted).TEST_LOG_COLOR=true — adds colored/prefixed tags to test log lines.console.* in tests are routed through the test logger with a [test] prefix.npm run build
# Generate tool documentation
npm run docs:tools
# See tools/README.md for more developer utilities
Thank you to all contributors! See CONTRIBUTORS.md for the complete list.
Acknowledgment: This project was originally inspired by mario-andreschak/mcp-abap-adt. We started with the core concept and then evolved it into an independent project with our own architecture and features.
Two packages, two licences. Which one applies depends on which you install.
| Package | Licence | |
|---|---|---|
@mcp-abap-adt/lib | Apache-2.0 | LICENSE, NOTICE |
@mcp-abap-adt/core | AGPL-3.0-only | server/LICENSE |
Both are published from this repository with one command, in the order the dependency requires:
npm run release:dry # rehearses both, touches nothing
npm run release:publish # @mcp-abap-adt/lib, then @mcp-abap-adt/core
release:publish skips a version already on the registry, so re-running after
a failure resumes rather than starting over. It aborts on the first failure
instead of publishing the server on top of a library that is not there.
Note that npm publish and npm run are different commands. npm publish release asks npm to publish a package named release, which is somebody
else's package on the registry.
Copyright © 2025–2026 Oleksii Kyslytsia
Both are distributed in the hope that they will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
What this means. Running either, on your own data, carries no conditions.
Embedding the library in your own application carries no obligation to open your application: Apache-2.0 asks for the notice and the licence text to travel with it, and nothing more.
Distributing the standalone server, or running a modified version of it as a network service, means passing on the same freedoms under AGPL section 13 — including the source. That is why the two are separate packages: installing the library never puts the server in your dependency tree.
The packages underneath are LGPL-3.0-only — @mcp-abap-adt/adt-clients,
adt-strategies, connection, logger, auth-broker, auth-providers,
auth-stores and the contract packages interfaces-adt,
interfaces-adt-connection, interfaces-network, interfaces-auth,
interfaces-auth-sap and interfaces-utils — and the library links them at
runtime. It was four of them when this paragraph was written; the rule is the
whole scope now, libraries LGPL and servers AGPL or GPL, and the MIT that a few
of the auth packages still carried was an oversight rather than an offer. LGPL
does not reach your own code, but its terms do travel with those packages
whatever this project is licensed as. Plan for that, not for the notice on this
repository.
Other terms are possible. Apache-2.0 is what the library is offered under
publicly, not the only way it can be offered. The copyright holder may license
the same code separately to a party who needs different terms; that takes
nothing away from anyone who received it under Apache-2.0, which is permanent.
CONTRIBUTORS.md records what keeps that option
open, including the rule that no LGPL code from the packages underneath is ever
copied into this tree.
History. Releases through 8.13.0 were MIT and stay MIT; 9.x was
GPL-3.0-only. A licence change is not retroactive — anyone may still take an
earlier release under the licence it carried. See CONTRIBUTORS.md
for the full account of how the relicensing was lawful.
Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @mcp-abap-adt/coreMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-fr0ster-mcp-abap-adt": {
"command": "npx",
"args": [
"-y",
"@mcp-abap-adt/core"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup reference@mcp-abap-adt/corenpmio.github.fr0ster/mcp-abap-adt works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.