sap-adt-mcp 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 yzonur
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,527 @@
1
+ # sap-adt-mcp
2
+
3
+ > **MCP server giving Claude (and any MCP-compatible client) live access to SAP systems via ADT.**
4
+ >
5
+ > Read source, search the repository, run syntax checks, run unit tests, run
6
+ > ATC, diff the same object across landscapes, edit and activate ABAP — all
7
+ > from a chat window or an autonomous agent. No add-on installation on the SAP
8
+ > stack required.
9
+
10
+ [![npm version](https://img.shields.io/npm/v/sap-adt-mcp.svg)](https://www.npmjs.com/package/sap-adt-mcp)
11
+ [![CI](https://github.com/yzonur/sap-adt-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/yzonur/sap-adt-mcp/actions/workflows/ci.yml)
12
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
13
+ [![Node.js](https://img.shields.io/node/v/sap-adt-mcp.svg)](https://nodejs.org)
14
+
15
+ ---
16
+
17
+ ## Why
18
+
19
+ SAP development is full of repetitive read-the-source / check-the-callers /
20
+ diff-the-system work. AI assistants are great at exactly that kind of task —
21
+ but only if they can reach the system. ADT (ABAP Development Tools) is the
22
+ HTTP API that Eclipse uses; it ships with every modern NetWeaver and S/4
23
+ system. This server speaks ADT on behalf of the agent so the agent can do real
24
+ work against your real systems, with the same auth and scoping you'd give a
25
+ developer in Eclipse.
26
+
27
+ ## What's in the box
28
+
29
+ **27 high-level tools** wrapped around the most common ADT endpoints, plus a
30
+ generic escape hatch for anything else, **plus 5 user-invokable Clean Core
31
+ prompts** that turn the tool surface into outcome-shaped slash commands
32
+ (see [Clean Core prompts](#clean-core-prompts) below).
33
+
34
+ | Category | Tools |
35
+ | --- | --- |
36
+ | Connection | `adt_list_systems`, `adt_ping` |
37
+ | Source CRUD | `adt_get_source`, `adt_set_source` |
38
+ | Quality | `adt_syntax_check`, `adt_pretty_print`, `adt_run_unit_tests`, `adt_run_atc`, `adt_run_atc_package`, `adt_run_atc_transport` |
39
+ | Lifecycle | `adt_create_object`, `adt_delete_object`, `adt_activate`, `adt_lock`, `adt_unlock`, `adt_list_inactive_objects` |
40
+ | Versions | `adt_list_versions`, `adt_compare_versions` |
41
+ | Discovery | `adt_browse_package`, `adt_list_packages`, `adt_search_objects`, `adt_grep_source`, `adt_where_used` |
42
+ | CDS | `adt_cds_data_preview`, `adt_cds_dependencies`, `adt_list_released_apis` |
43
+ | Cross-system | `adt_compare_source`, `adt_transport_diff` |
44
+ | Transports | `adt_list_transports`, `adt_get_transport`, `adt_create_transport`, `adt_release_transport` |
45
+ | Runtime errors | `adt_list_dumps`, `adt_get_dump` |
46
+ | Data | `adt_read_table` |
47
+ | Generation | `adt_rap_scaffold` |
48
+ | Experimental¹ | `adt_get_note`, `adt_check_note_status`, `adt_implement_note`, `adt_list_locks`, `adt_schedule_job`, `adt_read_spool` |
49
+ | Escape hatch | `adt_request` |
50
+
51
+ ¹ Experimental tools target ADT endpoints (SNOTE, SM12 enqueues, SM36/SP01)
52
+ that classic NetWeaver does not expose; on such systems they return
53
+ `available:false` with a fall-back hint rather than failing. They work where the
54
+ backing service exists (typically S/4HANA).
55
+
56
+ **Multi-system aware.** One config, many SAP systems (DEV / QAS / PRD or
57
+ landscape-wide); switch with the `system` argument or compare across two with
58
+ `adt_compare_source` / `adt_transport_diff`.
59
+
60
+ **Safe by default.** A `readOnly` flag (global or per-system) blocks every
61
+ write method. Read-only POST queries (search, where-used, package tree)
62
+ remain allowed so agents can still discover.
63
+
64
+ **Robust.** Per-request timeout. CSRF token negotiation with auto-retry on
65
+ 403. Self-signed cert opt-out. Optional debug tracing to stderr.
66
+
67
+ **Structured errors.** ADT's `<exc:exception>` envelopes are parsed into
68
+ `{ type, message, namespace }` so failed calls don't dump XML into the agent's
69
+ context window.
70
+
71
+ ## Install
72
+
73
+ > Previously published as `claude-for-abap` — that package still works but is
74
+ > deprecated; new installs should use `sap-adt-mcp`.
75
+
76
+ ```bash
77
+ # global
78
+ npm install -g sap-adt-mcp
79
+
80
+ # or run without installing
81
+ npx sap-adt-mcp
82
+ ```
83
+
84
+ Requires Node.js **22.19+** (undici v8, used as the HTTP client, requires
85
+ this minimum).
86
+
87
+ ## Configure
88
+
89
+ Create your config:
90
+
91
+ ```bash
92
+ mkdir -p ~/.sap-adt-mcp
93
+ cp config.example.json ~/.sap-adt-mcp/config.json
94
+ $EDITOR ~/.sap-adt-mcp/config.json
95
+ ```
96
+
97
+ The server searches in this order:
98
+
99
+ 1. `$SAP_ADT_MCP_CONFIG` (absolute path)
100
+ 2. `~/.sap-adt-mcp/config.json`
101
+ 3. `./config.json` (cwd at server start)
102
+
103
+ ### Sample config
104
+
105
+ ```json
106
+ {
107
+ "defaultSystem": "DEV",
108
+ "readOnly": false,
109
+ "systems": {
110
+ "DEV": {
111
+ "host": "https://sap-dev.example.com:44300",
112
+ "client": "100",
113
+ "language": "EN",
114
+ "user": "DEVELOPER",
115
+ "password": "env:SAP_DEV_PASSWORD",
116
+ "rejectUnauthorized": false
117
+ },
118
+ "QAS": {
119
+ "host": "https://sap-qas.example.com:44300",
120
+ "client": "200",
121
+ "user": "DEVELOPER",
122
+ "password": "env:SAP_QAS_PASSWORD"
123
+ },
124
+ "PRD": {
125
+ "host": "https://sap-prd.example.com:44300",
126
+ "client": "300",
127
+ "user": "READONLY",
128
+ "password": "env:SAP_PRD_PASSWORD",
129
+ "readOnly": true
130
+ }
131
+ }
132
+ }
133
+ ```
134
+
135
+ ### Per-system options
136
+
137
+ | Field | Meaning |
138
+ | --- | --- |
139
+ | `host` | Base URL including scheme + ICM HTTPS port (e.g. `https://...:44300`). |
140
+ | `client` | SAP client (sets `sap-client` query param). |
141
+ | `language` | Optional logon language (sets `sap-language`). |
142
+ | `user` | RFC user. |
143
+ | `password` | Either a literal string or `env:VAR_NAME` to read from environment. |
144
+ | `rejectUnauthorized` | Set `false` to skip TLS validation for self-signed certs. Default `true`. |
145
+ | `readOnly` | Block POST / PUT / DELETE / PATCH for this system (read-only POST queries still work). |
146
+ | `timeoutMs` | Override default 30 s request timeout. |
147
+
148
+ ### Read-only mode
149
+
150
+ `readOnly: true` (top-level or per-system) refuses any unsafe HTTP method.
151
+ Whitelisted read-only POST endpoints (`nodestructure`, `search`,
152
+ `usagereferences`, `parsers`, `checkruns`) remain available so agents can
153
+ still discover and analyze without being able to modify.
154
+
155
+ Recommended: set `readOnly: true` for QAS and PRD profiles. Keep DEV writable.
156
+
157
+ ### Self-signed certificates
158
+
159
+ Many internal SAP systems use self-signed certs. `"rejectUnauthorized": false`
160
+ disables TLS validation for that profile only. Don't set this on PRD.
161
+
162
+ ## Connect a client
163
+
164
+ ### Claude Code (CLI)
165
+
166
+ ```bash
167
+ claude mcp add sap-adt -- npx sap-adt-mcp
168
+ ```
169
+
170
+ Pass secrets through the registration:
171
+
172
+ ```bash
173
+ claude mcp add sap-adt \
174
+ --env SAP_DEV_PASSWORD=... \
175
+ --env SAP_PRD_PASSWORD=... \
176
+ -- npx sap-adt-mcp
177
+ ```
178
+
179
+ ### Claude Desktop
180
+
181
+ Edit `claude_desktop_config.json` (Settings → Developer → Edit Config):
182
+
183
+ ```json
184
+ {
185
+ "mcpServers": {
186
+ "sap-adt": {
187
+ "command": "npx",
188
+ "args": ["-y", "sap-adt-mcp"],
189
+ "env": {
190
+ "SAP_DEV_PASSWORD": "..."
191
+ }
192
+ }
193
+ }
194
+ }
195
+ ```
196
+
197
+ Quit and restart Claude Desktop fully (system tray → Quit) for the change to
198
+ apply.
199
+
200
+ ### Validate before connecting
201
+
202
+ ```bash
203
+ npx sap-adt-mcp --validate-config
204
+ ```
205
+
206
+ Loads the config and pings every system; exits non-zero if any are unreachable
207
+ or rejecting credentials. Run this first when troubleshooting.
208
+
209
+ ## Tools
210
+
211
+ ### Object-source CRUD
212
+
213
+ | Tool | Purpose | Notes |
214
+ | --- | --- | --- |
215
+ | `adt_get_source` | Fetch ABAP source by object name + type. | Returns plain text. For classes, pick the include via `include`: `main` (default), `definitions`, `implementations`, `macros`, `testclasses`. Function modules require `group`. |
216
+ | `adt_set_source` | Replace source. Orchestrates lock → PUT → unlock. | Optional `transport` parameter assigns the change to a TR (`corrNr`). Optional `lockHandle` to reuse an externally-acquired lock. Refused under `readOnly: true`. |
217
+ | `adt_create_object` | Create a new ABAP object in a package. | Supported types: program, class, interface, include, functiongroup, function, cds, accesscontrol, metadataext, behaviordef, messageclass. After creation, set the source body with `adt_set_source` and activate. Refused under `readOnly: true`. |
218
+ | `adt_delete_object` | Delete an object. | Acquires lock and DELETEs. Refused under `readOnly: true`. |
219
+ | `adt_activate` | Activate one or more objects. | Pass `objects: [{ name, type, group? }]`. |
220
+ | `adt_pretty_print` | Run the SAP-side ABAP formatter. | Stateless — pass source, get formatted source back. |
221
+ | `adt_lock` / `adt_unlock` | Acquire / release a lock for multi-step edits. | For one-shot edits, prefer `adt_set_source` (manages the lock for you). Use these when you need to keep an object locked across multiple writes within a single agent turn. |
222
+
223
+ ### Quality
224
+
225
+ | Tool | Purpose | Notes |
226
+ | --- | --- | --- |
227
+ | `adt_syntax_check` | ADT syntax check on an object. | Returns `<chkrun:reports>` XML; the agent reads severity + line numbers. |
228
+ | `adt_run_unit_tests` | ABAP Unit run. | Pass test container objects (typically classes). |
229
+ | `adt_run_atc` | ABAP Test Cockpit run. | API surface varies across NW releases — see Caveats. |
230
+
231
+ ### Discovery
232
+
233
+ | Tool | Purpose | Notes |
234
+ | --- | --- | --- |
235
+ | `adt_browse_package` | One level of package contents. | |
236
+ | `adt_list_packages` | Recursive walk from a root. | Has `prefix` (only descend into matching subpackages) and `maxPackages` safety cap (default 200). |
237
+ | `adt_search_objects` | Quick-search by name pattern. | `*` wildcard. Returns parsed `{ name, type, description, packageName, uri }` records. |
238
+ | `adt_where_used` | Where-used list. | Same parsed record shape. |
239
+
240
+ ### Cross-system
241
+
242
+ | Tool | Purpose | Notes |
243
+ | --- | --- | --- |
244
+ | `adt_compare_source` | Diff one object between two systems. | Returns unified diff + `{ added, removed }` stats. |
245
+ | `adt_transport_diff` | Diff every object in a TR between two systems. | Caps at `maxObjects` (default 50). |
246
+
247
+ ### Runtime errors
248
+
249
+ | Tool | Purpose | Notes |
250
+ | --- | --- | --- |
251
+ | `adt_list_dumps` | List ST22 short dumps. | Optional filters: `user`, `host`, `from`/`to` (YYYYMMDD), `maxResults` (default 20). Atom feed is parsed into structured entries with `runtimeError`, `program`, `user`, `updated`, and release-specific `rba:*`/`dump:*` fields surfaced as a map. Trims client-side because some releases ignore the server-side cap. |
252
+ | `adt_get_dump` | Fetch a single dump by id. | Two-step fetch: metadata XML (runtime error, program, links) followed by the formatted dump text from the `dump:link relation="contents"` sub-resource. Returns a `chapters` map (shortText, whatHappened, errorAnalysis, howToCorrect, whereTerminated, sourceCodeExtract, …). Pass `chapters: [...]` to limit, `full: true` to include the raw text. |
253
+
254
+ ### Data
255
+
256
+ | Tool | Purpose | Notes |
257
+ | --- | --- | --- |
258
+ | `adt_read_table` | Run an OpenSQL SELECT via the ADT Data Preview API. | SE16-style table reads. SELECT-only — INSERT/UPDATE/DELETE rejected client-side; the SAP endpoint enforces server-side too. `maxRows` capped at 5000 (default 100). Requires NetWeaver 7.55+ / S/4HANA. |
259
+
260
+ ### Transports
261
+
262
+ | Tool | Purpose | Notes |
263
+ | --- | --- | --- |
264
+ | `adt_list_transports` | List TRs by user / status. | Default user = config user; default status = `modifiable`. |
265
+ | `adt_get_transport` | TR header + objects. | |
266
+ | `adt_create_transport` | Create a new TR. | Refused under `readOnly: true`. Endpoint shape varies — see Caveats. |
267
+ | `adt_release_transport` | Release a TR. | Refused under `readOnly: true`. |
268
+
269
+ ### Escape hatch
270
+
271
+ `adt_request` — direct ADT REST call. Use this when a niche endpoint isn't
272
+ covered by a high-level tool. Handles auth / CSRF / cookies / sap-client
273
+ automatically.
274
+
275
+ ### Object types
276
+
277
+ Friendly aliases (any of either column work):
278
+
279
+ | Alias | TADIR code |
280
+ | --- | --- |
281
+ | program / report | PROG |
282
+ | include | INCL |
283
+ | class | CLAS |
284
+ | interface | INTF |
285
+ | function / fm | FUGR/FF (requires `group`) |
286
+ | functiongroup | FUGR |
287
+ | table / structure | TABL |
288
+ | dataelement | DTEL |
289
+ | domain | DOMA |
290
+ | cds / ddls | DDLS |
291
+ | accesscontrol / dcls | DCLS |
292
+ | metadataext / ddlx | DDLX |
293
+ | behaviordef / bdef | BDEF |
294
+ | messageclass / msag | MSAG |
295
+
296
+ ## Clean Core: prompts + reference
297
+
298
+ The server ships an opt-in **Clean Core** layer for SAP S/4HANA work.
299
+ There are two pieces, and they are deliberately separate:
300
+
301
+ - **Five MCP prompts** (`src/prompts.js`) — the operational surface. The
302
+ user invokes them as slash commands. Each one pairs a slice of the
303
+ Clean Core framework with the relevant `adt_*` tools so the model can
304
+ act on a real system, not just lecture about levels.
305
+ - **Long-form reference** ([`skills/abap-clean-core/`](skills/abap-clean-core/))
306
+ — the framework's full text: Stay Clean / Get Clean playbook, A/B/C/D
307
+ level deep-dive, Cloudification Repository state semantics, ABAP Cloud
308
+ allowed/forbidden lists, the SAP Application Extension Methodology
309
+ (3 phases), governance practices, KPI calculations, ATC exemption
310
+ process. Read once, link to it from PRs, hand to a new team member.
311
+ The prompts above quote what they need; the reference is everything
312
+ else.
313
+
314
+ ### Design choices
315
+
316
+ - **Opt-in, not auto-firing.** Clean Core is an S/4HANA discipline. ECC
317
+ developers should not have it imposed on them. Nothing fires unless the
318
+ user types the slash command.
319
+ - **ECC applicability check baked into every prompt.** The first thing
320
+ each prompt body asks the model to do is verify the target system is
321
+ S/4HANA. On ECC, it backs off and offers help in classic-ABAP idioms
322
+ with no level labels.
323
+ - **Tone is descriptive, not judgmental.** "I know it's Level D, just
324
+ ship it" is honored. The agent ships, marks the level, sketches the
325
+ Level A refactor for later, and moves on.
326
+
327
+ ### The prompts
328
+
329
+ In Claude Code (assuming you registered the server as `sap-adt`), the
330
+ exact commands are:
331
+
332
+ | Command | Arguments | What it does |
333
+ | --- | --- | --- |
334
+ | `/mcp__sap-adt__clean_core_grade` | `object` (req), `type` (req), `system` | Grade one object A/B/C/D. Pulls source + ATC, classifies, cites reasons, sketches the Level A refactor if Level C/D. |
335
+ | `/mcp__sap-adt__clean_core_review` | `package` (req), `system`, `maxObjects` (default 50) | Walk a package and compute Clean Core Share %, Tech Debt Score, top Level D offenders. |
336
+ | `/mcp__sap-adt__clean_core_refactor` | `object`, `type`, `system` (all optional) | Enter refactor mode. Loads BAPI-wrapper / MARA→released-CDS / modification→BAdI patterns. With `object` it pre-seeds; without, waits for direction. |
337
+ | `/mcp__sap-adt__clean_core_create` | `requirement`, `package`, `system` (all optional) | Enter creation mode at Level A by default — ABAP Cloud syntax, released CDS views, RAP, business object interfaces. Drives the `create_object → set_source → syntax_check → activate` pipeline. |
338
+ | `/mcp__sap-adt__clean_core_design` | `use_case` (optional) | Architecture mode — fit-to-standard, 3-phase methodology, on-stack vs side-by-side, hybrid. No code writes. Produces a target-solution memo. |
339
+
340
+ The slash-command name structure is determined by the MCP client: the
341
+ `mcp__<server-alias>__` prefix is added automatically based on the alias
342
+ you used when registering the server. If you registered the server with
343
+ a different alias (e.g. `claude mcp add cc -- npx sap-adt-mcp`), the
344
+ prefix changes accordingly (`/mcp__cc__clean_core_grade`).
345
+
346
+ In Claude Desktop, prompts appear in the slash-command picker — same
347
+ naming.
348
+
349
+ ### Argument flow examples
350
+
351
+ Atomic prompts (`grade`, `review`) take all their arguments inline and
352
+ return a structured analysis:
353
+
354
+ ```
355
+ You: /mcp__sap-adt__clean_core_grade object:ZCL_PRICING type:class system:DEV
356
+ Agent: → adt_get_source { ... }
357
+ → adt_run_atc { ... }
358
+ Verdict: Level C. Two SELECTs from MARA without using the released
359
+ I_Product view; one CALL FUNCTION to internal FM RV_PRICE_PRINT.
360
+ Refactor sketch: replace SELECT with `from I_Product`; encapsulate
361
+ the RV_PRICE_PRINT call in a Z-class so the dependency is localised.
362
+ ```
363
+
364
+ Mode-loading prompts (`refactor`, `create`, `design`) optionally take a
365
+ seed; without one, they wait for the user's natural-language follow-up:
366
+
367
+ ```
368
+ You: /mcp__sap-adt__clean_core_create
369
+ Agent: I'm in Clean Core CREATE mode (Level A by default). What do you
370
+ want to build, on which package and system?
371
+ You: A small Fiori list-report of overdue invoices, package ZFIN_REPORTS,
372
+ system DEV.
373
+ Agent: Plan: a CDS view projecting I_OperationalAcctgDocItemCube for items
374
+ with NetDueDate < today; a behavior definition; a service binding
375
+ exposing it to Fiori Elements list-report. Three objects. Confirm?
376
+ ```
377
+
378
+ Or with a seed argument so the request is one-shot:
379
+
380
+ ```
381
+ You: /mcp__sap-adt__clean_core_create requirement:"Fiori list-report of
382
+ overdue invoices" package:ZFIN_REPORTS system:DEV
383
+ ```
384
+
385
+ ### Read the long-form reference
386
+
387
+ [`skills/abap-clean-core/`](skills/abap-clean-core/) is the canonical
388
+ source for everything the prompts quote and more. If you're setting up
389
+ Clean Core governance for a real program — KPI baselines, ATC exemption
390
+ discipline, maturity assessment, on-stack vs side-by-side trade-offs at
391
+ the architecture level — that's where the depth lives.
392
+
393
+ The directory is structured as one entry point (`SKILL.md`) plus four
394
+ deep-dive files in `references/`:
395
+
396
+ - `references/levels-detailed.md` — Cloudification Repository state
397
+ values, released local vs released remote APIs, reclassification
398
+ dynamics, per-anti-pattern remediation
399
+ - `references/decision-framework.md` — fit-to-standard, the SAP
400
+ Application Extension Methodology in detail, on-stack vs side-by-side
401
+ triggers, hybrid patterns, worked scenarios
402
+ - `references/governance.md` — Stay Clean / Get Clean playbook, the four
403
+ KPIs and how to compute them, ATC exemption process, maturity
404
+ assessment, multi-year roadmap
405
+ - `references/abap-cloud-rules.md` — full allowed/forbidden lists, RAP /
406
+ CDS / business object interfaces / Custom Fields, prebuilt services,
407
+ classic-to-cloud migration patterns
408
+
409
+ You can install the reference as an actual auto-loading Claude skill by
410
+ copying or symlinking `skills/abap-clean-core/` into your
411
+ `~/.claude/skills/` — but that's an explicit choice. The default
412
+ behavior of this repo is opt-in, prompt-only.
413
+
414
+ ## Examples
415
+
416
+ See [`examples/`](examples) for end-to-end agent workflows: project discovery,
417
+ class audit, cross-system release verification, where-used-driven refactor,
418
+ test triage.
419
+
420
+ Quick taste:
421
+
422
+ ```
423
+ You: "Compare class ZCL_PRICING between DEV and PRD on the live systems."
424
+ Agent: → adt_compare_source { systemA: "DEV", systemB: "PRD",
425
+ object: "ZCL_PRICING", type: "class" }
426
+ Returns: { identical: false, stats: { added: 14, removed: 9 },
427
+ diff: "..." }
428
+ Then narrates the meaningful changes.
429
+ ```
430
+
431
+ ## Architecture
432
+
433
+ ```
434
+ MCP client (Claude Desktop / Claude Code / custom)
435
+ │ stdio (JSON-RPC)
436
+
437
+ ┌──────────────────────────────────┐
438
+ │ src/server.js │ CLI + MCP dispatch (thin)
439
+ │ ├─ src/tools/*.js │ one module per category:
440
+ │ │ │ connection, source, quality,
441
+ │ │ │ lifecycle, discovery,
442
+ │ │ │ cross-system, transports,
443
+ │ │ │ runtime, data, request
444
+ │ ├─ src/object-uris.js │ type alias → ADT URI map
445
+ │ ├─ src/node-structure.js │ package tree XML parser
446
+ │ ├─ src/object-references.js │ <objectReference> parser
447
+ │ ├─ src/dump-feed.js │ runtime-dumps Atom parser
448
+ │ ├─ src/data-preview.js │ Data Preview XML parser + SELECT guard
449
+ │ ├─ src/diff.js │ unified diff (LCS)
450
+ │ ├─ src/adt-error.js │ <exc:exception> parser
451
+ │ ├─ src/lock.js │ ADT lock acquire / release
452
+ │ └─ src/adt-client.js │ HTTP client: auth / CSRF / cookies / timeout
453
+ └──────────────────────────────────┘
454
+ │ HTTPS
455
+
456
+ SAP system (ADT REST: /sap/bc/adt/...)
457
+ ```
458
+
459
+ Two runtime dependencies: `@modelcontextprotocol/sdk` (the MCP wire protocol)
460
+ and `undici` (HTTP with custom TLS dispatcher). Everything else is stdlib.
461
+
462
+ ## Multi-step editing pattern
463
+
464
+ For most edits, `adt_set_source` is enough — it acquires the lock, writes,
465
+ and releases. For workflows that touch the same object multiple times within
466
+ a single turn (e.g. apply N method-level patches, then activate), use the
467
+ sticky-lock pattern:
468
+
469
+ ```text
470
+ 1. adt_lock { object: "ZCL_X", type: "class" } → returns lockHandle
471
+ 2. adt_set_source { object: "ZCL_X", type: "class", (repeat as needed)
472
+ source: "...", lockHandle: "<handle>" }
473
+ 3. adt_activate { objects: [{ name: "ZCL_X", type: "class" }] }
474
+ 4. adt_unlock { object: "ZCL_X", type: "class",
475
+ lockHandle: "<handle>" }
476
+ ```
477
+
478
+ The `lockHandle` parameter on `adt_set_source` skips internal lock/unlock
479
+ when present.
480
+
481
+ ## Caveats
482
+
483
+ - **NetWeaver release variation.** A few ADT endpoints (especially around
484
+ transport requests, ATC, and object-create XML shapes) have small shape
485
+ differences across NW 7.5x, S/4 on-prem, and Steampunk. If a high-level
486
+ tool fails with HTTP 4xx, the tool description notes which endpoint it
487
+ hits — fall back to `adt_request` with the right path / content type for
488
+ your release.
489
+ - **ABAP Cloud (BTP / Steampunk).** Only on-prem ADT 7.5x+ has been actively
490
+ exercised. Steampunk uses a stricter object-type allowlist (only released
491
+ / public APIs) and some collection endpoints differ. Steampunk users:
492
+ please open an issue with the endpoints that differ; PRs welcome.
493
+ - **Object-create XML shapes.** The body templates target modern on-prem
494
+ releases. Some older systems require additional attributes
495
+ (`adtcore:masterLanguage`, etc.) — open an issue if your system rejects
496
+ the create payload, and include the response body.
497
+ - **DDIC primitives** (tables, data elements, domains) are not creatable via
498
+ `adt_create_object` — these need a richer DDIC-specific payload that we
499
+ haven't generalised. Use `adt_request` for now.
500
+
501
+ ## Troubleshooting
502
+
503
+ **"failed" in Claude Desktop's MCP server list.** Run `sap-adt-mcp
504
+ --validate-config` from a terminal. If that prints OK, the server is fine and
505
+ the issue is in your `claude_desktop_config.json` (wrong path or env).
506
+
507
+ **403 with `x-csrf-token: required`.** Should self-heal — the client refetches
508
+ the token and retries. If it persists, you likely have an SSO / front-end
509
+ auth in front of ADT that breaks Basic auth; check your ICM and SAP web
510
+ dispatcher rules.
511
+
512
+ **Read-only mode refuses an obviously-read endpoint.** It's probably a POST
513
+ endpoint not in the whitelist. Open a PR or issue with the path; we'll add
514
+ it. Or temporarily flip the system to `readOnly: false`.
515
+
516
+ **`SAP_ADT_MCP_DEBUG=1`** traces every request and response (status, latency,
517
+ URL, request headers minus `Authorization`) to stderr. The MCP client shows
518
+ stderr in its server log, so check there.
519
+
520
+ ## Contributing
521
+
522
+ See [CONTRIBUTING.md](CONTRIBUTING.md) — bug reports, new tool coverage,
523
+ NetWeaver compatibility notes, docs, examples all welcome.
524
+
525
+ ## License
526
+
527
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,32 @@
1
+ {
2
+ "defaultSystem": "DEV",
3
+ "instanceId": "756930e3-3bd4-6893-1f4c-3f5c266f2c66",
4
+ "readOnly": false,
5
+ "systems": {
6
+ "DEV": {
7
+ "host": "https://sap-dev.example.com:44300",
8
+ "client": "100",
9
+ "language": "EN",
10
+ "user": "DEVELOPER",
11
+ "password": "env:SAP_DEV_PASSWORD",
12
+ "rejectUnauthorized": false
13
+ },
14
+ "QAS": {
15
+ "host": "https://sap-qas.example.com:44300",
16
+ "client": "200",
17
+ "language": "EN",
18
+ "user": "DEVELOPER",
19
+ "password": "env:SAP_QAS_PASSWORD",
20
+ "rejectUnauthorized": true
21
+ },
22
+ "PRD": {
23
+ "host": "https://sap-prd.example.com:44300",
24
+ "client": "300",
25
+ "language": "EN",
26
+ "user": "READONLY",
27
+ "password": "env:SAP_PRD_PASSWORD",
28
+ "rejectUnauthorized": true,
29
+ "readOnly": true
30
+ }
31
+ }
32
+ }
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "sap-adt-mcp",
3
+ "version": "0.7.1",
4
+ "description": "MCP server giving Claude live access to SAP systems via ADT (ABAP Development Tools) REST. Read source, search, run syntax checks, and edit ABAP objects from any MCP-compatible client.",
5
+ "type": "module",
6
+ "main": "src/server.js",
7
+ "bin": {
8
+ "sap-adt-mcp": "src/server.js",
9
+ "claude-for-abap": "src/server.js"
10
+ },
11
+ "files": [
12
+ "src",
13
+ "config.example.json",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "engines": {
18
+ "node": ">=22.19"
19
+ },
20
+ "scripts": {
21
+ "start": "node src/server.js",
22
+ "test": "node --test test/adt-error.test.js test/atc-bulk.test.js test/cds.test.js test/data-preview.test.js test/diff.test.js test/dump-feed.test.js test/grep-source.test.js test/jobs.test.js test/lifecycle-activate.test.js test/lock.test.js test/mcp-bug-fixes.test.js test/node-structure.test.js test/notes.test.js test/object-create.test.js test/object-references.test.js test/object-uris.test.js test/prompts.test.js test/provenance.test.js test/rap-scaffold.test.js test/security.test.js test/source-chunked.test.js test/source-guard.test.js test/source-pagination.test.js test/tools-shape.test.js test/versions.test.js test/worklist.test.js",
23
+ "lint": "eslint src test"
24
+ },
25
+ "keywords": [
26
+ "mcp",
27
+ "model-context-protocol",
28
+ "claude",
29
+ "anthropic",
30
+ "sap",
31
+ "abap",
32
+ "adt",
33
+ "abap-development-tools",
34
+ "ai-agent"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/yzonur/sap-adt-mcp.git"
39
+ },
40
+ "bugs": {
41
+ "url": "https://github.com/yzonur/sap-adt-mcp/issues"
42
+ },
43
+ "homepage": "https://github.com/yzonur/sap-adt-mcp#readme",
44
+ "author": "yzonur",
45
+ "license": "MIT",
46
+ "dependencies": {
47
+ "@modelcontextprotocol/sdk": "^1.0.4",
48
+ "undici": "^8.1.0"
49
+ },
50
+ "devDependencies": {
51
+ "@eslint/js": "^10.0.1",
52
+ "eslint": "^10.3.0",
53
+ "globals": "^17.6.0"
54
+ }
55
+ }