Skip to main content
Glama

abapsmith

An MCP server that lets an LLM develop in SAP ABAP on a live system over ADT (/sap/bc/adt/*).

Capabilities

Area

What the server does

Read

Source, outline, single method, line windows, raw properties, version history, diff. DDIC rendered as pseudo-DDL. Every response carries an etag.

Search

Object-name patterns and where-used.

Classes & interfaces

Create, read, update, delete, activate.

Programs & function groups

Programs, function groups, function modules: create, read, update, delete, activate. Includes and transformations: read.

DDIC

Domains, data elements, structures, table types, tables: create, read, update, delete, activate. Message classes: create, read, update, delete. Lock objects: read, update, activate.

CDS

DDL sources and metadata extensions: create, read, update, delete, activate.

RAP & services

Behavior definitions, behavior pool classes, service definitions, service bindings: create, read, update, activate. OData contract read (V2 and V4), metadata only.

BOPF

Business objects, nodes, associations, actions, determinations, validations, queries: create, read, delete. Dangling-reference check. End-to-end run through a generated bridge.

Enhancements

Enhancement spots, BAdI definitions and implementations, filters, source-code plug-ins.

Debugger

Arm breakpoints, trigger a run, step, read the call stack, inspect any variable in scope down to one field or table row.

ABAP Unit

Run existing tests. Four distinct outcomes — "nothing ran" is never reported as a pass.

ATC

Run ABAP Test Cockpit static analysis, return the findings. No IDE needed.

Quick fixes

List and apply ADT position-driven quick fixes as a gated, journalled write. Deterministic proposals only.

Transports

List, show, check, users, create, add user, set owner, delete. Release is separately gated and dry-run unless confirmed.

Run

Classes via IF_OO_ADT_CLASSRUN, and classic reports through a generated bridge, with list output and selection-screen parameters captured.

Activate

Check-only or activate, single object or batched.

Dumps

Read ST22 runtime errors. Variable contents are opt-in.

Data preview

Rows from one DDIC table or view. Opt-in, denylisted, refused on a productive system.

Classic dynpro

Read a screen's fields, flow logic and GUI status; drive a transaction by batch input (opt-in, admin only).

Undo

Local write journal: list, show, and undo a mutation, restoring the exact prior source. Drift is detected and refused.

Per-object-type detail, and the evidence behind every claim above: doc/CAPABILITIES/README.md.

Every response is capped and truncation is line-wise, marked, and names the call that fetches the rest.

Related MCP server: abap-adt-mcp

Requirements

  • Node >= 20

  • An ABAP system with ADT enabled (/sap/bc/adt/* reachable over HTTP)

  • A user with S_DEVELOP. A dedicated technical user is recommended.

Install

Claude Code

This repository is a plugin marketplace, so there is nothing to clone and nothing to build:

/plugin marketplace add Freight-Art/abapsmith
/plugin install abapsmith@abapsmith

That installs the MCP server together with the task-shaped skills in skills/, which carry the wire lore an agent needs before it calls a tool. The server runs from bundle/ — a committed, dependency-free build, because plugin installation performs no build step.

To stay on a particular release, or to step back to one after an update, add the marketplace at its tag instead of at main; every release is a vX.Y.Z tag with a CHANGELOG section of the same name:

/plugin marketplace add Freight-Art/abapsmith#v0.3.1
/plugin install abapsmith@abapsmith

/plugin update follows whatever the marketplace points at, so a marketplace added at a tag stays on that tag until you add it again at another one.

The plugin deliberately declares no env block, so configure the connection the way the next section describes: a .env in the directory you start Claude Code from, or exported shell variables. Both reach the server. Wire it into an MCP client is then only for other clients.

Any other MCP client

Not published to a registry — build from a clone.

git clone https://github.com/Freight-Art/abapsmith.git
cd abapsmith
npm install
npm run build

npm run build emits dist/index.js, which is the server entry point.

Configure

Five variables connect to a system. Put them in a .env in the directory the server runs from — it is loaded automatically — or in your MCP client's env block. Copy .env.example for the annotated version.

ABAP_URL=https://abap.example.com:44300
ABAP_USER=DEVELOPER
ABAP_PASSWORD=your-password
ABAP_CLIENT=001
ABAP_SID=A4H
ABAP_MODE=read          # read (default) | edit | admin

ABAP_PASSWORD is one of five mutually exclusive credential methods — the others are a session cookie, an X.509 client certificate, a static bearer token, and OAuth 2.0 client credentials; see doc/CONFIGURATION/connection.md for all five.

ABAP_MODE is the single permission knob. read is an absolute ceiling that no other variable lifts. edit allows write, activate and run. admin adds transport release, transport and cascade delete, and SAP-original enhancement targets. Three capabilities sit outside the ladder and stay off in every mode, admin included, until named explicitly: ABAP_ALLOW_DATA_PREVIEW, ABAP_ALLOW_DUMP_VARIABLES, ABAP_ALLOW_UI_PRESS.

The server speaks stdio by default — that's what the plugin install above and the mcpServers block below both use. ABAP_MCP_TRANSPORT=http runs the same binary as a Streamable HTTP service instead (ABAP_MCP_HTTP_HOST/_PORT/_PATH), so it can run next to the SAP system and serve several MCP sessions over the network rather than one process per local conversation. A non-loopback bind with no ABAP_MCP_HTTP_TOKEN set is refused at startup. See doc/CONFIGURATION/transport.md for the variables and doc/SAFETY/remote-transport.md for what the bearer token does and does not guarantee once this is reachable over a network.

Every other variable — allowlists, pool sizing, journal retention, timeouts, debugger identity — is in doc/CONFIGURATION/README.md.

Concurrent calls and ABAP_SESSION_WAIT_MS. Calls to one server share a small pool of ABAP sessions (ABAP_MAX_SESSIONS, default 5 = ABAP_READ_CONCURRENCY 2 + ABAP_WRITE_CONCURRENCY 2

  • 1 reserved for the debugger). A call that finds every slot of its lane busy queues, up to ABAP_SESSION_WAIT_MS (default 10000) of queueing headroom plus the longest request timeout (ABAP_TIMEOUT_MS, ABAP_RUN_TIMEOUT_MS, ABAP_ACTIVATE_TIMEOUT_MS, ...), so a call queued behind one long abap_ui press, run or activation is not refused before that holder can finish. If it still times out, the result is SESSION_BUSY with retryable: true and details naming the holder, how long it has held the slot, its expected remaining time and a suggested retryAfterMs; nothing was sent to SAP, so retrying unchanged is safe. abap_ui press already runs on the write lane, so read-only calls (abap_read, abap_data_preview) are not queued behind it. More lane slots (ABAP_READ_CONCURRENCY, ABAP_WRITE_CONCURRENCY, within ABAP_MAX_SESSIONS) reduce queueing; raising ABAP_SESSION_WAIT_MS only lengthens how long a caller waits.

Wire it into an MCP client

For clients other than Claude Code, which the plugin install above already wires up:

{
  "mcpServers": {
    "abap": {
      "command": "node",
      "args": ["/absolute/path/to/abapsmith/dist/index.js"],
      "env": {
        "ABAP_URL": "https://abap.example.com:44300",
        "ABAP_USER": "DEVELOPER",
        "ABAP_CLIENT": "001",
        "ABAP_SID": "A4H",
        "ABAP_MODE": "read"
      }
    }
  }
}

ABAP_PASSWORD — and, in whichever other credential method is in play, ABAP_TOKEN, ABAP_OAUTH_CLIENT_SECRET, ABAP_SERVICE_KEY, and ABAP_CLIENT_KEY_PASSPHRASE — are deliberately absent from that block: keep them in the .env the client's working directory supplies, so a secret never lands in a JSON file that is easy to commit or sync alongside the rest of an editor config. Start on ABAP_MODE=read and opt into edit once you intend to write.

Documentation

doc/CAPABILITIES/README.md

Every object type, framework and capability, with the evidence behind each claim

doc/TOOLS/README.md

Full per-tool parameter reference

doc/FLUID-API/README.md

The fluid API: one package, one manifest format, one wire protocol for the tools that install ABAP to run

doc/CONFIGURATION/README.md

Every environment variable, its default, and its failure mode

doc/SAFETY/README.md

The gate, the modes, and the boundaries that are not security controls

doc/JOURNAL/README.md

Journal format, undo semantics, drift detection, retention

doc/CONCURRENCY/README.md

Session pool, lanes, object gate

doc/LIMITATIONS/README.md

What is unproven, unimplemented, or structurally impossible here

doc/DESIGN-NOTES/README.md

Decisions that are load-bearing and not obvious from the code

doc/TESTING/README.md

Suite layout, fixtures, and how the live tests are gated

CONTRIBUTING.md

Build, test, and the bar for a change

SECURITY.md

Reporting a vulnerability

CHANGELOG.md

What changed, release by release

License

MIT — see LICENSE. Third-party attribution: THIRD-PARTY-NOTICES.md.

Thanks

Big thanks to two projects whose ideas shaped this one:

Available Tools

29 tools
abap_activateA
Destructive

mode=check: syntax check, no lock. mode=activate: check then activate. mode=format: pretty-print (source=text, or object=format-and-save).

Inputs: mode, type, object, source, +5 more.

abap_atcC
Read-onlyIdempotent

Run ABAP Test Cockpit static analysis on an object. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_bopfA
Read-only

Reads a BOPF business object's design-time model: show (default, digest) | raw (v4 XML) | search (needs object_type) | check_refs (up to max_sites, default 25).

Inputs: bo, mode, query, max_sites, +2 more.

abap_bopf_deleteB
Read-onlyIdempotent

Delete a BOPF business object. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_bopf_editA
Read-onlyIdempotent

Make one design-time edit to a BOPF business object, or create one. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_bopf_testC
Read-onlyIdempotent

Run a BOPF business object end to end, writing real rows. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_debugA
Destructive

ABAP debugger driver: arm breakpoints, run a program, step, inspect the stack. One session at a time; frames observe-only. set_value changes a simple variable at a stop (edit/admin mode).

Inputs: action (required), id, op, run, +10 more.

abap_debug_valueB
Read-only

Tier-2 drill-in: render one variable path in detail, with a row window for tables.

Inputs: path (required), stateId (required), from, count, +1 more.

abap_debug_varsA
Read-only

Survey of every variable in scope at a debugger stop; complex values come back as abap_debug_value stubs.

Inputs: stateId (required), scope, filter.

abap_dumpsRead ABAP runtime errors (ST22 short dumps)A
Read-onlyIdempotent

Read ABAP runtime errors (ST22 short dumps) from the system's dump repository — not the exception text of a run this server just triggered. mode=list filters the dump feed; mode=show returns one dump, chapter by chapter. The feed reaches back 8 DAYS ONLY: an empty list means "no dumps in the last 8 days matching this filter", never "nothing failed". Copy key from a list row VERBATIM. show returns a summary (exception, short text, error analysis, how to correct, source line, top of the call stack, chapter index); section or chapters returns chapter text — where terminated, source extract, system fields, call stack, and nothing else unless the operator enabled more.

Inputs: to, key, max, from, +5 more.

abap_enhA

Default op writes the root adtcore:description of an existing ENHO/XH, ENHO/XHH or ENHS/XS, optionally activating it. ENHO/XHH plug-in source body: use abap_write, not this tool. See operation for the other ops.

Inputs: name (required), spec, type, affects, +6 more.

abap_fluidC
Read-onlyIdempotent

Deploy and run small generated ABAP tools inside $ABAPSMITH_FLUID_API. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_fpm_readC
Read-onlyIdempotent

Read SAP FPM/FBI screen configurations; every call deploys a throwaway bridge class. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_imgRead IMG customizing catalogA
Read-only

Read the IMG customizing catalog: search (query) finds activities; show (activity) returns its path, objects and tables; tree (node/treeId optional) lists a node's children; objects (object, kind optional) returns a customizing object's DDIC tables and fields. search/tree page via after/limit (default 25, ceiling 200) — pass back the exact {"after": ""} a response gives; there is no numeric offset. Fields not valid for the mode are rejected.

Inputs: mode (required), kind, node, after, +6 more.

abap_img_editC
Read-onlyIdempotent

Preview and write IMG/customizing table rows. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_journalA
Destructive

History and undo for writes abapsmith made. Parameters: mode (list|show|undo|reconcile, default list), entry, object, detail, limit, session, force, activate, outcome, reason. Common calls: mode=list (recent writes with entry ids, each row's undoable column and truncated undo_blocker say up front whether an undo is expected to work); mode=show entry= (one entry with its before-image, and the full undo_blocker reason if any; detail=full for the complete images); mode=undo entry= activate=true (revert it — refuses on drift or a delete-gate; see abapsmith-recover-a-bad-write); mode=reconcile entry= outcome=<succeeded|failed> reason= (close a stranded pending entry — journal bookkeeping only, nothing is sent to SAP).

Inputs: mode, entry, force, limit, +6 more.

abap_open_urlGet a browser-openable URL for an ABAP object, keyword, or Web Dynpro appA
Read-only

Browser-openable URL: ADT source/HTML (object=, type=/line=), keyword doc (keyword=), or Web Dynpro URL (webdynpro=). Exactly one required. Does not open a browser.

Inputs: line, type, object, keyword, +1 more.

abap_quick_fixC
Read-onlyIdempotent

List and apply ADT quick fixes at one source position. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_rapA
Read-onlyIdempotent

Generate a RAP stack (CDS, BDEF, class, SRVD, SRVB) from a table. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_readRead ABAP objectA
Read-only

Read an ABAP object: source, pseudo-DDL, a DEVC/K package listing, or (SUSO/B, TABL/DI) a read-only catalog render; view= selects docu/digest/history/diff/definition/lineage/footprint. A CLAS/INTF/PROG/FUGR source above 150 lines or 8k chars answers with its outline by default — then method=, pattern= (regex, with context), offset/limit, or full=true. To learn a method's signature, use method= with include="definitions" (declaration only); method= also finds inherited members (superclasses and interfaces) and reports foundOn. Returns an etag; capped ~15k tokens, truncation marked. Example: {"object":"ZCL_FOO","type":"CLAS/OC"}.

Inputs: object (required), to, from, full, +17 more.

abap_runC
Read-onlyIdempotent

Execute an IF_OO_ADT_CLASSRUN class or report and capture its output. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_serviceA
DestructiveIdempotent

OData contract a RAP SRVB publishes: entity sets, keys, fields, nav, CRUD/search/page perms; V2/V4 detected. Cannot read entity data — contract only. op="publish"/"unpublish" register or deregister the binding in the OData service runtime (admin-mode ceiling, confirm required to arm). Unpublished bindings named as such.

Inputs: binding (required), op, mode, entity, +1 more.

abap_testC
Read-onlyIdempotent

Run ABAP Unit tests and report each method's verdict. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_traceA
Destructive

ABAP runtime tracing (SAT): records everything a traced request's dispatch touches — time per call and every database access. op="run" (default) traces one execution of a class/report and reads the result back; op="start" arms a request to trace a later run yourself; op="list" shows existing runs/requests; op="read" reads a run's hit list, DB accesses, or call tree; op="delete" removes a run or request.

Inputs: id, op, top, kind, +14 more.

abap_transportA
Destructive

Inspect and manage CTS transport requests: list, show, check (does an object need a transport?), users, log (a request's export/import log per target system), queue (a target system's import buffer), create (kind="workbench" default, or "copies" with target), addUser, setOwner, delete, removeObject (drop one E071 entry and its CTS lock). list/show/check/users/log/queue are plain reads, always allowed; create/addUser/setOwner need write access; delete/removeObject additionally need the admin-only transport-delete ceiling. Release is a separate tool, abap_transport_release. Semantics of log/queue/copies/removeObject: doc/TOOLS/transports.md.

Inputs: operation (required), kind, user, domain, +7 more.

abap_transport_releaseB
Read-onlyIdempotent

Release one CTS transport request — irreversible. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. ABAP_ALLOW_TRANSPORT_RELEASE does not enable releasing a transport request, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Set ABAP_ALLOW_TRANSPORT_RELEASE=true. Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_uiB
Read-onlyIdempotent

Drive classic SAP dynpro screens via batch input: read one screen, or run a scripted transaction. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

abap_writeC
Read-onlyIdempotent

Create, change or delete an ABAP object: save/check/activate. LOCKED on this server: ABAP_ALLOW_WRITE does not enable writes, and ABAP_MODE is not set, so that variable is what decides it. Set ABAP_ALLOW_WRITE=true (ABAP_ALLOW_PACKAGES is optional — it narrows the default, which is every package). Calling it returns a refusal and sends nothing to the SAP system.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

    TDQS

    B3.2/5.0

    Scored across 29 tools

    Disambiguation4/5

    Most tools target distinct resource-action pairs (search, read, write, debug, transport, BOPF, IMG, RAP) and descriptions are detailed enough to disambiguate. A few pairs like abap_read vs abap_search or abap_bopf vs abap_bopf_edit could cause hesitation, but the descriptions clarify their boundaries.

    Naming Consistency3/5

    All tools share a consistent snake_case style with the abap_ prefix, which is good. However, the naming mixes nouns (abap_transport, abap_journal), verbs (abap_read, abap_write), and compounds (abap_transport_release, abap_debug_vars), so there is no uniform verb_noun pattern.

    Tool Count3/5

    29 tools is on the heavy side, but the apparent scope is broad—ABAP development spans search, read/write, transports, BOPF, IMG, RAP, debugging, and testing. The count is justified by the domain, though many tools are locked on this server, adding surface area without live functionality.

    Completeness4/5

    The set covers the core ABAP lifecycle—search, read, write/activate, test, debug, and transport—plus specialized areas like BOPF, RAP, FPM, and IMG. Minor gaps exist (e.g., no dedicated object comparison tool), but common workflows are well supported and abap_write covers delete operations.

    Maintenance

    ActivityMaintained
    ResponsivenessUsually handled

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      Enables AI agents to read, write, activate, and transport ABAP code in SAP systems via ABAP ADT REST API, without needing SAP GUI.
      24
      576 npm
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to perform ABAP Development Tools operations on SAP ERP (ECC and S/4HANA) systems, including source code editing, object activation, syntax checks, and ABAP unit tests.
      8 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI assistants to work with SAP ABAP systems through the ADT REST API, supporting repository search, source code read/write, activation, syntax checks, and transport request management.
      1
      Apache 2.0