@mcp-abap-adt/calm-server 0.1.0 → 0.2.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 (174) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +48 -25
  3. package/dist/bin/stdio.js +9 -6
  4. package/dist/bin/stdio.js.map +1 -1
  5. package/dist/server/config.d.ts.map +1 -1
  6. package/dist/server/config.js +7 -1
  7. package/dist/server/config.js.map +1 -1
  8. package/dist/server/runStdio.d.ts +2 -4
  9. package/dist/server/runStdio.d.ts.map +1 -1
  10. package/dist/server/runStdio.js +15 -5
  11. package/dist/server/runStdio.js.map +1 -1
  12. package/dist/server/stderrLogger.d.ts +24 -0
  13. package/dist/server/stderrLogger.d.ts.map +1 -0
  14. package/dist/server/stderrLogger.js +44 -0
  15. package/dist/server/stderrLogger.js.map +1 -0
  16. package/dist/tools/documents/createDocument.d.ts +5 -0
  17. package/dist/tools/documents/createDocument.d.ts.map +1 -0
  18. package/dist/tools/documents/createDocument.js +48 -0
  19. package/dist/tools/documents/createDocument.js.map +1 -0
  20. package/dist/tools/documents/deleteDocument.d.ts +10 -0
  21. package/dist/tools/documents/deleteDocument.d.ts.map +1 -0
  22. package/dist/tools/documents/deleteDocument.js +35 -0
  23. package/dist/tools/documents/deleteDocument.js.map +1 -0
  24. package/dist/tools/documents/index.d.ts +10 -0
  25. package/dist/tools/documents/index.d.ts.map +1 -1
  26. package/dist/tools/documents/index.js +21 -1
  27. package/dist/tools/documents/index.js.map +1 -1
  28. package/dist/tools/documents/listDocumentStatuses.d.ts +7 -0
  29. package/dist/tools/documents/listDocumentStatuses.d.ts.map +1 -0
  30. package/dist/tools/documents/listDocumentStatuses.js +23 -0
  31. package/dist/tools/documents/listDocumentStatuses.js.map +1 -0
  32. package/dist/tools/documents/listDocumentTypes.d.ts +7 -0
  33. package/dist/tools/documents/listDocumentTypes.d.ts.map +1 -0
  34. package/dist/tools/documents/listDocumentTypes.js +23 -0
  35. package/dist/tools/documents/listDocumentTypes.js.map +1 -0
  36. package/dist/tools/documents/updateDocument.d.ts +7 -0
  37. package/dist/tools/documents/updateDocument.d.ts.map +1 -0
  38. package/dist/tools/documents/updateDocument.js +43 -0
  39. package/dist/tools/documents/updateDocument.js.map +1 -0
  40. package/dist/tools/features/createExternalReference.d.ts +5 -0
  41. package/dist/tools/features/createExternalReference.d.ts.map +1 -0
  42. package/dist/tools/features/createExternalReference.js +49 -0
  43. package/dist/tools/features/createExternalReference.js.map +1 -0
  44. package/dist/tools/features/deleteExternalReference.d.ts +12 -0
  45. package/dist/tools/features/deleteExternalReference.d.ts.map +1 -0
  46. package/dist/tools/features/deleteExternalReference.js +44 -0
  47. package/dist/tools/features/deleteExternalReference.js.map +1 -0
  48. package/dist/tools/features/index.d.ts +6 -0
  49. package/dist/tools/features/index.d.ts.map +1 -1
  50. package/dist/tools/features/index.js +13 -1
  51. package/dist/tools/features/index.js.map +1 -1
  52. package/dist/tools/features/listExternalReferences.d.ts +11 -0
  53. package/dist/tools/features/listExternalReferences.d.ts.map +1 -0
  54. package/dist/tools/features/listExternalReferences.js +47 -0
  55. package/dist/tools/features/listExternalReferences.js.map +1 -0
  56. package/dist/tools/hierarchy/createHierarchyNode.d.ts +5 -0
  57. package/dist/tools/hierarchy/createHierarchyNode.d.ts.map +1 -0
  58. package/dist/tools/hierarchy/createHierarchyNode.js +46 -0
  59. package/dist/tools/hierarchy/createHierarchyNode.js.map +1 -0
  60. package/dist/tools/hierarchy/deleteHierarchyNode.d.ts +10 -0
  61. package/dist/tools/hierarchy/deleteHierarchyNode.d.ts.map +1 -0
  62. package/dist/tools/hierarchy/deleteHierarchyNode.js +35 -0
  63. package/dist/tools/hierarchy/deleteHierarchyNode.js.map +1 -0
  64. package/dist/tools/hierarchy/index.d.ts +6 -0
  65. package/dist/tools/hierarchy/index.d.ts.map +1 -1
  66. package/dist/tools/hierarchy/index.js +13 -1
  67. package/dist/tools/hierarchy/index.js.map +1 -1
  68. package/dist/tools/hierarchy/listHierarchy.d.ts.map +1 -1
  69. package/dist/tools/hierarchy/listHierarchy.js +4 -2
  70. package/dist/tools/hierarchy/listHierarchy.js.map +1 -1
  71. package/dist/tools/hierarchy/updateHierarchyNode.d.ts +7 -0
  72. package/dist/tools/hierarchy/updateHierarchyNode.d.ts.map +1 -0
  73. package/dist/tools/hierarchy/updateHierarchyNode.js +38 -0
  74. package/dist/tools/hierarchy/updateHierarchyNode.js.map +1 -0
  75. package/dist/tools/logs/index.d.ts +2 -0
  76. package/dist/tools/logs/index.d.ts.map +1 -1
  77. package/dist/tools/logs/index.js +8 -2
  78. package/dist/tools/logs/index.js.map +1 -1
  79. package/dist/tools/logs/postLogs.d.ts +10 -0
  80. package/dist/tools/logs/postLogs.d.ts.map +1 -0
  81. package/dist/tools/logs/postLogs.js +58 -0
  82. package/dist/tools/logs/postLogs.js.map +1 -0
  83. package/dist/tools/projects/createProject.d.ts +5 -0
  84. package/dist/tools/projects/createProject.d.ts.map +1 -0
  85. package/dist/tools/projects/createProject.js +42 -0
  86. package/dist/tools/projects/createProject.js.map +1 -0
  87. package/dist/tools/projects/getProgram.d.ts +7 -0
  88. package/dist/tools/projects/getProgram.d.ts.map +1 -0
  89. package/dist/tools/projects/getProgram.js +32 -0
  90. package/dist/tools/projects/getProgram.js.map +1 -0
  91. package/dist/tools/projects/index.d.ts +10 -0
  92. package/dist/tools/projects/index.d.ts.map +1 -1
  93. package/dist/tools/projects/index.js +21 -1
  94. package/dist/tools/projects/index.js.map +1 -1
  95. package/dist/tools/projects/listPrograms.d.ts +10 -0
  96. package/dist/tools/projects/listPrograms.d.ts.map +1 -0
  97. package/dist/tools/projects/listPrograms.js +36 -0
  98. package/dist/tools/projects/listPrograms.js.map +1 -0
  99. package/dist/tools/projects/listTeamMembers.d.ts +11 -0
  100. package/dist/tools/projects/listTeamMembers.d.ts.map +1 -0
  101. package/dist/tools/projects/listTeamMembers.js +49 -0
  102. package/dist/tools/projects/listTeamMembers.js.map +1 -0
  103. package/dist/tools/projects/listTimeboxes.d.ts +11 -0
  104. package/dist/tools/projects/listTimeboxes.d.ts.map +1 -0
  105. package/dist/tools/projects/listTimeboxes.js +49 -0
  106. package/dist/tools/projects/listTimeboxes.js.map +1 -0
  107. package/dist/tools/tasks/createTask.d.ts +5 -0
  108. package/dist/tools/tasks/createTask.d.ts.map +1 -0
  109. package/dist/tools/tasks/createTask.js +58 -0
  110. package/dist/tools/tasks/createTask.js.map +1 -0
  111. package/dist/tools/tasks/createTaskComment.d.ts +7 -0
  112. package/dist/tools/tasks/createTaskComment.d.ts.map +1 -0
  113. package/dist/tools/tasks/createTaskComment.js +36 -0
  114. package/dist/tools/tasks/createTaskComment.js.map +1 -0
  115. package/dist/tools/tasks/deleteTask.d.ts +10 -0
  116. package/dist/tools/tasks/deleteTask.d.ts.map +1 -0
  117. package/dist/tools/tasks/deleteTask.js +35 -0
  118. package/dist/tools/tasks/deleteTask.js.map +1 -0
  119. package/dist/tools/tasks/index.d.ts +14 -0
  120. package/dist/tools/tasks/index.d.ts.map +1 -1
  121. package/dist/tools/tasks/index.js +29 -1
  122. package/dist/tools/tasks/index.js.map +1 -1
  123. package/dist/tools/tasks/listDeliverables.d.ts +11 -0
  124. package/dist/tools/tasks/listDeliverables.d.ts.map +1 -0
  125. package/dist/tools/tasks/listDeliverables.js +42 -0
  126. package/dist/tools/tasks/listDeliverables.js.map +1 -0
  127. package/dist/tools/tasks/listTaskReferences.d.ts +11 -0
  128. package/dist/tools/tasks/listTaskReferences.d.ts.map +1 -0
  129. package/dist/tools/tasks/listTaskReferences.js +46 -0
  130. package/dist/tools/tasks/listTaskReferences.js.map +1 -0
  131. package/dist/tools/tasks/listWorkstreams.d.ts +11 -0
  132. package/dist/tools/tasks/listWorkstreams.d.ts.map +1 -0
  133. package/dist/tools/tasks/listWorkstreams.js +42 -0
  134. package/dist/tools/tasks/listWorkstreams.js.map +1 -0
  135. package/dist/tools/tasks/updateTask.d.ts +7 -0
  136. package/dist/tools/tasks/updateTask.d.ts.map +1 -0
  137. package/dist/tools/tasks/updateTask.js +44 -0
  138. package/dist/tools/tasks/updateTask.js.map +1 -0
  139. package/dist/tools/testCases/createTestAction.d.ts +5 -0
  140. package/dist/tools/testCases/createTestAction.d.ts.map +1 -0
  141. package/dist/tools/testCases/createTestAction.js +54 -0
  142. package/dist/tools/testCases/createTestAction.js.map +1 -0
  143. package/dist/tools/testCases/createTestActivity.d.ts +5 -0
  144. package/dist/tools/testCases/createTestActivity.d.ts.map +1 -0
  145. package/dist/tools/testCases/createTestActivity.js +46 -0
  146. package/dist/tools/testCases/createTestActivity.js.map +1 -0
  147. package/dist/tools/testCases/createTestCase.d.ts +5 -0
  148. package/dist/tools/testCases/createTestCase.d.ts.map +1 -0
  149. package/dist/tools/testCases/createTestCase.js +42 -0
  150. package/dist/tools/testCases/createTestCase.js.map +1 -0
  151. package/dist/tools/testCases/deleteTestCase.d.ts +10 -0
  152. package/dist/tools/testCases/deleteTestCase.d.ts.map +1 -0
  153. package/dist/tools/testCases/deleteTestCase.js +35 -0
  154. package/dist/tools/testCases/deleteTestCase.js.map +1 -0
  155. package/dist/tools/testCases/index.d.ts +14 -0
  156. package/dist/tools/testCases/index.d.ts.map +1 -1
  157. package/dist/tools/testCases/index.js +29 -1
  158. package/dist/tools/testCases/index.js.map +1 -1
  159. package/dist/tools/testCases/listTestActions.d.ts +11 -0
  160. package/dist/tools/testCases/listTestActions.d.ts.map +1 -0
  161. package/dist/tools/testCases/listTestActions.js +45 -0
  162. package/dist/tools/testCases/listTestActions.js.map +1 -0
  163. package/dist/tools/testCases/listTestActivities.d.ts +11 -0
  164. package/dist/tools/testCases/listTestActivities.d.ts.map +1 -0
  165. package/dist/tools/testCases/listTestActivities.js +45 -0
  166. package/dist/tools/testCases/listTestActivities.js.map +1 -0
  167. package/dist/tools/testCases/listTestCases.d.ts.map +1 -1
  168. package/dist/tools/testCases/listTestCases.js +5 -7
  169. package/dist/tools/testCases/listTestCases.js.map +1 -1
  170. package/dist/tools/testCases/updateTestCase.d.ts +7 -0
  171. package/dist/tools/testCases/updateTestCase.d.ts.map +1 -0
  172. package/dist/tools/testCases/updateTestCase.js +38 -0
  173. package/dist/tools/testCases/updateTestCase.js.map +1 -0
  174. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 — 2026-05-13
4
+
5
+ Parity with the consetto-Rust port plus a wider bonus surface, live
6
+ integration coverage, and a logger that is safe to use under MCP
7
+ stdio. **54 tools** (was 23), **232 tests** (was 103), full build
8
+ green.
9
+
10
+ ### Added
11
+
12
+ - **Tasks CRUD (M7)** — `create`, `update`, `delete`, `create_comment`.
13
+ - **TestCases CRUD (M8)** — `create`, `update`, `delete`, plus nested
14
+ `create_activity` / `create_action`.
15
+ - **Documents CRUD (M9)** — `create`, `update`, `delete`.
16
+ - **Hierarchy CRUD (M10)** — `create_node`, `update_node`,
17
+ `delete_node`.
18
+ - **Feature external references (M11)** —
19
+ `create_external_reference`, `delete_external_reference`.
20
+ - **Projects writes (M12)** — `create`.
21
+ - **Logs writes (M13)** — `post` (OpenTelemetry-style record
22
+ ingestion).
23
+ - **Bonus read tools (M16, +12)** — surface every read method already
24
+ in `calm-client` that consetto-Rust does not expose:
25
+ - `documents.list_statuses`, `documents.list_types`
26
+ - `projects.list_programs`, `projects.get_program`,
27
+ `projects.list_team_members`, `projects.list_timeboxes`
28
+ - `features.list_external_references`
29
+ - `tasks.list_deliverables`, `tasks.list_workstreams`,
30
+ `tasks.list_references`
31
+ - `testCases.list_activities`, `testCases.list_actions`
32
+ - **Integration test suite (M14)** under
33
+ `src/__tests__/integration/*.sandbox.test.ts` — one file per service,
34
+ gated on env, runs against the SAP sandbox in CI.
35
+ - **Live OAuth2 gates (M17)** —
36
+ `describeWhenLive`, `describeOAuth2`, `describeMutating` alongside
37
+ the existing sandbox gates. Mutation tests are opt-in via
38
+ `CALM_ALLOW_MUTATIONS=1` and always finalise via
39
+ `try/finally { delete }`.
40
+ - **`StderrLogger` (M15)** — minimal `ILogger` that routes every level
41
+ to stderr. Wired into `runStdio` so the bin emits lifecycle events
42
+ (start, transport bound, shutdown) without ever touching stdout
43
+ (which MCP-stdio reserves for the JSON-RPC frame stream). The
44
+ family's `PinoLogger` / `DefaultLogger` write `info`/`debug` to
45
+ stdout by default — using either inside a stdio MCP server would
46
+ corrupt every call.
47
+ - **`scripts/smoke-sandbox.mjs`** — 30-second smoke check: spawns the
48
+ stdio bin, lists tools, exercises a handful of read endpoints,
49
+ exits non-zero on any unexpected failure.
50
+
51
+ ### Fixed
52
+
53
+ - `list_hierarchy` and `list_test_cases` no longer ship sandbox-
54
+ incompatible properties in their default `$select`. The sandbox
55
+ OData type does not expose `parentNodeUuid` / `rootNodeUuid` on
56
+ `HierarchyNodes`, nor `statusCode` on `ManualTestCases`; defaults
57
+ returned 400 against the sandbox. Removed from `DEFAULT_FIELDS`;
58
+ callers can still opt in via `fields: [...]` against a tenant that
59
+ exposes them.
60
+ - `config.loadEnv` no longer reads the cwd-level `.env` under Jest.
61
+ The config-unit suite assumes a clean env; a developer's local
62
+ sandbox `.env` was silently leaking into it. Smoke scripts and the
63
+ stdio bin load `.env` explicitly via `dotenv` themselves.
64
+
65
+ ### Notes
66
+
67
+ - All HTTP / OData work lives in `@mcp-abap-adt/calm-client`. This
68
+ package is pure tool-shim: JSON Schema, args validation, error
69
+ mapping. The 19 new mutation tools added in M7–M13 required *zero*
70
+ changes to the client.
71
+ - Mutations against the shared SAP sandbox at `api.sap.com` are
72
+ intentionally not exercised by `npm test`; reachability is verified
73
+ via each tool's `INVALID_ARGUMENT` guard. Real ingestion happens
74
+ only under `describeMutating` on an opt-in live backend.
75
+
3
76
  ## 0.1.0 — 2026-04-24
4
77
 
5
78
  First usable release. 23 MCP tools covering all 9 Cloud ALM services,
package/README.md CHANGED
@@ -4,8 +4,9 @@
4
4
 
5
5
  MCP server for **SAP Cloud ALM**, built on
6
6
  [`@mcp-abap-adt/calm-client`](https://github.com/fr0ster/mcp-calm-client).
7
- Ships 23 MCP tools covering all 9 Cloud ALM services, with rich JSON
8
- Schema descriptions that let an LLM plan multi-step workflows.
7
+ Ships **54 MCP tools** covering all 9 Cloud ALM services full CRUD
8
+ where the service supports it, plus a wide read surface — with rich
9
+ JSON Schema descriptions that let an LLM plan multi-step workflows.
9
10
 
10
11
  This package is **dual-purpose**:
11
12
 
@@ -17,9 +18,10 @@ This package is **dual-purpose**:
17
18
 
18
19
  ## Status
19
20
 
20
- **0.1.0** — 23 tools, 103 unit tests, full build green. Integration
21
- against a live Cloud ALM tenant/sandbox is driven by the host — no
22
- server-side credential storage beyond the standalone `.env`.
21
+ **0.2.0** — 54 tools, 232 tests (224 unit + integration, 7 env-gated
22
+ skips, 1 todo), full build green. Integration suite runs live against
23
+ the SAP sandbox (api.sap.com) or any OAuth2 Cloud ALM tenant with a
24
+ single `.env` switch; gates skip cleanly when no backend is wired.
23
25
 
24
26
  ## Installation
25
27
 
@@ -101,7 +103,7 @@ on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows):
101
103
  }
102
104
  ```
103
105
 
104
- Restart Claude Desktop; the 23 `calm_*` tools become available to the
106
+ Restart Claude Desktop; the 54 `calm_*` tools become available to the
105
107
  model.
106
108
 
107
109
  ## Library: composing into another MCP server
@@ -145,19 +147,19 @@ import { ALL_GROUPS } from '@mcp-abap-adt/calm-server/tools';
145
147
  import { CalmToolRegistry } from '@mcp-abap-adt/calm-server/registry';
146
148
  ```
147
149
 
148
- ## Tool surface (23 tools across 9 services)
150
+ ## Tool surface (54 tools across 9 services)
149
151
 
150
152
  | Service | Tools |
151
153
  |---|---|
152
- | **Features** (8) | `list`, `get`, `get_by_display_id`, `create`, `update`, `delete`, `list_statuses`, `list_priorities` |
153
- | **Documents** (2) | `list`, `get` |
154
- | **TestCases** (2) | `list`, `get` |
155
- | **Hierarchy** (2) | `list`, `get_with_children` (default `$expand=[toChildNodes, toParentNode]`) |
154
+ | **Features** (11) | `list`, `get`, `get_by_display_id`, `create`, `update`, `delete`, `create_external_reference`, `delete_external_reference`, `list_external_references`, `list_statuses`, `list_priorities` |
155
+ | **Tasks** (10) | `list`, `get`, `create`, `update`, `delete`, `list_comments`, `create_comment`, `list_references`, `list_deliverables`, `list_workstreams` |
156
+ | **TestCases** (9) | `list`, `get`, `create`, `update`, `delete`, `create_activity`, `create_action`, `list_activities`, `list_actions` |
157
+ | **Documents** (7) | `list`, `get`, `create`, `update`, `delete`, `list_statuses`, `list_types` |
158
+ | **Projects** (7) | `list`, `get`, `create`, `list_programs`, `get_program`, `list_team_members`, `list_timeboxes` |
159
+ | **Hierarchy** (5) | `list`, `get_with_children`, `create_node`, `update_node`, `delete_node` |
156
160
  | **Analytics** (2, read-only) | `query` (17 endpoints), `list_providers` (static catalog) |
161
+ | **Logs** (2, domain-specific REST) | `get` (provider + serviceId + time window), `post` (inbound log records) |
157
162
  | **ProcessMonitoring** (1, read-only) | `list_processes` |
158
- | **Tasks** (3) | `list`, `get`, `list_comments` |
159
- | **Projects** (2) | `list`, `get` |
160
- | **Logs** (1, domain-specific REST) | `get` (provider + serviceId + time window) |
161
163
 
162
164
  Every MCP tool:
163
165
  - Has a full JSON Schema with descriptions — the LLM reads these to plan.
@@ -173,11 +175,20 @@ See `src/tools/<service>/*.ts` for per-tool argument schemas.
173
175
 
174
176
  ## Destructive tools (write operations)
175
177
 
176
- Currently only **Features** exposes `create` / `update` / `delete`. For
177
- the other 8 services, destructive tools are deferred to a future minor
178
- release they require live-tenant validation before the patterns are
179
- promoted. If you need them earlier, open an issue or contribute via the
180
- per-service handler modules; pattern is identical to the Features ones.
178
+ Every Cloud ALM service that supports writes is now exposed:
179
+
180
+ - **Features**: `create`, `update`, `delete`, plus external-reference
181
+ `create` / `delete`
182
+ - **Tasks**: `create`, `update`, `delete`, `create_comment`
183
+ - **TestCases**: `create`, `update`, `delete`, plus nested
184
+ `create_activity` / `create_action`
185
+ - **Documents**: `create`, `update`, `delete`
186
+ - **Hierarchy**: `create_node`, `update_node`, `delete_node`
187
+ - **Projects**: `create`
188
+ - **Logs**: `post` (inbound OpenTelemetry-style record ingestion)
189
+
190
+ The shared SAP sandbox at `api.sap.com` is read-friendly only — mutation
191
+ integration tests are opt-in (see Live-tenant integration below).
181
192
 
182
193
  ## Debug logging
183
194
 
@@ -197,16 +208,28 @@ git clone git@github.com:fr0ster/mcp-calm-server.git
197
208
  cd mcp-calm-server
198
209
  npm install
199
210
 
200
- npm run test # 103 unit tests, no network
211
+ npm run test # 224 unit + integration tests
201
212
  npm run build # emits dist/, includes executable bin
202
213
  npm run lint:check # biome
203
214
  ```
204
215
 
205
- No integration tests in this package — the `CalmClient` peer already
206
- covers live-tenant verification (see
207
- [mcp-calm-client/docs/TESTING.md](https://github.com/fr0ster/mcp-calm-client/blob/main/docs/TESTING.md)).
208
- Tools here only mediate between MCP and the client; their contracts
209
- are fully exercised via mocks.
216
+ ### Live-tenant integration
217
+
218
+ `src/__tests__/integration/` runs against a real backend when env is
219
+ present, and skips cleanly when it isn't (so `npm test` without secrets
220
+ is always green). Five gates, drop them into `.env`:
221
+
222
+ | Gate | Env trigger | What it unlocks |
223
+ |---|---|---|
224
+ | `describeSandbox` | `CALM_MODE=sandbox` + `CALM_API_KEY` | The `api.sap.com` sandbox |
225
+ | `describeOAuth2` | `CALM_MODE=oauth2` + `CALM_BASE_URL` + 3× UAA env | Live tenant (incl. endpoints absent from the sandbox catalog, e.g. Business Processes) |
226
+ | `describeWhenLive` | either of the above | Read-side tests that work in either mode |
227
+ | `describeWithProject` | live backend + `CALM_PROJECT_ID` | Project-scoped chains (features list→get, tasks list→get→comments, …) |
228
+ | `describeMutating` | live + `CALM_PROJECT_ID` + `CALM_ALLOW_MUTATIONS=1` | Write tests (every mutation finalises via `try/finally { delete }`) |
229
+
230
+ A quick smoke script lives at `scripts/smoke-sandbox.mjs` — spawns the
231
+ stdio bin, lists tools, calls a handful of read endpoints, and exits
232
+ 1 on any non-skip failure.
210
233
 
211
234
  ## License
212
235
 
package/dist/bin/stdio.js CHANGED
@@ -2,14 +2,17 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const runStdio_1 = require("../server/runStdio");
5
+ const stderrLogger_1 = require("../server/stderrLogger");
5
6
  (0, runStdio_1.runStdio)().catch((err) => {
7
+ // runStdio() may fail before its own logger is wired (config throws,
8
+ // missing env, etc.), so the catch block keeps a separate logger.
9
+ // StderrLogger guarantees we never write to stdout — keeping the
10
+ // MCP-stdio contract intact even on startup failure.
11
+ const logger = new stderrLogger_1.StderrLogger();
6
12
  const msg = err instanceof Error ? err.message : String(err);
7
- // All diagnostic output on stderr — stdout is reserved for the MCP
8
- // protocol stream.
9
- process.stderr.write(`[calm-mcp] startup failed: ${msg}\n`);
10
- if (err instanceof Error && err.stack) {
11
- process.stderr.write(`${err.stack}\n`);
12
- }
13
+ logger.error(`[calm-mcp] startup failed: ${msg}`, {
14
+ stack: err instanceof Error ? err.stack : undefined,
15
+ });
13
16
  process.exit(1);
14
17
  });
15
18
  //# sourceMappingURL=stdio.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/bin/stdio.ts"],"names":[],"mappings":";;;AACA,iDAA8C;AAE9C,IAAA,mBAAQ,GAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAChC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,mEAAmE;IACnE,mBAAmB;IACnB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,GAAG,IAAI,CAAC,CAAC;IAC5D,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;QACtC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,IAAI,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"stdio.js","sourceRoot":"","sources":["../../src/bin/stdio.ts"],"names":[],"mappings":";;;AACA,iDAA8C;AAC9C,yDAAsD;AAEtD,IAAA,mBAAQ,GAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAChC,qEAAqE;IACrE,kEAAkE;IAClE,iEAAiE;IACjE,qDAAqD;IACrD,MAAM,MAAM,GAAG,IAAI,2BAAY,EAAE,CAAC;IAClC,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAC7D,MAAM,CAAC,KAAK,CAAC,8BAA8B,GAAG,EAAE,EAAE;QAChD,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;KACpD,CAAC,CAAC;IACH,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAK9B;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAYD,wBAAgB,UAAU,IAAI,iBAAiB,CAkC9C"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":"AAMA;;;;GAIG;AACH,wBAAgB,OAAO,IAAI,IAAI,CAU9B;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAYD,wBAAgB,UAAU,IAAI,iBAAiB,CAkC9C"}
@@ -14,10 +14,16 @@ let loaded = false;
14
14
  function loadEnv() {
15
15
  if (loaded)
16
16
  return;
17
+ loaded = true;
18
+ // Under Jest, never auto-load a cwd-level .env: unit tests assert on
19
+ // the absence of CALM_* vars, and a developer's local sandbox .env
20
+ // would otherwise leak into that suite and make assertions flaky.
21
+ // Smoke scripts and the stdio bin explicitly call dotenvConfig themselves.
22
+ if (process.env.JEST_WORKER_ID)
23
+ return;
17
24
  const path = (0, node_path_1.resolve)(process.cwd(), '.env');
18
25
  if ((0, node_fs_1.existsSync)(path))
19
26
  (0, dotenv_1.config)({ path });
20
- loaded = true;
21
27
  }
22
28
  function required(name) {
23
29
  const v = process.env[name];
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":";;AAWA,0BAKC;AAwBD,gCAkCC;AA1ED,qCAAqC;AACrC,yCAAoC;AACpC,mCAAgD;AAEhD,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB;;;;GAIG;AACH,SAAgB,OAAO;IACrB,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,IAAI,GAAG,IAAA,mBAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,IAAA,oBAAU,EAAC,IAAI,CAAC;QAAE,IAAA,eAAY,EAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC;AAcD,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,6CAA6C,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAgB,UAAU;IACxB,OAAO,EAAE,CAAC;IACV,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,EAElC,CAAC;IACd,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY;QACxC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAClC,CAAC,CAAC,MAAM,CAAC;IAEX,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO;YACL,IAAI;YACJ,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC;YAClC,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC;YAChC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC;YAC3C,eAAe,EAAE,QAAQ,CAAC,wBAAwB,CAAC;YACnD,SAAS;SACV,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,OAAO,EACL,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,qCAAqC;YACpE,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC;YAChC,SAAS;SACV,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,GAAG,CAAC,CAAC;AAC5D,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/server/config.ts"],"names":[],"mappings":";;AAWA,0BAUC;AAwBD,gCAkCC;AA/ED,qCAAqC;AACrC,yCAAoC;AACpC,mCAAgD;AAEhD,IAAI,MAAM,GAAG,KAAK,CAAC;AAEnB;;;;GAIG;AACH,SAAgB,OAAO;IACrB,IAAI,MAAM;QAAE,OAAO;IACnB,MAAM,GAAG,IAAI,CAAC;IACd,qEAAqE;IACrE,mEAAmE;IACnE,kEAAkE;IAClE,2EAA2E;IAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc;QAAE,OAAO;IACvC,MAAM,IAAI,GAAG,IAAA,mBAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;IAC5C,IAAI,IAAA,oBAAU,EAAC,IAAI,CAAC;QAAE,IAAA,eAAY,EAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AAC/C,CAAC;AAcD,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,IAAI,KAAK,CACb,sBAAsB,IAAI,6CAA6C,CACxE,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAgB,UAAU;IACxB,OAAO,EAAE,CAAC;IACV,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,WAAW,EAElC,CAAC;IACd,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CACb,yEAAyE,CAC1E,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY;QACxC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;QAClC,CAAC,CAAC,MAAM,CAAC;IAEX,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,OAAO;YACL,IAAI;YACJ,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC;YAClC,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC;YAChC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC;YAC3C,eAAe,EAAE,QAAQ,CAAC,wBAAwB,CAAC;YACnD,SAAS;SACV,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,OAAO,EACL,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,qCAAqC;YACpE,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC;YAChC,SAAS;SACV,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,GAAG,CAAC,CAAC;AAC5D,CAAC"}
@@ -3,10 +3,8 @@
3
3
  * builds a `CalmClient`, wires all tool groups onto a
4
4
  * `BaseCalmMcpServer`, and binds the server to the stdio transport.
5
5
  *
6
- * Errors during config/connect phase are written to stderr so the
7
- * host (Claude Desktop / whoever) sees a meaningful failure instead
8
- * of a silent hang. On success, stdio takes over — no console output
9
- * from the server.
6
+ * Logging goes through `StderrLogger` never stdout because MCP
7
+ * stdio reserves stdout for the JSON-RPC protocol stream.
10
8
  */
11
9
  export declare function runStdio(): Promise<void>;
12
10
  //# sourceMappingURL=runStdio.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"runStdio.d.ts","sourceRoot":"","sources":["../../src/server/runStdio.ts"],"names":[],"mappings":"AASA;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CA4B9C"}
1
+ {"version":3,"file":"runStdio.d.ts","sourceRoot":"","sources":["../../src/server/runStdio.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAwC9C"}
@@ -6,35 +6,45 @@ const tools_1 = require("../tools");
6
6
  const BaseCalmMcpServer_1 = require("./BaseCalmMcpServer");
7
7
  const buildClient_1 = require("./buildClient");
8
8
  const config_1 = require("./config");
9
+ const stderrLogger_1 = require("./stderrLogger");
9
10
  const PACKAGE_NAME = '@mcp-abap-adt/calm-server';
10
- const PACKAGE_VERSION = '0.0.1';
11
+ const PACKAGE_VERSION = '0.2.0';
11
12
  /**
12
13
  * Entry point for standalone stdio mode. Reads `.env` + env vars,
13
14
  * builds a `CalmClient`, wires all tool groups onto a
14
15
  * `BaseCalmMcpServer`, and binds the server to the stdio transport.
15
16
  *
16
- * Errors during config/connect phase are written to stderr so the
17
- * host (Claude Desktop / whoever) sees a meaningful failure instead
18
- * of a silent hang. On success, stdio takes over — no console output
19
- * from the server.
17
+ * Logging goes through `StderrLogger` never stdout because MCP
18
+ * stdio reserves stdout for the JSON-RPC protocol stream.
20
19
  */
21
20
  async function runStdio() {
21
+ const logger = new stderrLogger_1.StderrLogger();
22
22
  const config = (0, config_1.readConfig)();
23
23
  const calm = (0, buildClient_1.buildCalmClient)(config);
24
24
  const server = new BaseCalmMcpServer_1.BaseCalmMcpServer({
25
25
  name: PACKAGE_NAME,
26
26
  version: PACKAGE_VERSION,
27
27
  calm,
28
+ logger,
28
29
  groups: [...tools_1.ALL_GROUPS],
29
30
  });
31
+ logger.info('calm-mcp starting', {
32
+ package: PACKAGE_NAME,
33
+ version: PACKAGE_VERSION,
34
+ mode: config.mode,
35
+ baseUrl: config.baseUrl,
36
+ tools: server.listRegisteredTools().length,
37
+ });
30
38
  // Best-effort early token / connectivity probe so misconfiguration
31
39
  // surfaces on startup rather than on the first tool call.
32
40
  await calm.getConnection().connect();
33
41
  const transport = new stdio_js_1.StdioServerTransport();
34
42
  await server.connect(transport);
43
+ logger.info('calm-mcp transport bound (stdio)');
35
44
  // Graceful shutdown on SIGINT / SIGTERM — ensures stdio is cleanly
36
45
  // closed so the host does not see a dangling child process.
37
46
  const shutdown = async () => {
47
+ logger.info('calm-mcp shutdown signal received');
38
48
  try {
39
49
  await server.close();
40
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"runStdio.js","sourceRoot":"","sources":["../../src/server/runStdio.ts"],"names":[],"mappings":";;AAmBA,4BA4BC;AA/CD,wEAAiF;AACjF,oCAAsC;AACtC,2DAAwD;AACxD,+CAAgD;AAChD,qCAAsC;AAEtC,MAAM,YAAY,GAAG,2BAA2B,CAAC;AACjD,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC;;;;;;;;;GASG;AACI,KAAK,UAAU,QAAQ;IAC5B,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAA,6BAAe,EAAC,MAAM,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,qCAAiB,CAAC;QACnC,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,eAAe;QACxB,IAAI;QACJ,MAAM,EAAE,CAAC,GAAG,kBAAU,CAAC;KACxB,CAAC,CAAC;IAEH,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,CAAC;IAErC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,mEAAmE;IACnE,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC"}
1
+ {"version":3,"file":"runStdio.js","sourceRoot":"","sources":["../../src/server/runStdio.ts"],"names":[],"mappings":";;AAkBA,4BAwCC;AA1DD,wEAAiF;AACjF,oCAAsC;AACtC,2DAAwD;AACxD,+CAAgD;AAChD,qCAAsC;AACtC,iDAA8C;AAE9C,MAAM,YAAY,GAAG,2BAA2B,CAAC;AACjD,MAAM,eAAe,GAAG,OAAO,CAAC;AAEhC;;;;;;;GAOG;AACI,KAAK,UAAU,QAAQ;IAC5B,MAAM,MAAM,GAAG,IAAI,2BAAY,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;IAC5B,MAAM,IAAI,GAAG,IAAA,6BAAe,EAAC,MAAM,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,IAAI,qCAAiB,CAAC;QACnC,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,eAAe;QACxB,IAAI;QACJ,MAAM;QACN,MAAM,EAAE,CAAC,GAAG,kBAAU,CAAC;KACxB,CAAC,CAAC;IAEH,MAAM,CAAC,IAAI,CAAC,mBAAmB,EAAE;QAC/B,OAAO,EAAE,YAAY;QACrB,OAAO,EAAE,eAAe;QACxB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,KAAK,EAAE,MAAM,CAAC,mBAAmB,EAAE,CAAC,MAAM;KAC3C,CAAC,CAAC;IAEH,mEAAmE;IACnE,0DAA0D;IAC1D,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,CAAC;IAErC,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IAEhD,mEAAmE;IACnE,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,KAAK,IAAmB,EAAE;QACzC,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { ILogger } from '@mcp-abap-adt/interfaces';
2
+ /**
3
+ * Minimal `ILogger` that writes every level to **stderr only**.
4
+ *
5
+ * Why this exists: the MCP **stdio** transport reserves stdout for the
6
+ * JSON-RPC protocol stream. Any byte written to stdout that is not a
7
+ * valid MCP frame breaks the connection. Both the family's
8
+ * `DefaultLogger` and `PinoLogger` write `info`/`debug` to stdout by
9
+ * default — using them inside a stdio MCP server would corrupt the
10
+ * stream. This logger sidesteps that by sending every message to
11
+ * fd=2.
12
+ *
13
+ * Library consumers that wire `BaseCalmMcpServer` over a non-stdio
14
+ * transport (HTTP, custom) should bring their own logger — they don't
15
+ * have the stdout-collision concern.
16
+ */
17
+ export declare class StderrLogger implements ILogger {
18
+ private write;
19
+ info(message: string, meta?: unknown): void;
20
+ warn(message: string, meta?: unknown): void;
21
+ error(message: string, meta?: unknown): void;
22
+ debug(message: string, meta?: unknown): void;
23
+ }
24
+ //# sourceMappingURL=stderrLogger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stderrLogger.d.ts","sourceRoot":"","sources":["../../src/server/stderrLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAExD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,YAAW,OAAO;IAC1C,OAAO,CAAC,KAAK;IAQb,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;IAI5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI;CAI7C"}
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StderrLogger = void 0;
4
+ /**
5
+ * Minimal `ILogger` that writes every level to **stderr only**.
6
+ *
7
+ * Why this exists: the MCP **stdio** transport reserves stdout for the
8
+ * JSON-RPC protocol stream. Any byte written to stdout that is not a
9
+ * valid MCP frame breaks the connection. Both the family's
10
+ * `DefaultLogger` and `PinoLogger` write `info`/`debug` to stdout by
11
+ * default — using them inside a stdio MCP server would corrupt the
12
+ * stream. This logger sidesteps that by sending every message to
13
+ * fd=2.
14
+ *
15
+ * Library consumers that wire `BaseCalmMcpServer` over a non-stdio
16
+ * transport (HTTP, custom) should bring their own logger — they don't
17
+ * have the stdout-collision concern.
18
+ */
19
+ class StderrLogger {
20
+ write(prefix, message, meta) {
21
+ if (meta !== undefined) {
22
+ process.stderr.write(`${prefix} ${message} ${JSON.stringify(meta)}\n`);
23
+ }
24
+ else {
25
+ process.stderr.write(`${prefix} ${message}\n`);
26
+ }
27
+ }
28
+ info(message, meta) {
29
+ this.write('[INFO]', message, meta);
30
+ }
31
+ warn(message, meta) {
32
+ this.write('[WARN]', message, meta);
33
+ }
34
+ error(message, meta) {
35
+ this.write('[ERROR]', message, meta);
36
+ }
37
+ debug(message, meta) {
38
+ if (process.env.CALM_LOG_LEVEL?.toLowerCase() !== 'debug')
39
+ return;
40
+ this.write('[DEBUG]', message, meta);
41
+ }
42
+ }
43
+ exports.StderrLogger = StderrLogger;
44
+ //# sourceMappingURL=stderrLogger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stderrLogger.js","sourceRoot":"","sources":["../../src/server/stderrLogger.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAa,YAAY;IACf,KAAK,CAAC,MAAc,EAAE,OAAe,EAAE,IAAc;QAC3D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,OAAO,IAAI,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,IAAc;QAClC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,IAAc;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,EAAE,KAAK,OAAO;YAAE,OAAO;QAClE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACvC,CAAC;CACF;AAzBD,oCAyBC"}
@@ -0,0 +1,5 @@
1
+ import type { ICreateDocumentParams, IDocument } from '@mcp-abap-adt/calm-client';
2
+ import type { ICalmHandlerEntry } from '../../registry/types';
3
+ export type ICreateDocumentArgs = ICreateDocumentParams;
4
+ export declare const createDocumentTool: ICalmHandlerEntry<ICreateDocumentArgs, IDocument>;
5
+ //# sourceMappingURL=createDocument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDocument.d.ts","sourceRoot":"","sources":["../../../src/tools/documents/createDocument.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,SAAS,EACV,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,MAAM,mBAAmB,GAAG,qBAAqB,CAAC;AA8CxD,eAAO,MAAM,kBAAkB,EAAE,iBAAiB,CAChD,mBAAmB,EACnB,SAAS,CAIV,CAAC"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createDocumentTool = void 0;
4
+ const utils_1 = require("../../utils");
5
+ const definition = {
6
+ name: 'calm_documents_create',
7
+ description: 'Create a new Cloud ALM document. Destructive. Requires `title`; other fields are optional. NOTE the write-side field is `typeCode` (read-side returns `documentTypeCode`). Returns the newly created document.',
8
+ inputSchema: {
9
+ type: 'object',
10
+ required: ['title'],
11
+ properties: {
12
+ title: { type: 'string', description: 'Document title.' },
13
+ content: {
14
+ type: 'string',
15
+ description: 'Optional document body (markdown or plain text).',
16
+ },
17
+ projectId: {
18
+ type: 'string',
19
+ description: 'Optional project scope.',
20
+ },
21
+ typeCode: {
22
+ type: 'string',
23
+ description: 'Document type code (write-side spelling).',
24
+ },
25
+ statusCode: { type: 'string', description: 'Optional starting status.' },
26
+ priorityCode: { type: 'string', description: 'Optional priority.' },
27
+ },
28
+ },
29
+ };
30
+ const handler = async (ctx, args) => {
31
+ if (!args?.title) {
32
+ throw new utils_1.CalmToolError({
33
+ code: 'INVALID_ARGUMENT',
34
+ message: 'title is required',
35
+ });
36
+ }
37
+ try {
38
+ return await ctx.calm.getDocuments().create(args);
39
+ }
40
+ catch (err) {
41
+ throw (0, utils_1.mapCalmErrorForTool)(err);
42
+ }
43
+ };
44
+ exports.createDocumentTool = {
45
+ toolDefinition: definition,
46
+ handler,
47
+ };
48
+ //# sourceMappingURL=createDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createDocument.js","sourceRoot":"","sources":["../../../src/tools/documents/createDocument.ts"],"names":[],"mappings":";;;AASA,uCAAiE;AAIjE,MAAM,UAAU,GAAwB;IACtC,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,gNAAgN;IAClN,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,OAAO,CAAC;QACnB,UAAU,EAAE;YACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,iBAAiB,EAAE;YACzD,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,kDAAkD;aAChE;YACD,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,yBAAyB;aACvC;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,2CAA2C;aACzD;YACD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2BAA2B,EAAE;YACxE,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;SACpE;KACF;CACF,CAAC;AAEF,MAAM,OAAO,GAAoD,KAAK,EACpE,GAAG,EACH,IAAI,EACJ,EAAE;IACF,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;QACjB,MAAM,IAAI,qBAAa,CAAC;YACtB,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,mBAAmB;SAC7B,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC;QACH,OAAO,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACpD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAA,2BAAmB,EAAC,GAAG,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC;AAEW,QAAA,kBAAkB,GAG3B;IACF,cAAc,EAAE,UAAU;IAC1B,OAAO;CACR,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { ICalmHandlerEntry } from '../../registry/types';
2
+ export interface IDeleteDocumentArgs {
3
+ uuid: string;
4
+ }
5
+ export interface IDeleteDocumentResult {
6
+ deleted: true;
7
+ uuid: string;
8
+ }
9
+ export declare const deleteDocumentTool: ICalmHandlerEntry<IDeleteDocumentArgs, IDeleteDocumentResult>;
10
+ //# sourceMappingURL=deleteDocument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deleteDocument.d.ts","sourceRoot":"","sources":["../../../src/tools/documents/deleteDocument.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,iBAAiB,EAElB,MAAM,sBAAsB,CAAC;AAG9B,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAiCD,eAAO,MAAM,kBAAkB,EAAE,iBAAiB,CAChD,mBAAmB,EACnB,qBAAqB,CAItB,CAAC"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deleteDocumentTool = void 0;
4
+ const utils_1 = require("../../utils");
5
+ const definition = {
6
+ name: 'calm_documents_delete',
7
+ description: 'Delete a Cloud ALM document by UUID. Destructive. Returns a confirmation object; raises NOT_FOUND if the document does not exist.',
8
+ inputSchema: {
9
+ type: 'object',
10
+ required: ['uuid'],
11
+ properties: {
12
+ uuid: { type: 'string', description: 'Document UUID to delete.' },
13
+ },
14
+ },
15
+ };
16
+ const handler = async (ctx, args) => {
17
+ if (!args?.uuid) {
18
+ throw new utils_1.CalmToolError({
19
+ code: 'INVALID_ARGUMENT',
20
+ message: 'uuid is required',
21
+ });
22
+ }
23
+ try {
24
+ await ctx.calm.getDocuments().delete(args.uuid);
25
+ return { deleted: true, uuid: args.uuid };
26
+ }
27
+ catch (err) {
28
+ throw (0, utils_1.mapCalmErrorForTool)(err);
29
+ }
30
+ };
31
+ exports.deleteDocumentTool = {
32
+ toolDefinition: definition,
33
+ handler,
34
+ };
35
+ //# sourceMappingURL=deleteDocument.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deleteDocument.js","sourceRoot":"","sources":["../../../src/tools/documents/deleteDocument.ts"],"names":[],"mappings":";;;AAKA,uCAAiE;AAWjE,MAAM,UAAU,GAAwB;IACtC,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,mIAAmI;IACrI,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0BAA0B,EAAE;SAClE;KACF;CACF,CAAC;AAEF,MAAM,OAAO,GAGT,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;IACtB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;QAChB,MAAM,IAAI,qBAAa,CAAC;YACtB,IAAI,EAAE,kBAAkB;YACxB,OAAO,EAAE,kBAAkB;SAC5B,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAA,2BAAmB,EAAC,GAAG,CAAC,CAAC;IACjC,CAAC;AACH,CAAC,CAAC;AAEW,QAAA,kBAAkB,GAG3B;IACF,cAAc,EAAE,UAAU;IAC1B,OAAO;CACR,CAAC"}
@@ -1,9 +1,19 @@
1
1
  import { HandlerGroup } from '../../registry/HandlerGroup';
2
2
  import type { ICalmHandlerEntry } from '../../registry/types';
3
+ export type { ICreateDocumentArgs } from './createDocument';
4
+ export { createDocumentTool } from './createDocument';
5
+ export type { IDeleteDocumentArgs, IDeleteDocumentResult, } from './deleteDocument';
6
+ export { deleteDocumentTool } from './deleteDocument';
3
7
  export type { IGetDocumentArgs } from './getDocument';
4
8
  export { getDocumentTool } from './getDocument';
9
+ export type { IListDocumentStatusesResult } from './listDocumentStatuses';
10
+ export { listDocumentStatusesTool } from './listDocumentStatuses';
5
11
  export type { IListDocumentsArgs } from './listDocuments';
6
12
  export { listDocumentsTool } from './listDocuments';
13
+ export type { IListDocumentTypesResult } from './listDocumentTypes';
14
+ export { listDocumentTypesTool } from './listDocumentTypes';
15
+ export type { IUpdateDocumentArgs } from './updateDocument';
16
+ export { updateDocumentTool } from './updateDocument';
7
17
  export declare const DOCUMENTS_HANDLERS: readonly ICalmHandlerEntry[];
8
18
  export declare const DOCUMENTS_GROUP: HandlerGroup;
9
19
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/documents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAI9D,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEpD,eAAO,MAAM,kBAAkB,EAAE,SAAS,iBAAiB,EAG1D,CAAC;AAEF,eAAO,MAAM,eAAe,cAG3B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/documents/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAS9D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EACV,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,YAAY,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAC1E,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,YAAY,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEtD,eAAO,MAAM,kBAAkB,EAAE,SAAS,iBAAiB,EAQ1D,CAAC;AAEF,eAAO,MAAM,eAAe,cAG3B,CAAC"}
@@ -1,16 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DOCUMENTS_GROUP = exports.DOCUMENTS_HANDLERS = exports.listDocumentsTool = exports.getDocumentTool = void 0;
3
+ exports.DOCUMENTS_GROUP = exports.DOCUMENTS_HANDLERS = exports.updateDocumentTool = exports.listDocumentTypesTool = exports.listDocumentsTool = exports.listDocumentStatusesTool = exports.getDocumentTool = exports.deleteDocumentTool = exports.createDocumentTool = void 0;
4
4
  const HandlerGroup_1 = require("../../registry/HandlerGroup");
5
+ const createDocument_1 = require("./createDocument");
6
+ const deleteDocument_1 = require("./deleteDocument");
5
7
  const getDocument_1 = require("./getDocument");
8
+ const listDocumentStatuses_1 = require("./listDocumentStatuses");
6
9
  const listDocuments_1 = require("./listDocuments");
10
+ const listDocumentTypes_1 = require("./listDocumentTypes");
11
+ const updateDocument_1 = require("./updateDocument");
12
+ var createDocument_2 = require("./createDocument");
13
+ Object.defineProperty(exports, "createDocumentTool", { enumerable: true, get: function () { return createDocument_2.createDocumentTool; } });
14
+ var deleteDocument_2 = require("./deleteDocument");
15
+ Object.defineProperty(exports, "deleteDocumentTool", { enumerable: true, get: function () { return deleteDocument_2.deleteDocumentTool; } });
7
16
  var getDocument_2 = require("./getDocument");
8
17
  Object.defineProperty(exports, "getDocumentTool", { enumerable: true, get: function () { return getDocument_2.getDocumentTool; } });
18
+ var listDocumentStatuses_2 = require("./listDocumentStatuses");
19
+ Object.defineProperty(exports, "listDocumentStatusesTool", { enumerable: true, get: function () { return listDocumentStatuses_2.listDocumentStatusesTool; } });
9
20
  var listDocuments_2 = require("./listDocuments");
10
21
  Object.defineProperty(exports, "listDocumentsTool", { enumerable: true, get: function () { return listDocuments_2.listDocumentsTool; } });
22
+ var listDocumentTypes_2 = require("./listDocumentTypes");
23
+ Object.defineProperty(exports, "listDocumentTypesTool", { enumerable: true, get: function () { return listDocumentTypes_2.listDocumentTypesTool; } });
24
+ var updateDocument_2 = require("./updateDocument");
25
+ Object.defineProperty(exports, "updateDocumentTool", { enumerable: true, get: function () { return updateDocument_2.updateDocumentTool; } });
11
26
  exports.DOCUMENTS_HANDLERS = [
12
27
  listDocuments_1.listDocumentsTool,
13
28
  getDocument_1.getDocumentTool,
29
+ createDocument_1.createDocumentTool,
30
+ updateDocument_1.updateDocumentTool,
31
+ deleteDocument_1.deleteDocumentTool,
32
+ listDocumentStatuses_1.listDocumentStatusesTool,
33
+ listDocumentTypes_1.listDocumentTypesTool,
14
34
  ];
15
35
  exports.DOCUMENTS_GROUP = new HandlerGroup_1.HandlerGroup('documents', exports.DOCUMENTS_HANDLERS);
16
36
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/documents/index.ts"],"names":[],"mappings":";;;AAAA,8DAA2D;AAE3D,+CAAgD;AAChD,mDAAoD;AAGpD,6CAAgD;AAAvC,8GAAA,eAAe,OAAA;AAExB,iDAAoD;AAA3C,kHAAA,iBAAiB,OAAA;AAEb,QAAA,kBAAkB,GAAiC;IAC9D,iCAAiB;IACjB,6BAAe;CAChB,CAAC;AAEW,QAAA,eAAe,GAAG,IAAI,2BAAY,CAC7C,WAAW,EACX,0BAAkB,CACnB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/documents/index.ts"],"names":[],"mappings":";;;AAAA,8DAA2D;AAE3D,qDAAsD;AACtD,qDAAsD;AACtD,+CAAgD;AAChD,iEAAkE;AAClE,mDAAoD;AACpD,2DAA4D;AAC5D,qDAAsD;AAGtD,mDAAsD;AAA7C,oHAAA,kBAAkB,OAAA;AAK3B,mDAAsD;AAA7C,oHAAA,kBAAkB,OAAA;AAE3B,6CAAgD;AAAvC,8GAAA,eAAe,OAAA;AAExB,+DAAkE;AAAzD,gIAAA,wBAAwB,OAAA;AAEjC,iDAAoD;AAA3C,kHAAA,iBAAiB,OAAA;AAE1B,yDAA4D;AAAnD,0HAAA,qBAAqB,OAAA;AAE9B,mDAAsD;AAA7C,oHAAA,kBAAkB,OAAA;AAEd,QAAA,kBAAkB,GAAiC;IAC9D,iCAAiB;IACjB,6BAAe;IACf,mCAAkB;IAClB,mCAAkB;IAClB,mCAAkB;IAClB,+CAAwB;IACxB,yCAAqB;CACtB,CAAC;AAEW,QAAA,eAAe,GAAG,IAAI,2BAAY,CAC7C,WAAW,EACX,0BAAkB,CACnB,CAAC"}