Skip to main content
Glama
README.md
# 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](doc/CAPABILITIES/README.md)**.

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

## 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](#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.

```bash
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.

```bash
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](doc/CONFIGURATION/connection.md#authentication) 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](doc/CONFIGURATION/transport.md) for the variables and
[doc/SAFETY/remote-transport.md](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](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:

```jsonc
{
  "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](doc/CAPABILITIES/README.md) | Every object type, framework and capability, with the evidence behind each claim |
| [doc/TOOLS/README.md](doc/TOOLS/README.md) | Full per-tool parameter reference |
| [doc/FLUID-API/README.md](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](doc/CONFIGURATION/README.md) | Every environment variable, its default, and its failure mode |
| [doc/SAFETY/README.md](doc/SAFETY/README.md) | The gate, the modes, and the boundaries that are not security controls |
| [doc/JOURNAL/README.md](doc/JOURNAL/README.md) | Journal format, undo semantics, drift detection, retention |
| [doc/CONCURRENCY/README.md](doc/CONCURRENCY/README.md) | Session pool, lanes, object gate |
| [doc/LIMITATIONS/README.md](doc/LIMITATIONS/README.md) | What is unproven, unimplemented, or structurally impossible here |
| [doc/DESIGN-NOTES/README.md](doc/DESIGN-NOTES/README.md) | Decisions that are load-bearing and not obvious from the code |
| [doc/TESTING/README.md](doc/TESTING/README.md) | Suite layout, fixtures, and how the live tests are gated |
| [CONTRIBUTING.md](CONTRIBUTING.md) | Build, test, and the bar for a change |
| [SECURITY.md](SECURITY.md) | Reporting a vulnerability |
| [CHANGELOG.md](CHANGELOG.md) | What changed, release by release |

## License

MIT — see [LICENSE](LICENSE). Third-party attribution: [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).

## Thanks

Big thanks to two projects whose ideas shaped this one:

- [Vibing Steampunk](https://github.com/oisee/vibing-steampunk) — also the source of the ADT
  debugger protocol knowledge behind `src/debug/`, credited in
  [THIRD-PARTY-NOTICES.md](THIRD-PARTY-NOTICES.md).
- [mcp-abap-adt](https://github.com/fr0ster/mcp-abap-adt)

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
ResponsivenessUnresponsive