@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.
- package/CHANGELOG.md +31 -0
- package/README.md +3 -2
- package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.d.ts +79 -0
- package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.d.ts.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.js +75 -0
- package/dist/handlers/system/readonly/handleRuntimeCreateProfilerTraceParameters.js.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpById.d.ts +27 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpById.d.ts.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpById.js +48 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpById.js.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.d.ts +27 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.d.ts.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.js +47 -0
- package/dist/handlers/system/readonly/handleRuntimeGetDumpByUri.js.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.d.ts +53 -0
- package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.d.ts.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.js +83 -0
- package/dist/handlers/system/readonly/handleRuntimeGetProfilerTraceData.js.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeListDumps.d.ts +48 -0
- package/dist/handlers/system/readonly/handleRuntimeListDumps.d.ts.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeListDumps.js +75 -0
- package/dist/handlers/system/readonly/handleRuntimeListDumps.js.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.d.ts +18 -0
- package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.d.ts.map +1 -0
- package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.js +39 -0
- package/dist/handlers/system/readonly/handleRuntimeListProfilerTraceFiles.js.map +1 -0
- package/dist/handlers/system/readonly/runtimePayloadParser.d.ts +6 -0
- package/dist/handlers/system/readonly/runtimePayloadParser.d.ts.map +1 -0
- package/dist/handlers/system/readonly/runtimePayloadParser.js +28 -0
- package/dist/handlers/system/readonly/runtimePayloadParser.js.map +1 -0
- package/dist/lib/config/ArgumentsParser.js +2 -2
- package/dist/lib/config/ArgumentsParser.js.map +1 -1
- package/dist/lib/config/ServerConfigManager.d.ts.map +1 -1
- package/dist/lib/config/ServerConfigManager.js +4 -2
- package/dist/lib/config/ServerConfigManager.js.map +1 -1
- package/dist/lib/config/yamlConfig.d.ts +2 -1
- package/dist/lib/config/yamlConfig.d.ts.map +1 -1
- package/dist/lib/config/yamlConfig.js +18 -7
- package/dist/lib/config/yamlConfig.js.map +1 -1
- package/dist/lib/handlers/groups/SystemHandlersGroup.d.ts.map +1 -1
- package/dist/lib/handlers/groups/SystemHandlersGroup.js +45 -0
- package/dist/lib/handlers/groups/SystemHandlersGroup.js.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +5 -4
- package/dist/lib/utils.js.map +1 -1
- package/dist/server/SseServer.d.ts.map +1 -1
- package/dist/server/SseServer.js +7 -3
- package/dist/server/SseServer.js.map +1 -1
- package/dist/server/StreamableHttpServer.d.ts.map +1 -1
- package/dist/server/StreamableHttpServer.js +10 -5
- package/dist/server/StreamableHttpServer.js.map +1 -1
- package/dist/server/launcher.js +1 -1
- package/dist/server/launcher.js.map +1 -1
- package/docs/architecture/ARCHITECTURE.md +706 -0
- package/docs/architecture/README.md +1 -0
- package/docs/configuration/YAML_CONFIG.md +25 -22
- package/docs/user-guide/AVAILABLE_TOOLS.md +73 -3
- package/docs/user-guide/AVAILABLE_TOOLS_HIGH.md +1 -1
- package/docs/user-guide/AVAILABLE_TOOLS_LOW.md +1 -1
- package/docs/user-guide/AVAILABLE_TOOLS_READONLY.md +72 -2
- package/docs/user-guide/CLI_OPTIONS.md +6 -5
- 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
|
+
```
|