@mcp-abap-adt/core 2.3.0 → 2.4.0

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +3 -2
  3. package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.d.ts +79 -0
  4. package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.d.ts.map +1 -0
  5. package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.js +75 -0
  6. package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.js.map +1 -0
  7. package/dist/handlers/system/readonly/handleRuntimeGetDumpById.d.ts +27 -0
  8. package/dist/handlers/system/readonly/handleRuntimeGetDumpById.d.ts.map +1 -0
  9. package/dist/handlers/system/readonly/handleRuntimeGetDumpById.js +48 -0
  10. package/dist/handlers/system/readonly/handleRuntimeGetDumpById.js.map +1 -0
  11. package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.d.ts +27 -0
  12. package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.d.ts.map +1 -0
  13. package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.js +47 -0
  14. package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.js.map +1 -0
  15. package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.d.ts +53 -0
  16. package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.d.ts.map +1 -0
  17. package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.js +83 -0
  18. package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.js.map +1 -0
  19. package/dist/handlers/system/readonly/handleRuntimeListDumps.d.ts +48 -0
  20. package/dist/handlers/system/readonly/handleRuntimeListDumps.d.ts.map +1 -0
  21. package/dist/handlers/system/readonly/handleRuntimeListDumps.js +75 -0
  22. package/dist/handlers/system/readonly/handleRuntimeListDumps.js.map +1 -0
  23. package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.d.ts +18 -0
  24. package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.d.ts.map +1 -0
  25. package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.js +39 -0
  26. package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.js.map +1 -0
  27. package/dist/handlers/system/readonly/runtimePayloadParser.d.ts +6 -0
  28. package/dist/handlers/system/readonly/runtimePayloadParser.d.ts.map +1 -0
  29. package/dist/handlers/system/readonly/runtimePayloadParser.js +28 -0
  30. package/dist/handlers/system/readonly/runtimePayloadParser.js.map +1 -0
  31. package/dist/lib/config/ArgumentsParser.js +2 -2
  32. package/dist/lib/config/ArgumentsParser.js.map +1 -1
  33. package/dist/lib/config/ServerConfigManager.d.ts.map +1 -1
  34. package/dist/lib/config/ServerConfigManager.js +4 -2
  35. package/dist/lib/config/ServerConfigManager.js.map +1 -1
  36. package/dist/lib/config/yamlConfig.d.ts +2 -1
  37. package/dist/lib/config/yamlConfig.d.ts.map +1 -1
  38. package/dist/lib/config/yamlConfig.js +18 -7
  39. package/dist/lib/config/yamlConfig.js.map +1 -1
  40. package/dist/lib/handlers/groups/SystemHandlersGroup.d.ts.map +1 -1
  41. package/dist/lib/handlers/groups/SystemHandlersGroup.js +45 -0
  42. package/dist/lib/handlers/groups/SystemHandlersGroup.js.map +1 -1
  43. package/dist/lib/utils.d.ts.map +1 -1
  44. package/dist/lib/utils.js +5 -4
  45. package/dist/lib/utils.js.map +1 -1
  46. package/dist/server/SseServer.d.ts.map +1 -1
  47. package/dist/server/SseServer.js +7 -3
  48. package/dist/server/SseServer.js.map +1 -1
  49. package/dist/server/StreamableHttpServer.d.ts.map +1 -1
  50. package/dist/server/StreamableHttpServer.js +10 -5
  51. package/dist/server/StreamableHttpServer.js.map +1 -1
  52. package/dist/server/launcher.js +1 -1
  53. package/dist/server/launcher.js.map +1 -1
  54. package/docs/architecture/ARCHITECTURE.md +706 -0
  55. package/docs/architecture/README.md +1 -0
  56. package/docs/configuration/YAML_CONFIG.md +25 -22
  57. package/docs/user-guide/AVAILABLE_TOOLS.md +73 -3
  58. package/docs/user-guide/AVAILABLE_TOOLS_HIGH.md +1 -1
  59. package/docs/user-guide/AVAILABLE_TOOLS_LOW.md +1 -1
  60. package/docs/user-guide/AVAILABLE_TOOLS_READONLY.md +72 -2
  61. package/docs/user-guide/CLI_OPTIONS.md +6 -5
  62. package/package.json +7 -7
@@ -0,0 +1,706 @@
1
+ # MCP ABAP ADT -- System Architecture
2
+
3
+ This document provides a comprehensive architectural description of the **mcp-abap-adt** system: a multi-component, interface-driven TypeScript platform that enables AI assistants to interact with SAP ABAP systems through the ADT (ABAP Development Tools) REST API via the Model Context Protocol (MCP).
4
+
5
+ ---
6
+
7
+ ## 1. Architectural Principles
8
+
9
+ ### 1.1 Interface-Only Communication (IOC)
10
+
11
+ All inter-package communication occurs exclusively through TypeScript interfaces defined in `@mcp-abap-adt/interfaces`. No package imports concrete implementations from another package. This is not a guideline -- it is an enforced architectural invariant.
12
+
13
+ ```typescript
14
+ // Correct -- depends on interface only
15
+ import type { ISessionStore } from '@mcp-abap-adt/interfaces';
16
+
17
+ // Prohibited -- creates concrete coupling
18
+ import { AbapSessionStore } from '@mcp-abap-adt/auth-stores';
19
+ ```
20
+
21
+ ### 1.2 Dependency Inversion
22
+
23
+ All high-level modules depend on abstractions (interfaces), not on low-level implementations. Concrete implementations are injected at the composition root (`launcher.ts` in the main server). This ensures that every component can be tested in isolation and replaced without modifying consumers.
24
+
25
+ ### 1.3 Replaceable Default Implementations
26
+
27
+ Every interface shipped with the system has at least one default implementation. Consumers are free to substitute any default with a custom implementation that satisfies the same interface contract. The system makes no assumptions beyond what interfaces specify.
28
+
29
+ ### 1.4 Separation of Concerns
30
+
31
+ Each package owns exactly one responsibility:
32
+
33
+ | Concern | Package |
34
+ |:---|:---|
35
+ | Interface contracts | `@mcp-abap-adt/interfaces` |
36
+ | Logging abstraction | `@mcp-abap-adt/logger` |
37
+ | Header validation | `@mcp-abap-adt/header-validator` |
38
+ | Credential storage | `@mcp-abap-adt/auth-stores` |
39
+ | Token orchestration | `@mcp-abap-adt/auth-broker` |
40
+ | Token acquisition flows | `@mcp-abap-adt/auth-providers` |
41
+ | HTTP transport to SAP | `@mcp-abap-adt/connection` |
42
+ | ABAP object operations | `@mcp-abap-adt/adt-clients` |
43
+ | MCP protocol adapter | `mcp-abap-adt` (main server) |
44
+ | Authorization proxy | `@mcp-abap-adt/proxy` |
45
+ | Client configurator | `@mcp-abap-adt/configurator` |
46
+
47
+ ### 1.5 Clear Runtime Contracts
48
+
49
+ Every public function and method operates against well-defined input/output types. Error conditions are expressed through typed error codes (`AdtObjectErrorCodes`, `TokenProviderErrorCodes`, `StoreErrorCodes`), not raw strings. This makes error handling deterministic across all consumers.
50
+
51
+ ---
52
+
53
+ ## 2. Component Catalogue
54
+
55
+ ### 2.1 @mcp-abap-adt/interfaces
56
+
57
+ | Attribute | Value |
58
+ |:---|:---|
59
+ | **Responsibility** | Single source of truth for all TypeScript interfaces, types, enums, and error codes |
60
+ | **Dependencies** | None (base package) |
61
+ | **Replaceable** | N/A -- defines contracts, not implementations |
62
+ | **Runtime role** | Type-only at runtime (compile-time contracts) |
63
+
64
+ **Interface domains:**
65
+
66
+ | Domain | Key Interfaces | Purpose |
67
+ |:---|:---|:---|
68
+ | Connection | `IAbapConnection`, `IAbapRequestOptions`, `IAdtResponse` | HTTP communication with SAP ADT |
69
+ | Authentication | `IAuthorizationConfig`, `IConnectionConfig`, `IConfig` | Auth credential structures |
70
+ | Token | `ITokenProvider`, `ITokenResult`, `ITokenRefresher` | Token lifecycle management |
71
+ | Session | `ISessionStore`, `ISessionStorage`, `ISessionState` | Session persistence |
72
+ | Service Key | `IServiceKeyStore` | Service key access |
73
+ | ADT Objects | `IAdtObject<TConfig, TState>`, `IAdtObjectState`, `IAdtObjectConfig` | CRUD lifecycle for ABAP objects |
74
+ | Logging | `ILogger`, `LogLevel` | Structured logging |
75
+ | Validation | `IHeaderValidationResult`, `IValidatedAuthConfig` | Header analysis |
76
+ | SAP Config | `ISapConfig`, `SapAuthType` | SAP system configuration |
77
+ | Headers | `HEADER_*` constants, header group arrays | HTTP header contracts |
78
+
79
+ **Generic object model** -- every ABAP object type is modeled through two generic parameters:
80
+
81
+ - **`TConfig`** -- static metadata (name, package, description, transport request)
82
+ - **`TState extends IAdtObjectState`** -- accumulated operation results (read, create, lock, activate, errors)
83
+
84
+ This allows `IAdtObject<TConfig, TState>` to provide a uniform CRUD interface across all 22+ supported ABAP object types.
85
+
86
+ ---
87
+
88
+ ### 2.2 @mcp-abap-adt/logger
89
+
90
+ | Attribute | Value |
91
+ |:---|:---|
92
+ | **Responsibility** | Logging abstraction with two default implementations |
93
+ | **Public interface** | `ILogger` (info, error, warn, debug) |
94
+ | **Default implementations** | `DefaultLogger` (console-based), `PinoLogger` (structured, with fallback) |
95
+ | **Replaceable** | Yes -- any `ILogger` implementation accepted |
96
+ | **Runtime role** | Injected into all components that produce diagnostic output |
97
+ | **Dependencies** | `@mcp-abap-adt/interfaces`; `pino` as optional peer dependency |
98
+
99
+ `PinoLogger` dynamically loads `pino` at runtime. If pino is not installed, it silently falls back to `DefaultLogger`. Both implementations respect the `AUTH_LOG_LEVEL` environment variable and redact sensitive fields (passwords, tokens, authorization headers).
100
+
101
+ ---
102
+
103
+ ### 2.3 @mcp-abap-adt/header-validator
104
+
105
+ | Attribute | Value |
106
+ |:---|:---|
107
+ | **Responsibility** | Validates and normalizes incoming HTTP authorization headers |
108
+ | **Public interface** | `IHeaderValidationResult`, `IValidatedAuthConfig` |
109
+ | **Replaceable** | Yes |
110
+ | **Runtime role** | Used by HTTP/SSE transport servers to extract auth parameters from request headers |
111
+ | **Dependencies** | `@mcp-abap-adt/interfaces` |
112
+
113
+ Supports prioritized authentication methods:
114
+
115
+ | Priority | Method | Headers |
116
+ |:---|:---|:---|
117
+ | 4 (highest) | SAP Destination (AuthBroker) | `x-sap-destination` |
118
+ | 3 | MCP Destination + JWT | `x-mcp-destination` + `x-sap-auth-type=jwt` |
119
+ | 2 | Direct JWT | `x-sap-jwt-token` |
120
+ | 1 | Basic Auth | `x-sap-login` + `x-sap-password` |
121
+ | 0 | None | No valid auth |
122
+
123
+ ---
124
+
125
+ ### 2.4 @mcp-abap-adt/auth-stores
126
+
127
+ | Attribute | Value |
128
+ |:---|:---|
129
+ | **Responsibility** | Persistent storage for service keys and session data |
130
+ | **Public interfaces** | `IServiceKeyStore`, `ISessionStore` |
131
+ | **Default implementations** | `AbapServiceKeyStore`, `XsuaaServiceKeyStore`, `AbapSessionStore`, `XsuaaSessionStore` |
132
+ | **Replaceable** | Yes -- consumers can provide any `IServiceKeyStore` / `ISessionStore` |
133
+ | **Runtime role** | Supplies credentials and persists tokens between sessions |
134
+ | **Dependencies** | `@mcp-abap-adt/interfaces`, `dotenv` |
135
+
136
+ Service key stores read `{destination}.json` files from a configurable directory. Session stores persist authorization and connection configurations per destination. ABAP and XSUAA variants differ in JSON structure parsing, not in interface contract.
137
+
138
+ ---
139
+
140
+ ### 2.5 @mcp-abap-adt/auth-broker
141
+
142
+ | Attribute | Value |
143
+ |:---|:---|
144
+ | **Responsibility** | Token orchestration -- coordinates stores and providers to produce valid tokens |
145
+ | **Public interface** | `AuthBroker` class, `ITokenRefresher` factory |
146
+ | **Replaceable** | Yes -- any object satisfying the same method signatures |
147
+ | **Runtime role** | Central authentication coordinator; creates `ITokenRefresher` for injection into connections |
148
+ | **Dependencies** | `@mcp-abap-adt/interfaces` |
149
+
150
+ **Token acquisition flow** (multi-step with fallback):
151
+
152
+ ```
153
+ 1. Check session store for cached token
154
+ └─ Valid? → return token
155
+ 2. Attempt token refresh via refresh_token
156
+ └─ Success? → persist to session store, return token
157
+ 3. Fall back to browser-based OAuth2 authorization_code flow
158
+ └─ Success? → persist to session store, return token
159
+ 4. Fail with typed error (BROWSER_AUTH_REQUIRED, REFRESH_ERROR, etc.)
160
+ ```
161
+
162
+ `AuthBroker` accepts three injected dependencies:
163
+
164
+ - `ISessionStore` (required) -- cached tokens and connection config
165
+ - `IServiceKeyStore` (optional) -- initial credentials from service key files
166
+ - `ITokenProvider` (required) -- handles actual token acquisition (browser OAuth, client credentials, etc.)
167
+
168
+ It also produces `ITokenRefresher` instances that are injected into `JwtAbapConnection` for transparent token renewal on 401/403 responses.
169
+
170
+ ---
171
+
172
+ ### 2.6 @mcp-abap-adt/auth-providers
173
+
174
+ | Attribute | Value |
175
+ |:---|:---|
176
+ | **Responsibility** | Concrete token acquisition strategies |
177
+ | **Public interface** | `ITokenProvider` (from interfaces package) |
178
+ | **Default implementations** | `AuthorizationCodeProvider`, `ClientCredentialsProvider`, `DeviceFlowProvider`, `OidcBrowserProvider`, `OidcDeviceFlowProvider`, `OidcPasswordProvider`, `OidcTokenExchangeProvider`, `Saml2BearerProvider`, `Saml2PureProvider` |
179
+ | **Replaceable** | Yes -- any `ITokenProvider` implementation |
180
+ | **Runtime role** | Injected into `AuthBroker` to perform specific OAuth2/OIDC/SAML flows |
181
+ | **Dependencies** | `@mcp-abap-adt/interfaces`, `axios`, `express`, `open` |
182
+
183
+ All providers extend `BaseTokenProvider` which manages token caching, expiration tracking, and the `getTokens()` lifecycle. Each provider implements a specific grant type:
184
+
185
+ | Provider | Grant Type | Use Case |
186
+ |:---|:---|:---|
187
+ | `AuthorizationCodeProvider` | `authorization_code` | Interactive browser-based BTP auth |
188
+ | `ClientCredentialsProvider` | `client_credentials` | Machine-to-machine, no user context |
189
+ | `DeviceFlowProvider` | `device_code` | Devices without browser |
190
+ | `OidcBrowserProvider` | OIDC + browser | Generic OIDC with browser |
191
+ | `OidcDeviceFlowProvider` | OIDC + device | Generic OIDC without browser |
192
+ | `OidcPasswordProvider` | `password` | Resource owner password (legacy) |
193
+ | `OidcTokenExchangeProvider` | `token_exchange` | Token exchange flows |
194
+ | `Saml2BearerProvider` | `saml2_bearer` | SAML2 bearer assertion |
195
+ | `Saml2PureProvider` | Pure SAML | Direct SAML authentication |
196
+
197
+ ---
198
+
199
+ ### 2.7 @mcp-abap-adt/connection
200
+
201
+ | Attribute | Value |
202
+ |:---|:---|
203
+ | **Responsibility** | HTTP transport layer to SAP ADT REST API |
204
+ | **Public interface** | `IAbapConnection` |
205
+ | **Default implementations** | `BaseAbapConnection` (Basic auth), `JwtAbapConnection` (JWT/BTP), `SamlAbapConnection` (SAML) |
206
+ | **Replaceable** | Yes -- any `IAbapConnection` implementation |
207
+ | **Runtime role** | Executes HTTP requests against SAP ADT endpoints |
208
+ | **Dependencies** | `@mcp-abap-adt/interfaces`, `axios` |
209
+
210
+ **Factory function:**
211
+
212
+ ```typescript
213
+ createAbapConnection(config: SapConfig, logger?: ILogger, sessionId?: string, tokenRefresher?: ITokenRefresher): IAbapConnection
214
+ ```
215
+
216
+ Automatically selects the correct implementation based on `config.authType` (`basic`, `jwt`, or `saml`).
217
+
218
+ **Key capabilities:**
219
+ - CSRF token management (automatic fetch, cache, refresh on error)
220
+ - Stateful/stateless session switching via `sap-contextid` headers
221
+ - Cookie management for session persistence
222
+ - Automatic token refresh on 401/403 via injected `ITokenRefresher`
223
+ - TLS configuration respecting `NODE_TLS_REJECT_UNAUTHORIZED`
224
+ - Retry logic for transient errors
225
+
226
+ ---
227
+
228
+ ### 2.8 @mcp-abap-adt/adt-clients
229
+
230
+ | Attribute | Value |
231
+ |:---|:---|
232
+ | **Responsibility** | Domain logic for ABAP object CRUD operations |
233
+ | **Public interface** | `IAdtObject<TConfig, TState>` per object type |
234
+ | **Default implementation** | `AdtClient` (factory), 22+ object-type handlers |
235
+ | **Replaceable** | Yes -- via interface |
236
+ | **Runtime role** | Called by MCP tool handlers to perform SAP operations |
237
+ | **Dependencies** | `@mcp-abap-adt/interfaces`, `@mcp-abap-adt/logger`, `fast-xml-parser` |
238
+
239
+ **AdtClient** is a factory that creates typed object handlers:
240
+
241
+ ```typescript
242
+ const client = new AdtClient(connection, logger);
243
+ const program = client.getProgram(); // → IAdtObject<IProgramConfig, IProgramState>
244
+ const cls = client.getClass(); // → IAdtObject<IClassConfig, IClassState>
245
+ const func = client.getFunctionModule(); // → IAdtObject<IFunctionModuleConfig, IFunctionModuleState>
246
+ ```
247
+
248
+ **Supported ABAP object types** (22+): Class, Program, Interface, Domain, DataElement, Structure, Table, TableType, View, FunctionGroup, FunctionModule, Package, ServiceDefinition, BehaviorDefinition, BehaviorImplementation, MetadataExtension, Enhancement, UnitTest, CdsUnitTest, Transport Request, LocalDefinitions, LocalTypes, LocalMacros, LocalTestClass.
249
+
250
+ **Operation chains** -- create and update operations are multi-step sequences:
251
+
252
+ ```
253
+ Create: validate → create → check → lock → update → unlock → check → activate (optional)
254
+ Update: lock → check → update → unlock → check → activate (optional)
255
+ Delete: check(deletion) → delete
256
+ Read: single GET request
257
+ ```
258
+
259
+ Each step accumulates results in `TState`, providing full audit trail of the operation.
260
+
261
+ **AdtUtils** provides cross-cutting utilities: repository search, where-used analysis, package hierarchy traversal, table content queries, inactive object lists, and batch operations.
262
+
263
+ ---
264
+
265
+ ### 2.9 mcp-abap-adt (Main MCP Server)
266
+
267
+ | Attribute | Value |
268
+ |:---|:---|
269
+ | **Responsibility** | MCP protocol adapter -- translates MCP tool calls into ADT client operations |
270
+ | **Runtime role** | Primary application entry point; composition root |
271
+ | **Transport modes** | `stdio`, `streamable-http`, `sse` |
272
+ | **Dependencies** | All packages above + `@modelcontextprotocol/sdk`, `zod` |
273
+
274
+ #### Composition Root
275
+
276
+ `src/server/launcher.ts` is the composition root where all dependencies are wired:
277
+
278
+ ```
279
+ launcher.ts main()
280
+ ├── ServerConfigManager.getConfig() // CLI args, YAML, env vars
281
+ ├── Create handler groups (by exposition) // ReadOnly, HighLevel, LowLevel, Search, System
282
+ ├── CompositeHandlersRegistry(groups) // Aggregate registry
283
+ ├── AuthBrokerFactory // Per-destination auth broker management
284
+ └── Transport server (Stdio|Http|Sse) // Start appropriate transport
285
+ ```
286
+
287
+ #### Handler Architecture
288
+
289
+ Handlers are organized into groups by access level:
290
+
291
+ | Group | Purpose | Typical Tool Count |
292
+ |:---|:---|:---|
293
+ | `ReadOnlyHandlersGroup` | Get operations (read source, metadata) | ~10 |
294
+ | `HighLevelHandlersGroup` | Full CRUD (Create, Update, Delete, Get) | ~90 |
295
+ | `LowLevelHandlersGroup` | Fine-grained (lock, unlock, activate, validate) | ~40 |
296
+ | `SearchHandlersGroup` | Repository search, where-used | ~5 |
297
+ | `SystemHandlersGroup` | System info, discovery | ~3 |
298
+
299
+ The `exposition` configuration controls which groups are active, enabling read-only deployments or full-access modes.
300
+
301
+ **Handler registration flow:**
302
+
303
+ ```
304
+ CompositeHandlersRegistry
305
+ └── for each IHandlerGroup:
306
+ └── BaseHandlerGroup.registerHandlers(server)
307
+ └── for each HandlerEntry:
308
+ ├── Convert JSON Schema → Zod
309
+ ├── Wrap handler with context injection
310
+ └── server.registerTool(name, schema, wrappedHandler)
311
+ ```
312
+
313
+ Each handler follows a uniform pattern:
314
+
315
+ ```typescript
316
+ // Tool definition (static metadata)
317
+ export const TOOL_DEFINITION = {
318
+ name: "GetProgram",
319
+ description: "Retrieve ABAP program source code",
320
+ inputSchema: { type: "object", properties: { program_name: { type: "string" } }, required: ["program_name"] }
321
+ } as const;
322
+
323
+ // Handler function (receives injected context)
324
+ export async function handleGetProgram(context: HandlerContext, args: GetProgramArgs) {
325
+ const client = new AdtClient(context.connection, context.logger);
326
+ const result = await client.getProgram().read({ programName: args.program_name }, args.version || 'active');
327
+ return return_response(result);
328
+ }
329
+ ```
330
+
331
+ `HandlerContext` contains the `IAbapConnection` and optional `ILogger` -- injected per-request by `BaseMcpServer`.
332
+
333
+ #### Transport Servers
334
+
335
+ | Transport | Class | Connection Model | Session Management |
336
+ |:---|:---|:---|:---|
337
+ | stdio | `StdioServer` | Cached (one per server lifetime) | Single persistent session |
338
+ | HTTP | `StreamableHttpServer` | Per-request (new server instance) | Stateless |
339
+ | SSE | `SseServer` | Per-connection | Map by session ID |
340
+
341
+ All transports extend `BaseMcpServer` which handles handler registration, connection context management, and per-request context injection.
342
+
343
+ ---
344
+
345
+ ### 2.10 @mcp-abap-adt/proxy (Auxiliary Utility)
346
+
347
+ | Attribute | Value |
348
+ |:---|:---|
349
+ | **Responsibility** | Authorization proxy between MCP clients and remote MCP servers on BTP |
350
+ | **Architectural relationship** | Fully independent -- can proxy to ANY MCP server, not just mcp-abap-adt |
351
+ | **Runtime role** | Intercepts requests, obtains JWT via XSUAA, forwards authenticated requests |
352
+ | **Transport modes** | `stdio`, `streamable-http`, `sse` |
353
+ | **Dependencies** | `@mcp-abap-adt/auth-broker`, `@mcp-abap-adt/auth-providers`, `@mcp-abap-adt/auth-stores`, `@mcp-abap-adt/interfaces`, `@modelcontextprotocol/sdk`, `axios` |
354
+
355
+ The proxy is **not** part of the main server's runtime. It is a standalone utility for scenarios where MCP clients (Cline, Copilot, Cursor) cannot perform BTP authentication directly.
356
+
357
+ **Key capabilities:**
358
+ - JWT token management with 30-minute cache TTL
359
+ - Multi-destination support (per-destination auth brokers)
360
+ - Circuit breaker pattern for resilience
361
+ - Retry with exponential backoff
362
+ - Service key-based MCP server URL discovery
363
+ - Request/response logging with sensitive data redaction
364
+ - Eager authentication (browser opens on startup for stdio mode)
365
+
366
+ ---
367
+
368
+ ### 2.11 @mcp-abap-adt/configurator (Auxiliary Utility)
369
+
370
+ | Attribute | Value |
371
+ |:---|:---|
372
+ | **Responsibility** | Automates MCP server registration in client configuration files |
373
+ | **Architectural relationship** | Fully independent -- no runtime dependency on any other package |
374
+ | **Supported clients** | Cline, Claude, Codex, Cursor, Copilot, Goose, Windsurf, OpenCode, Antigravity, Qwen, Crush (11 total) |
375
+ | **Operations** | add, rm, ls, show, enable, disable, where, update, tui |
376
+
377
+ A pure CLI/TUI tool that handles platform-specific and client-specific configuration file formats (JSON, YAML, TOML) across global and project scopes.
378
+
379
+ ---
380
+
381
+ ## 3. Submodule Clarification
382
+
383
+ Each package is an **independent git repository** with its own version, build pipeline, test suite, and npm publication. For development convenience, packages can be aggregated using **git submodules**:
384
+
385
+ ```
386
+ mcp-abap-adt/ ← Own git repo, published to npm
387
+ mcp-abap-adt-interfaces/ ← Own git repo, published to npm
388
+ mcp-abap-adt-clients/ ← Own git repo, published to npm
389
+ mcp-abap-connection/ ← Own git repo, published to npm
390
+ ... ← Each package is independent
391
+ ```
392
+
393
+ **Critical distinction:**
394
+
395
+ - **Submodules are purely administrative** -- they enable synchronized development and convenient cross-package navigation, but are not required
396
+ - **Architectural isolation remains intact** -- each package has its own `package.json`, version, build pipeline, test suite, and npm publication
397
+ - **Submodule grouping does not equal monolith** -- consuming packages individually from npm changes nothing architecturally
398
+ - **No package references another package's source code** -- all inter-package dependencies go through npm-published interfaces
399
+
400
+ ---
401
+
402
+ ## 4. Runtime Interaction Model
403
+
404
+ ### 4.1 High-Level Component Interaction
405
+
406
+ ```mermaid
407
+ graph TD
408
+ Client["MCP Client<br/>(Claude, Cline, Copilot, Cursor)"]
409
+ Proxy["@mcp-abap-adt/proxy<br/>(optional auth proxy)"]
410
+ Server["mcp-abap-adt<br/>(MCP Server)"]
411
+ Registry["CompositeHandlersRegistry"]
412
+ Handlers["Handler Groups<br/>(ReadOnly, HighLevel, LowLevel, Search, System)"]
413
+ AdtClients["@mcp-abap-adt/adt-clients<br/>(AdtClient factory)"]
414
+ Connection["@mcp-abap-adt/connection<br/>(IAbapConnection)"]
415
+ AuthBroker["@mcp-abap-adt/auth-broker<br/>(AuthBroker)"]
416
+ Providers["@mcp-abap-adt/auth-providers<br/>(ITokenProvider)"]
417
+ Stores["@mcp-abap-adt/auth-stores<br/>(IServiceKeyStore, ISessionStore)"]
418
+ SAP["SAP ABAP System<br/>(ADT REST API)"]
419
+
420
+ Client -->|"MCP protocol<br/>(stdio/http/sse)"| Proxy
421
+ Client -->|"MCP protocol<br/>(stdio/http/sse)"| Server
422
+ Proxy -->|"Authenticated HTTP"| Server
423
+ Server --> Registry
424
+ Registry --> Handlers
425
+ Handlers -->|"HandlerContext"| AdtClients
426
+ AdtClients -->|"IAbapConnection"| Connection
427
+ Connection -->|"HTTP/HTTPS"| SAP
428
+ Connection -->|"ITokenRefresher"| AuthBroker
429
+ AuthBroker --> Providers
430
+ AuthBroker --> Stores
431
+ Providers -->|"OAuth2/OIDC/SAML"| SAP
432
+ ```
433
+
434
+ ### 4.2 Request Processing Flow (HTTP Transport)
435
+
436
+ ```
437
+ 1. HTTP POST /mcp/stream/http
438
+ └── StreamableHttpServer.createRequestHandler()
439
+
440
+ 2. Per-request server creation
441
+ └── new BaseMcpServer() instance per request
442
+
443
+ 3. Connection context resolution
444
+ ├── From x-mcp-destination header → AuthBrokerFactory.getBroker(destination)
445
+ ├── From x-sap-url + auth headers → Direct connection params
446
+ └── From default destination (startup config)
447
+
448
+ 4. Handler invocation
449
+ ├── BaseMcpServer resolves tool name → handler function
450
+ ├── Creates HandlerContext { connection: IAbapConnection, logger: ILogger }
451
+ └── Calls handler(context, args)
452
+
453
+ 5. ADT operation execution
454
+ ├── Handler creates AdtClient(connection, logger)
455
+ ├── Calls typed operation (e.g., client.getProgram().read(...))
456
+ ├── AdtClient delegates to IAbapConnection.makeAdtRequest()
457
+ └── Connection handles auth, CSRF, retries, session
458
+
459
+ 6. Response
460
+ └── Handler returns MCP-formatted response (text content)
461
+ ```
462
+
463
+ ### 4.3 Inversion of Control Boundaries
464
+
465
+ The system has three distinct IoC boundaries:
466
+
467
+ | Boundary | What is Inverted | Composition Point |
468
+ |:---|:---|:---|
469
+ | **Auth** | Token acquisition strategy | `AuthBroker` constructor receives `ITokenProvider`, `ISessionStore`, `IServiceKeyStore` |
470
+ | **Transport** | HTTP communication with SAP | `AdtClient` constructor receives `IAbapConnection` |
471
+ | **Handlers** | Tool behavior per transport/mode | `CompositeHandlersRegistry` receives `IHandlerGroup[]` |
472
+
473
+ ### 4.4 Composition Root Location
474
+
475
+ `mcp-abap-adt/src/server/launcher.ts` is the single composition root for the main server. It:
476
+
477
+ 1. Reads configuration (CLI, YAML, env)
478
+ 2. Instantiates concrete store implementations (`AbapServiceKeyStore`, `AbapSessionStore`)
479
+ 3. Creates token providers (`AuthorizationCodeProvider`)
480
+ 4. Assembles `AuthBroker` instances via `AuthBrokerFactory`
481
+ 5. Creates handler groups with `HandlerContext`
482
+ 6. Assembles `CompositeHandlersRegistry`
483
+ 7. Starts the appropriate transport server
484
+
485
+ No other file in the system creates concrete cross-package dependencies.
486
+
487
+ ---
488
+
489
+ ## 5. Extensibility Model
490
+
491
+ ### 5.1 Replacing Default Implementations
492
+
493
+ Any interface-backed component can be replaced. The general pattern:
494
+
495
+ ```typescript
496
+ // 1. Implement the interface
497
+ class CustomSessionStore implements ISessionStore {
498
+ async loadSession(destination: string): Promise<IConfig | null> { /* custom logic */ }
499
+ async saveSession(destination: string, config: IConfig): Promise<void> { /* custom logic */ }
500
+ async getAuthorizationConfig(destination: string): Promise<IAuthorizationConfig | null> { /* ... */ }
501
+ async getConnectionConfig(destination: string): Promise<IConnectionConfig | null> { /* ... */ }
502
+ async setAuthorizationConfig(destination: string, config: IAuthorizationConfig): Promise<void> { /* ... */ }
503
+ async setConnectionConfig(destination: string, config: IConnectionConfig): Promise<void> { /* ... */ }
504
+ }
505
+
506
+ // 2. Inject at composition root
507
+ const broker = new AuthBroker({
508
+ sessionStore: new CustomSessionStore(),
509
+ tokenProvider: new AuthorizationCodeProvider(providerConfig),
510
+ });
511
+ ```
512
+
513
+ ### 5.2 Custom Authentication Logic
514
+
515
+ To inject a custom authentication flow:
516
+
517
+ 1. **Implement `ITokenProvider`** with a `getTokens()` method that returns `ITokenResult`
518
+ 2. **Pass it to `AuthBroker`** in the composition root
519
+ 3. The rest of the system remains unchanged -- `AuthBroker` will use the custom provider for token acquisition
520
+
521
+ ```typescript
522
+ class CustomTokenProvider implements ITokenProvider {
523
+ async getTokens(): Promise<ITokenResult> {
524
+ // Custom token acquisition (e.g., corporate SSO, hardware token, vault)
525
+ return { authorizationToken: '...', authType: 'authorization_code' };
526
+ }
527
+ }
528
+ ```
529
+
530
+ ### 5.3 Custom Configuration Handling
531
+
532
+ `ServerConfigManager` supports:
533
+ - CLI arguments (`--transport`, `--host`, `--port`, `--conf`, `--mcp`, `--env`)
534
+ - YAML configuration files (via `--conf <path>`)
535
+ - Environment variables (`MCP_TRANSPORT`, `MCP_HTTP_HOST`, `MCP_HTTP_PORT`)
536
+
537
+ For deeper customization, consumers can bypass `ServerConfigManager` and construct `IServerConfig` directly.
538
+
539
+ ### 5.4 Extending MCP Tool Behavior
540
+
541
+ To add new tools:
542
+
543
+ 1. **Create a handler** following the existing pattern (TOOL_DEFINITION + handler function)
544
+ 2. **Create a handler group** implementing `IHandlerGroup`
545
+ 3. **Register it** via `CompositeHandlersRegistry.addHandlerGroup()`
546
+
547
+ ```typescript
548
+ class CustomHandlerGroup extends BaseHandlerGroup {
549
+ protected groupName = 'CustomHandlers';
550
+
551
+ getHandlers(): HandlerEntry[] {
552
+ return [
553
+ {
554
+ toolDefinition: { name: 'CustomTool', description: '...', inputSchema: { ... } },
555
+ handler: (context, args) => handleCustomTool(context, args),
556
+ },
557
+ ];
558
+ }
559
+ }
560
+
561
+ // At composition root
562
+ registry.addHandlerGroup(new CustomHandlerGroup(baseContext));
563
+ ```
564
+
565
+ ### 5.5 Architectural Guarantees
566
+
567
+ - **Interface stability** -- `@mcp-abap-adt/interfaces` follows semver; breaking changes require major version bumps
568
+ - **No hidden state** -- components do not share global mutable state (except the explicit `AuthBrokerRegistry` global for cross-package token refresh)
569
+ - **Typed errors** -- all error conditions use typed error code constants, enabling programmatic error handling
570
+ - **Operation auditability** -- `IAdtObjectState` accumulates every operation result, providing full trace of create/update/delete chains
571
+
572
+ ---
573
+
574
+ ## 6. Developer and Consumer Perspective
575
+
576
+ ### 6.1 For New ABAP Developers
577
+
578
+ **Recommended entry path:**
579
+
580
+ 1. Start with `@mcp-abap-adt/interfaces` -- read `IAdtObject<TConfig, TState>` to understand the CRUD contract
581
+ 2. Examine one object type in `@mcp-abap-adt/adt-clients` (e.g., `src/core/program/`) to see the operation chain pattern
582
+ 3. Look at the corresponding handler in `mcp-abap-adt/src/handlers/program/` to understand how MCP tool calls map to ADT operations
583
+ 4. Study `@mcp-abap-adt/connection` to understand how HTTP requests reach SAP
584
+
585
+ **Key concept:** Every ABAP object type (Class, Program, Table, etc.) follows the identical pattern: `TConfig` input, `IAdtObject` interface, `TState` accumulation. Learn one, understand all.
586
+
587
+ ### 6.2 Typical Usage Scenarios
588
+
589
+ | Scenario | Components Used | Transport |
590
+ |:---|:---|:---|
591
+ | Local development with Claude Code | Main server | stdio |
592
+ | Team deployment on BTP | Main server + proxy | HTTP |
593
+ | Read-only monitoring | Main server (exposition=readonly) | HTTP/SSE |
594
+ | Custom IDE integration | Main server (as npm dependency) | Embedded via `EmbeddableMcpServer` |
595
+ | Multi-system landscape | Main server + proxy (multi-destination) | HTTP |
596
+
597
+ ### 6.3 SAP Consultant Integration
598
+
599
+ Consultants working with customer systems typically:
600
+
601
+ 1. Use `@mcp-abap-adt/configurator` to set up their MCP client
602
+ 2. Configure service keys for BTP systems or basic auth for on-premise
603
+ 3. Deploy the proxy for team-shared access with centralized auth
604
+ 4. Control tool exposure via `exposition` config (readonly for auditing, full for development)
605
+
606
+ ### 6.4 Support Usage Patterns
607
+
608
+ For troubleshooting:
609
+
610
+ - Enable debug logging: `AUTH_LOG_LEVEL=debug` or `DEBUG_AUTH_LOG=true`
611
+ - Token flow diagnostics: `AuthBroker` logs every step of the acquisition flow
612
+ - Connection diagnostics: `AbstractAbapConnection` logs CSRF operations, retries, and session state
613
+ - Handler diagnostics: Each handler logs operation parameters and error details
614
+ - All sensitive data (tokens, passwords, secrets) is redacted in log output
615
+
616
+ ---
617
+
618
+ ## 7. Architecture Validation
619
+
620
+ ### 7.1 Architecture Style Classification
621
+
622
+ **Primary style:** Component-based architecture with dependency injection
623
+
624
+ **Supporting patterns:**
625
+ - Factory pattern (`AdtClient`, `createAbapConnection`, `AuthBrokerFactory`)
626
+ - Strategy pattern (`ITokenProvider` implementations selected at composition time)
627
+ - Composite pattern (`CompositeHandlersRegistry` aggregates `IHandlerGroup[]`)
628
+ - Chain of Responsibility (operation chains in `IAdtObject` implementations)
629
+ - Template Method (`BaseTokenProvider`, `AbstractAbapConnection`, `BaseHandlerGroup`)
630
+
631
+ ### 7.2 Coupling Assessment
632
+
633
+ | Coupling Type | Level | Evidence |
634
+ |:---|:---|:---|
635
+ | Interface coupling | Low | All cross-package communication through interfaces |
636
+ | Data coupling | Low | Well-defined DTOs (`IConfig`, `ITokenResult`, `IAdtResponse`) |
637
+ | Runtime coupling | Medium | `AuthBrokerRegistry` global for cross-package token refresh |
638
+ | Temporal coupling | Low | No implicit ordering between components (explicit operation chains only) |
639
+ | Build coupling | None | Each package builds independently |
640
+
641
+ ### 7.3 Replaceability Assessment
642
+
643
+ | Component | Replaceability | Effort |
644
+ |:---|:---|:---|
645
+ | Logger | Full | Implement 4-method `ILogger` interface |
646
+ | Session Store | Full | Implement `ISessionStore` (6 methods) |
647
+ | Service Key Store | Full | Implement `IServiceKeyStore` (3 methods) |
648
+ | Token Provider | Full | Implement `ITokenProvider` (1-2 methods) |
649
+ | Connection | Full | Implement `IAbapConnection` (4 methods) |
650
+ | Handler Groups | Full | Implement `IHandlerGroup` (3 methods) |
651
+ | Auth Broker | Moderate | Replace `AuthBroker` class (non-interface, but clear method contract) |
652
+ | Transport Server | Moderate | Extend `BaseMcpServer` and implement transport-specific logic |
653
+
654
+ ### 7.4 Strengths
655
+
656
+ - **Strict interface isolation** prevents accidental coupling between packages
657
+ - **Multi-auth strategy** supports Basic, JWT, SAML, OIDC, device flow -- covering on-premise through BTP cloud
658
+ - **Operation chain model** provides atomic, auditable CRUD sequences with automatic lock/unlock
659
+ - **Exposition control** enables deployment profiles (read-only, full CRUD, low-level)
660
+ - **Transport flexibility** (stdio, HTTP, SSE) adapts to different client architectures
661
+ - **22+ ABAP object types** with uniform interface -- broad coverage with consistent API
662
+
663
+ ### 7.5 Risks
664
+
665
+ | Risk | Mitigation |
666
+ |:---|:---|
667
+ | `AuthBrokerRegistry` global state could cause conflicts in multi-tenant scenarios | Scoped to destination key; documented as known limitation |
668
+ | Large handler count (~150 tools) may overwhelm AI model context | `exposition` config limits visible tools per deployment |
669
+ | XML parsing of ADT responses is fragile across SAP versions | `fast-xml-parser` with per-object-type parsers; integration tests validate against real systems |
670
+ | Service key files stored on filesystem | Configurable directory; `unsafe` flag controls file vs. in-memory storage |
671
+
672
+ ### 7.6 Recommendations
673
+
674
+ 1. **For new contributors:** Follow the existing handler pattern exactly -- tool definition + handler function + handler group registration. Do not introduce new cross-package dependencies.
675
+ 2. **For custom deployments:** Start with the `exposition` config and `EmbeddableMcpServer` before building custom infrastructure.
676
+ 3. **For enterprise adoption:** Use the proxy for centralized BTP authentication and the configurator for standardized client setup across teams.
677
+ 4. **For extending object type support:** Add a new module under `@mcp-abap-adt/adt-clients/src/core/{type}/` following the established pattern (types, CRUD functions, `IAdtObject` implementation).
678
+
679
+ ---
680
+
681
+ ## Appendix: Dependency Hierarchy
682
+
683
+ ```
684
+ @mcp-abap-adt/interfaces (base -- no dependencies)
685
+
686
+ ├── @mcp-abap-adt/logger
687
+
688
+ ├── @mcp-abap-adt/header-validator
689
+
690
+ ├── @mcp-abap-adt/auth-stores
691
+
692
+ ├── @mcp-abap-adt/connection
693
+ │ └── @mcp-abap-adt/adt-clients
694
+
695
+ ├── @mcp-abap-adt/auth-providers
696
+
697
+ ├── @mcp-abap-adt/auth-broker
698
+
699
+ └── mcp-abap-adt (main server -- composition root, consumes all)
700
+ ├── Depends on all packages above
701
+ └── @modelcontextprotocol/sdk
702
+
703
+ @mcp-abap-adt/proxy (independent auxiliary -- uses auth-broker, auth-stores, auth-providers)
704
+
705
+ @mcp-abap-adt/configurator (independent auxiliary -- no runtime deps on other packages)
706
+ ```