Glue between ARC-1 (MCP server for SAP ADT) and SAP's official
ABAP Development Tools for VS Code (SAPSE.adt-vscode), so GitHub Copilot can open, link to, diff and
— most usefully — validate ABAP objects that live in SAP rather than on disk.
Copilot can edit ABAP natively: sapse.adt-vscode exposes a writable abap: filesystem, so an ABAP
object is a workspace file, and Copilot's own edit tools produce real hunks with Keep/Undo. Two gaps
remain, and this extension fills them.
- SAP's extension has no public API. No way to open an object by name, no URI handler. So a model
that mentions
ZCL_FOOcannot get you to it. - SAP rejects source that looks like valid ABAP. A comment in a position the class serializer cannot store, for example — and nothing in the IDE knows until the save fails. ARC-1 can answer that question in under a second without writing anything.
Which makes the division of labour: Copilot writes. ARC-1 says whether SAP will accept it.
abapOpen |
Resolve an object name → open it in the real SAP editor. Returns a clickable vscode:// link. |
abapValidate |
Ask SAP whether the current buffer would be accepted, before saving. Separates findings your edit introduced from pre-existing ones. |
abapChanges |
Side-by-side diff: last activated version ↔ the inactive draft. Right side stays editable. |
vscode:// links |
Deep links from chat resolve into the editor. |
| Copilot instructions | Writes the division-of-labour block into .github/copilot-instructions.md. |
| Journal watcher | Off by default. Set journalDir and every ARC-1 write record pops a diff. |
- VS Code 1.105+
SAPSE.adt-vscode, logged on (ABAP: Log On to Destination...)- At least one ABAP folder in the workspace (
ABAP: Add Package as Folder to Workspace...— a whole destination works too, see How lookup works) - ARC-1 as an MCP server — required for
abapValidateand for fast package lookup
No build step and no runtime dependencies — plain JavaScript. (devDependencies exist only for
npm run typecheck.)
git clone https://github.com/arc-mcp/arc1-abap-bridge.git && cd arc1-abap-bridgePackage it into a .vsix:
npx --yes @vscode/vsce package --allow-missing-repositorycode points at. With Cursor installed it very likely owns /usr/local/bin/code, and
code --install-extension will silently install into Cursor instead of VS Code:
ls -l "$(which code)"Use the full path when in doubt:
"/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" --install-extension ./arc1-abap-bridge-0.9.0.vsix --forceRestart VS Code (a window reload is not enough for a newly installed extension), then ⇧⌘P →
ABAP Bridge: Open ABAP Object by Name....
abapValidate and fast package lookup call ARC-1 over MCP. Add it
to VS Code's mcp.json (⇧⌘P → MCP: Open User Configuration):
{
"servers": {
"arc-1": {
"type": "stdio",
"command": "npx",
"args": ["-y", "arc-1@latest"],
"env": {
"SAP_URL": "https://your-sap-host",
"SAP_USER": "YOURUSER",
"SAP_PASSWORD": "…",
"SAP_CLIENT": "100",
"SAP_ALLOW_WRITES": "false"
}
}
}
}SAP_ALLOW_WRITES can stay false. The IDE does the writing through SAP's own extension; ARC-1
only reads and runs the syntax check, both of which are read-scoped. Nothing here needs write access.
Optional: set ARC1_IDE_LINKS to vscode and ARC-1 appends a clickable vscode:// link to
single-object results, which this extension resolves and opens. That needs ARC-1 ≥ the version where
ARC1_IDE_LINKS landed; without it everything else still works.
| Command | What |
|---|---|
Open ABAP Object by Name... |
resolve a name and open it |
Show Inactive Changes (Diff) |
diff activated ↔ inactive |
Validate Buffer Against SAP |
ask SAP whether the open buffer would be accepted |
Write Copilot Instructions |
append the instruction block to .github/copilot-instructions.md |
Run Integration Self-Test |
measure the whole chain and write a report file |
Diagnose (write report file) |
dump workspace folders, root listings, last search |
Clear Object Index |
drop the cached name→URI, object→package and package→folder maps |
| Setting | Default | What |
|---|---|---|
validateBeforeSave |
true |
Warn on save when SAP would reject the buffer. A safety net — the real mechanism is the model calling abapValidate. |
usePackageLookupTool |
true |
Ask ARC-1 for an object's package instead of searching the tree. One SAP call, no model turn. |
journalDir |
"" |
Directory ARC-1 drops write-journal records into. Empty = off. |
searchBudget |
600 |
Max directories listed per lookup. |
searchDepth |
8 |
Max folder depth per lookup. |
searchTimeoutMs |
45000 |
Give up rather than hang a chat request. |
searchConcurrency |
6 |
Parallel listings. Too many can knock the ABAP language server offline. |
searchFanoutLimit |
60 |
Never descend blindly into a folder wider than this. |
sapse.adt-vscode enables no proposed APIs, so it registers no FileSearchProvider — findFiles does
not work on abap: — and its own name→URI resolver lives in the Java language server where no other
extension can reach it. The URI is tree-shaped and backend-labelled:
abap:/repotree-v1/A4H2023/System%20Library/ZARC1_DEMO/Source%20Code%20Library/Classes/ZCL_X/zcl_x.clas.abap
so it cannot be synthesised from a name either. Worse, a workspace rooted at a whole destination puts
every package in the system under System Library — a blind walk measured 2181 listings by depth 4
and needed roughly ten thousand.
So resolution goes: open editors → persisted caches (object→URI, object→package, package→folder) →
the package, supplied by the caller or fetched from ARC-1's SAPSearch(tadir_lookup) via
vscode.lm.invokeTool (one SAP call, no model turn), which lets the search jump straight to that subtree
(~15 listings) → a bounded walk of everything else with a fan-out guard: a folder with more
subfolders than searchFanoutLimit is never descended into blindly.
Nothing about the tree labels is hardcoded — only the shape of the fan-out — so a non-English logon and new object types keep working.
Mirrors what SAP's extension itself treats as editable source: files ending in .abap, .acds,
.ddic — the three languages sapse.adt-vscode registers. The object type is derived from the tag in
the file name (zcl_x.clas.abap → CLAS, ztable.tabl.ddic → TABL, zc_flight.ddls.acds → DDLS),
so new types work without a code change.
DDIC metadata files (.dtelde.jsonc, .domadd.jsonc, .clas.json, .properties) are deliberately
skipped — SAP's own stub for them says "not supported in ABAP development tools for VS Code."
- Copilot edits
abap:files natively with Keep/Undo, and the change round-trips into SAP. - The object must be in a chat edit session — invoked outside one, Copilot mangles the URI to
file:///abap%3A/…. abapValidatecatches what no local linter can: SAP refused a comment placement twice, each caught in ~800 ms with nothing written. Offline abaplint cannot substitute — it fails to resolve DDIC types and crashes on exactly the classes this matters for.- The activated ↔ inactive diff, left = activated, right = the editable draft.
vscode://links from a Copilot answer are clickable and route back into the extension.
- The diff only works while the object is still inactive. After activation the previous version is
gone — that is what
journalDiris for. - A dead ADT session surfaces as
NoPermissions … Method "createDirectory" not yet implemented, which says nothing about being logged out. The bridge detects it and reports the real cause. ⌘Sis a no-op while a Copilot hunk is pending — Keep is the commit-and-save.
npm test && npm run typechecklib.test.js covers the pure logic (name matching, type derivation, deep links, journal validation,
change summary). activate.test.js runs the real activate() against a stubbed vscode and asserts
every command and language-model tool declared in package.json is actually registered — the drift that
would otherwise show up as a broken palette entry. npm run typecheck checks against @types/vscode
pinned to the engines floor, so no newer API sneaks in.
Everything else needs a live SAP logon: use ABAP Bridge: Run Integration Self-Test, which measures the
whole chain (writability, invokable edit tools, resolution, read-through, a third-party WorkspaceEdit,
and optionally copilot_applyPatch) and writes a report to ~/arc1-abap-bridge-selftest.json.