@arc-mcp/adt-ls
A TypeScript SDK over adt-ls, the headless language server SAP ships inside ABAP Development Tools for VS CodeABAP Development Tools for VS CodeSAP's ABAP tools in VS Code: editing, debugging, ABAP Unit, ATC and transports for classes, CDS and RAP objects, over RFC to an on-premise or Private Cloud system and HTTP to a cloud one, with Joule's ADT MCP server and code completion behind an AI-unit licence.sap official, abap, so a program drives it without the discovery, JVM and handshake work.
SAP's adt-lsc runs inside the sapse.adt-vscode extension and speaks LSP over a named pipe, and reaching it means discovery, a JVM, the handshake, the reentrance logon and TLS before a single object is read. createAdtLs() does that and returns one namespaced client: repository for object search and file access, source and lifecycle for create, update, activate, unit tests and delete, navigation for hover, completion, references and pretty-printer formatting, quality for ATC and ABAP Unit coverage, services and transport, and raw for any adt-ls call it does not wrap. The credential is a strategy the caller passes: basic for an on-premise fixed user, bearer for BTP ABAP, an interactive sign-in the consumer opens itself, or clientCert for X.509 mutual TLS. Its scope section draws the line at adt-ls alone, with no direct ADT HTTP, no MCP server and no Cloud Connector bridge inside the library, which is the layer arc-1-lsparc-1-lspAn edition of ARC-1 that hands every ADT interaction to SAP's own embedded adt-ls language server instead of a hand-rolled HTTP client.independent, abap and abapify/openadt keep for themselves; the README names both as the first-party duplication the library was written to end. The runtime is not shipped with it, because adt-ls comes under the SAP Developer License and is not redistributable.
Facts
Where it sits
Who is behind it
In the atlas: maintains 9@arc-mcpMarian ZeisMarian ZeisMaintains this
In the atlas: maintains 35, contributes to 86, wrote 25@marianfoomaintainers
Before choosing this
Conditions
PracticalFunctional boundary
What adt-ls cannot do headless the maintainer puts out of scope, so a consumer that needs an ADT call the language server does not expose is back to speaking ADT itself. The README states the current runtime compatibility as verified on macOS arm64, against adt-ls 1.1.2 as the minimum and 1.1.2.202608131517 as the version tested. An Eclipse installation does not supply that runtime: SAP versions the two separately, so the VS Code extension has to be installed even where nobody opens VS Code.
What it declares
Every artifact
- Type
- Package
- Origin
- Independently maintained
- Runtime
- Node.js
As a package
- Where it runs
- In your own program
- Distributed through
- npm
Connections
Editor help with source: completion, navigation, errors, refactoring
ABAP runtime on BTP for the ABAP Cloud model
SAP's ERP suite, run on-premise or as a private cloud edition, with its business data and processes reached over OData, RFC and the ABAP platform. For the things here it is the system a tool reads from or writes to. The public cloud edition is its own entry.
SAP's ABAP tools in VS Code for editing, debugging, ATC and transports
Download
Install
npm add @arc-mcp/adt-lsDerived from the package name. No recipe recorded; the README has the configuration.
Where it sits in your app
Download
sapse.adt-vscode extension, which ships the adt-lsc runtime the library discovers and starts; it is licensed to the installer rather than redistributed with the packageREADME
quoted from arc-mcp/adt-ls under Apache-2.0, read@arc-mcp/adt-ls
Generic, reusable TypeScript SDK over SAP's headless adt-ls — the
adt-lsclanguage server shipped inside the officialsapse.adt-vscodeextension. It hides the painful setup (discovery, JVM, named-pipe + LSP handshake, reentrance logon, TLS/truststore, session resilience) so that driving adt-ls is a few lines of code.
Status: published on npm; current runtime compatibility verified on macOS arm64. The full SAP authoring
lifecycle (search → create → update → read → activate → run-tests → delete), plus code
intelligence, quality gates, ABAP formatting, transport, and OData service info, all run
end-to-end through createAdtLs() against a real S/4HANA system (adt-ls
1.1.2.202608131517). Runs under Node ≥ 20 and Bun (both verified live).
Install
npm install @arc-mcp/adt-ls
You bring adt-ls (SAP Developer License — not redistributable): install the
sapse.adt-vscode extension (VS Code / Cursor) and the library auto-discovers it, or
vendor the per-platform VSIX for CI. New here → docs/setup.md:
which platform build to download, CI vendoring, and connecting with auth.
Eclipse users: Eclipse ADT and the headless runtime have separate versions.
Your Eclipse installation does not supply this SDK's runtime; install/update
SAPSE.adt-vscode as described above. Current compatibility research and migration notes.
This release requires adt-ls >= 1.1.2 and is verified against 1.1.2.202608131517.
Quickstart
import { createAdtLs, basic } from '@arc-mcp/adt-ls';
const adt = await createAdtLs({
connection: { systemUrl: 'https://my-s4:50001', selfSigned: true, client: '001' },
auth: basic('DEVELOPER', process.env.SAP_PW!), // or bearer(token) / interactive({ openUrl }) / clientCert({ cert, key })
});
const hits = await adt.repository.search('CL_ABAP*', { types: ['CLAS/OC'] });
const src = await adt.source.read({ name: 'ZCL_FOO', objectType: 'CLAS/OC' });
await adt.lifecycle.create({ objectType: 'CLAS/OC', name: 'ZCL_BAR', packageName: '$TMP', description: 'demo' });
await adt.lifecycle.activate({ name: 'ZCL_BAR', objectType: 'CLAS/OC' });
await adt.dispose();
Auth strategies
The on-the-wire logon is always a reentrance ticket; auth supplies the credential:
basic(user, password)— headless user/password (on-prem fixed user).bearer(token | getToken)— headless OAuth bearer (BTP ABAP / Steampunk).interactive({ openUrl })— the consumer opens the SSO URL; a human signs in (the lib ships no browser/TTY).clientCert({ cert, key })— passwordless X.509 mutual TLS, no browser. The reverse proxy presents the client cert on every upstream hop, so the backend authenticates the TLS connection itself and the reentrance handler runs with no credential. Requiresconnection.selfSigned. Server-side this is the standard AS ABAP X.509 client-certificate logon- rule-based mapping (CERTRULE); it needs no KDC and no license (unlike Kerberos/SPNEGO). In an enterprise the cert is typically issued by SAP Secure Login Service (often from a Kerberos/SAML logon) or a corporate PKI. Consumers wire the cert source + server setup; arc-1-lsp ships a full guide.
import { createAdtLs, clientCert } from '@arc-mcp/adt-ls';
import { readFileSync } from 'node:fs';
const adt = await createAdtLs({
connection: { systemUrl: 'https://my-s4:50001', selfSigned: true, client: '001' },
auth: clientCert({ cert: readFileSync('client.crt'), key: readFileSync('client.key') }),
});
Low-level building blocks
Consumers that drive adt-ls themselves — e.g. proxying its MCP endpoint to external
agents — can skip createAdtLs() and use the primitives directly (this is what
abapify/openadt adopts):
import { resolveAdtLsPath, AdtLsDriver, startMcpServer } from '@arc-mcp/adt-ls';
const driver = new AdtLsDriver(resolveAdtLsPath(), {
extraArgs: ['-consoleLog', `-Djco.middleware.snc_lib=${sncLib}`], // SNC/JCo JVM flags
});
await driver.start(); // discovery + spawn + LSP initialize (short pipe; macOS-safe)
// register your own logon handlers: driver.setRequestHandler('adtLs/destinations/requestBrowserBasedLogon', …)
const { port, token } = await startMcpServer(driver, { port: 2240, token: myToken });
// → proxy http://localhost:${port}/mcp (Authorization: Bearer ${token}) however you like
await driver.dispose();
Capabilities
One namespaced client over both adt-ls channels (LSP + its own MCP) — the split is hidden:
capabilities()— fresh LSP providers and all MCP tool contracts, including schemas and annotations.repository— object search, file read/write/delete, inactive-object list, name→URI resolver.source/lifecycle— read; create, update, activate (native — per-phase diagnostics,forceActivation), run unit tests, delete; RAP generators; creatable-type catalog + creation-form (legal values per field), type-specific creation fields + validation.navigation— document symbols, definition/declaration, references, type hierarchy, hover, completion (with resolve → method signatures + ABAP-Doc), syntax check, semantic tokens, and ABAP Pretty-Printer formatting.quality— ATC static analysis + ABAP Unit code coverage.services— run a console app, service-binding details/publish, and live OData service info (URL + entity sets).transport— find / create / assign / list, lock status, and the transport decision oracle (check), and paged transport diffs (getDiff, backend-dependent).raw— escape hatches to any adt-ls MCP tool or LSP method.
What maps to which adt-ls call: the capability matrix. What's reachable headless vs. not (with live evidence): the capability survey.
Documentation
- Setup guide — start here: where to get the binary, which platform build, CI vendoring, and connecting with auth.
- 📖 API reference (hosted) — the full TypeDoc site, auto-published to GitHub Pages on every push to
main. - Usage guide — connecting, auth, the full API with examples, resilience, logging.
- Use cases — dev-tool & CI/CD recipes (ABAP Unit gate, ATC, syntax check, MCP server, scaffolding) with the API to use.
- API reference (Markdown) — the same reference rendered in-repo (
npm run docs:api). - Capability matrix — the method surface + the object-type support boundary.
- adt-ls capability survey — what the live binary offers vs. what's wrapped, and the known coverage gaps.
- ADRs — the architecture decisions (0001–0013).
Why this exists
Two first-party projects already drive headless adt-ls and reimplement the same
fragile, reverse-engineered plumbing: abapify/openadt (its
@openadt/sap-adt-mcp-launcher) and arc-1-lsp (src/adt-ls/*). Both encode the
identical landmines (the userAgentInfos NPE, HTTPS-only + hostname verification,
silent session death, the reentrance-ticket dance). The fragmentation that actually
hurt here is first-party duplication, and the cure is one shared library.
The thesis: adt-ls is the correct path (SAP-maintained CSRF/locking/activation/XML), but its setup is so much harder than calling ADT REST directly that people avoid it. This library makes adt-ls as easy to use as a plain API, so the easy choice is also the right one.
Scope — the hard line
adt-ls ONLY. No direct ADT/SAP HTTP, no SAP ADT SDK sidecar, no MCP server, no Cloud-Connector/BTP bridge inside the library. What adt-ls can't do headless is out of scope. See ADR-0001.
Current verification (2026-09-11)
Target: adt-ls 1.1.2.202608131517, bundled SAP Machine 21.12.0, macOS arm64, A4H over HTTPS port 443. The library's minimum runtime is 1.1.2 because activation, ABAP Unit, inactive-object listing and deletion contracts changed after the old baseline.
The test suite checks the real LSP handshake and presence of the MCP authoring tools; backend tests cover create/update/read/activate/test/delete, code intelligence, creation forms, service info, dictionary source and ABAP Unit coverage. Failure-path tests cover startup cleanup and MCP JSON/SSE, pagination, errors and timeouts.
See research and validation for measured results and the remaining platform/backend boundaries. This is not a claim of full Eclipse feature parity.
Consumers
- arc-1-lsp — replaces its
src/adt-ls/*entirely; keeps its own MCP server, BTP/Cloud-Connector bridge (via theconnection.forwardProxyhook), authz, and write-safety as thin wrappers over the lib. - openADT — its TypeScript launcher core can converge onto this lib.
History
Features 3, Fixes 4
Notes
Features
- lifecycle: optional uri on ObjectRef skips the name search (#29) (783588e)
- repository: typed readDirectory (#27) (132116c)
- source: read active source versions safely (#28) (a7c52ac)
Bug Fixes
- lifecycle: keep choice-field values in getCreationForm (#25) (e8d78b8)
- repository: use the main type for subtypes adt-ls can't filter (#26) (9ca86dc)
- services: refuse getServiceInfo on an un-published binding (#24) (dc961c8)
- transport: name SAP's reason when the assign lock check fails (#23) (e3272b2)
Features 1, Fixes 5
Notes
Features
Bug Fixes
- auth: send the destination client on ticket requests and honor the default client (#15, #16)
- lifecycle: resolve subtyped references through their main type (#11)
- lifecycle: reject transport backend refusals and incomplete results (#12, #18)
- services: publish from binding details and reject empty bindings (#14, #17)
- transport: verify assignments against CTS locks and reject failed checks (#13, #20)
Features 3, Fixes 1
Notes
Features
- lifecycle: getCreationForm — per-field legal values (value-help types + name regex) (96977e1)
- live-verified capabilities — formatting, native activate, transport check, completion resolve, semanticTokens (5049f1a)
- services: SRVB service info — listServices + getServiceInfo (OData URL + entity sets) (048e406)
Bug Fixes
- resilience: self-heal repository.search + raw.tool/LSP on session loss; honest backendLive (af2d272)
Others providing
Compare all 19 on the Editor support page →- abap-adt-apiabap-adt-apiA JS/TS client for the ADT resources an ABAP system exposes, so a program outside the system can do against it what the maintainer calls a good share of what the Eclipse tools do.independent, abapJS/TS client for the ADT resources of an ABAP system
- abap2UI5 Playgroundabap2UI5 PlaygroundABAP in the editor on the left and the abap2UI5 app it builds on the right, both inside one browser tab: the framework is transpiled to JavaScript at build time and the class in the editor is compiled when Run is pressed.community org, abapIn-browser ABAP editor beside the abap2UI5 app it builds
- abap2UI5 for VS Codeabap2UI5 for VS CodeA VS Code extension for abap2UI5 apps: F9 starts the app class in a preview beside the source, Ctrl+F3 activates the class and reloads it, and the abap2UI5 linter runs in the editor while you type.community org, abapVS Code extension to preview, activate and lint abap2UI5 apps
- vscode-tabl-ddicvscode-tabl-ddicA VS Code extension that registers .tabl.ddic files, the DDIC DDL form of an ABAP table definition, as a language of their own with a TextMate grammar for syntax highlighting, and nothing more.community org, abapVS Code syntax highlighting for .tabl.ddic table definitions
- HammerHammerA native macOS code editor for ABAP and CDS, with an Object Navigator, Transport Organizer, Data Browser and Gateway Client in the same app as the editor.independent, abapNative macOS code editor for ABAP and CDS
- abapthemesabapthemesThree colour themes for ABAP source in ABAP Development Tools for Eclipse, shipped as an Eclipse plugin and installed from the maintainer's own update site.independent, abapThree colour themes for ABAP source in ADT for Eclipse
- Cloud ALM Link for ADTCloud ALM Link for ADTAn Eclipse plugin that shows the transports and SAP Cloud ALM features behind an ABAP object, and turns Cloud ALM IDs in source comments into links.independent, abapEclipse plugin linking ABAP transports to SAP Cloud ALM features
- ABAP Call HierarchyABAP Call HierarchyAn Eclipse plugin that shows which members a class method, function module or subroutine calls, read from its own ADT backend in the system and published on a beta update site only.independent, abapEclipse plugin showing the call hierarchy of ABAP members
- abap-call-hierarchyabap-call-hierarchyThe ADT backend needed by the separate ABAP Call Hierarchy Eclipse plugin, installed in the ABAP system with abapGit and still in beta, which its maintainer calls not feature complete.independent, abapADT backend for the ABAP Call Hierarchy Eclipse plugin
- abap-tags-backendabap-tags-backendThe ADT backend needed by the separate ABAP Tags Eclipse plugin, installed in the ABAP system with abapGit; an upgrade to v2.0.0 or later runs a migration program for its new database tables.independent, abapADT backend for the ABAP Tags Eclipse plugin
- ABAP TagsABAP TagsAn Eclipse plugin for putting arbitrary tags on repository objects, with a Tag Manager view, tagged object search and tag import and export, served by its own ADT backend in the system.independent, abapEclipse plugin for tagging ABAP repository objects
- BellaBellaAn Eclipse plugin that puts Claude into ABAP Development Tools: explain, generate, rework and implement from the editor's context menu, completion as ghost text, and a chat whose tools reach the system through the developer's existing ADT logon.independent, abapEclipse plugin bringing Claude into ABAP Development Tools
- ABAP Syntax HighlightingABAP Syntax HighlightingA VS Code extension that registers .abap files as the language abap and colours them with a TextMate grammar.independent, abapVS Code syntax highlighting for .abap files
- abapfs_extensionsabapfs_extensionsABAP imported with abapGit that sets the stateful session flag on systems older than 7.51, so an HTTP client of the ADT resources can update objects there.independent, abapABAP objects enabling ADT updates on systems older than 7.51
- ABAP remote filesystemABAP remote filesystemA Visual Studio Code extension that opens an ABAP system over ADT as an editable filesystem and exposes system tools to GitHub Copilot and external MCP clients.independent, abapVS Code extension editing ABAP systems over ADT as a filesystem
- ABAP Development Tools for EclipseABAP Development Tools for EclipseSAP's Eclipse plugins for ABAP: source, dictionary and CDS editors, Project Explorer, Outline and ABAP Unit, calling ADT resources on the connected system.sap official, abapSAP's Eclipse plugins for ABAP development over ADT
- ABAP Development Tools for VS CodeABAP Development Tools for VS CodeSAP's ABAP tools in VS Code: editing, debugging, ABAP Unit, ATC and transports for classes, CDS and RAP objects, over RFC to an on-premise or Private Cloud system and HTTP to a cloud one, with Joule's ADT MCP server and code completion behind an AI-unit licence.sap official, abapSAP's ABAP tools in VS Code for editing, debugging, ATC and transports
- my-ide-actionsmy-ide-actionsA collection of eight ABAP Development Tools IDE Actions covering class creation, conversion of classic Open SQL to ABAP SQL, code snippets and RAP tooling.independent, abapCollection of ABAP Development Tools IDE Actions
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
History in the atlas
- First seen.
For your agent
- Ref
artifact:arc-mcp-adt-ls- JSON
- /artifacts/arc-mcp-adt-ls.json
- MCP
- Connecting an agent