@ui5/mcp-server 0.2.5 → 0.2.7

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 (31) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +75 -59
  3. package/icon.png +0 -0
  4. package/lib/tools/create_integration_card/create_integration_card.d.ts +3 -2
  5. package/lib/tools/create_integration_card/create_integration_card.js +24 -1
  6. package/lib/tools/create_integration_card/create_integration_card.js.map +1 -1
  7. package/lib/tools/create_integration_card/index.js +1 -0
  8. package/lib/tools/create_integration_card/index.js.map +1 -1
  9. package/lib/tools/create_integration_card/schema.d.ts +10 -0
  10. package/lib/tools/create_integration_card/schema.js +9 -0
  11. package/lib/tools/create_integration_card/schema.js.map +1 -1
  12. package/lib/tools/create_ui5_app/create_ui5_app.js +5 -33
  13. package/lib/tools/create_ui5_app/create_ui5_app.js.map +1 -1
  14. package/lib/tools/create_ui5_app/templateProcessor.d.ts +2 -0
  15. package/lib/tools/create_ui5_app/templateProcessor.js.map +1 -1
  16. package/lib/utils/getAllowedDomains.d.ts +1 -0
  17. package/lib/utils/getAllowedDomains.js +35 -0
  18. package/lib/utils/getAllowedDomains.js.map +1 -0
  19. package/lib/{tools/create_ui5_app → utils}/isValidUrl.js +1 -1
  20. package/lib/utils/isValidUrl.js.map +1 -0
  21. package/npm-shrinkwrap.json +756 -673
  22. package/package.json +21 -20
  23. package/resources/integration_cards_guidelines.md +260 -2
  24. package/resources/template-card/card/manifest.json +10 -0
  25. package/resources/template-card/test/App.js +20 -4
  26. package/resources/template-card/test/index.css +4 -0
  27. package/resources/template-card/test/index.html +1 -3
  28. package/resources/template-js/webapp/manifest.json +5 -1
  29. package/resources/template-ts/webapp/manifest.json +5 -1
  30. package/lib/tools/create_ui5_app/isValidUrl.js.map +0 -1
  31. /package/lib/{tools/create_ui5_app → utils}/isValidUrl.d.ts +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ui5/mcp-server",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
4
4
  "description": "MCP server for SAPUI5/OpenUI5 development",
5
5
  "author": {
6
6
  "name": "SAP SE",
@@ -35,8 +35,8 @@
35
35
  "build-test": "tsc --noEmit -p .",
36
36
  "build-watch": "npm run clean-lib && tsc -w -p tsconfig.build.json",
37
37
  "check-licenses": "licensee --errors-only",
38
- "depcheck": "depcheck --ignores @commitlint/config-conventional,@istanbuljs/esm-loader-hook,rimraf,@modelcontextprotocol/inspector",
39
- "hooks:pre-push": "npm run lint:commit && npm run lint && npm run depcheck",
38
+ "knip": "knip --config knip.config.js",
39
+ "hooks:pre-push": "npm run lint:commit && npm run lint && npm run knip",
40
40
  "lint:commit": "commitlint -e",
41
41
  "prepare": "node ./.husky/skip.js || husky",
42
42
  "clean-coverage": "rimraf coverage",
@@ -44,7 +44,7 @@
44
44
  "clean-test-tmp": "rimraf test/tmp",
45
45
  "lint": "eslint .",
46
46
  "lint-fix": "eslint . --fix",
47
- "test": "npm run lint && npm run build-test && npm run coverage && npm run depcheck && npm run check-licenses",
47
+ "test": "npm run lint && npm run build-test && npm run coverage && npm run knip && npm run check-licenses",
48
48
  "coverage": "npm run clean-coverage && nyc ava --node-arguments=\"--experimental-loader=@istanbuljs/esm-loader-hook\"",
49
49
  "unit": "ava",
50
50
  "unit-debug": "ava debug",
@@ -61,7 +61,8 @@
61
61
  "lib/**",
62
62
  "resources/**",
63
63
  "npm-shrinkwrap.json",
64
- ".reuse/**"
64
+ ".reuse/**",
65
+ "icon.png"
65
66
  ],
66
67
  "engines": {
67
68
  "node": "^20.17.0 || >=22.9.0",
@@ -75,30 +76,30 @@
75
76
  }
76
77
  },
77
78
  "dependencies": {
78
- "@modelcontextprotocol/sdk": "^1.26.0",
79
- "@ui5/linter": "^1.20.10",
79
+ "@modelcontextprotocol/sdk": "^1.27.1",
80
+ "@ui5/linter": "^1.20.12",
80
81
  "@ui5/logger": "^4.0.2",
81
- "@ui5/project": "^4.0.9",
82
+ "@ui5/project": "^4.0.11",
82
83
  "ajv": "^8.17.1",
83
84
  "ajv-formats": "^3.0.1",
84
85
  "async-mutex": "^0.5.0",
85
86
  "ejs": "^4.0.1",
86
87
  "execa": "^9.6.1",
87
- "fast-xml-parser": "^5.3.4",
88
- "globby": "^16.1.0",
88
+ "fast-xml-parser": "^5.4.1",
89
+ "globby": "^16.1.1",
89
90
  "lockfile": "^1.0.4",
90
- "make-fetch-happen": "^15.0.3",
91
+ "make-fetch-happen": "^15.0.4",
91
92
  "semver": "^7.7.4",
92
93
  "zod": "^4.3.6"
93
94
  },
94
95
  "devDependencies": {
95
- "@commitlint/cli": "^20.4.1",
96
- "@commitlint/config-conventional": "^20.4.1",
96
+ "@commitlint/cli": "^20.4.2",
97
+ "@commitlint/config-conventional": "^20.4.2",
97
98
  "@eslint/js": "^9.39.2",
98
99
  "@istanbuljs/esm-loader-hook": "^0.3.0",
99
100
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
100
- "@modelcontextprotocol/inspector": "^0.18.0",
101
- "@stylistic/eslint-plugin": "^5.7.1",
101
+ "@modelcontextprotocol/inspector": "^0.21.0",
102
+ "@stylistic/eslint-plugin": "^5.9.0",
102
103
  "@types/ejs": "^3.1.5",
103
104
  "@types/make-fetch-happen": "^10.0.4",
104
105
  "@types/node": "20.16.15",
@@ -107,18 +108,18 @@
107
108
  "@types/yauzl-promise": "^4.0.1",
108
109
  "@ui5-language-assistant/semantic-model-types": "^3.3.1",
109
110
  "ava": "^6.3.0",
110
- "depcheck": "^1.4.7",
111
111
  "eslint": "^9.39.2",
112
112
  "eslint-plugin-ava": "^15.0.1",
113
113
  "esmock": "^2.7.3",
114
114
  "husky": "^9.1.7",
115
- "licensee": "^12.0.1",
116
- "nyc": "^17.1.0",
117
- "rimraf": "^6.1.2",
115
+ "knip": "^5.84.1",
116
+ "licensee": "^11.1.1",
117
+ "nyc": "^18.0.0",
118
+ "rimraf": "^6.1.3",
118
119
  "sinon": "^21.0.1",
119
120
  "tsx": "^4.21.0",
120
121
  "typescript": "^5.9.3",
121
- "typescript-eslint": "^8.54.0",
122
+ "typescript-eslint": "^8.56.1",
122
123
  "yauzl-promise": "^4.0.0"
123
124
  },
124
125
  "overrides": {
@@ -39,6 +39,9 @@
39
39
  ### 1.3 Analytical Cards
40
40
  - **ALWAYS** follow [6. Analytical Cards Coding Guidelines](#6-analytical-cards-coding-guidelines) when developing Analytical cards.
41
41
 
42
+ ### 1.4 Configuration Editor
43
+ - **ALWAYS** follow [5. Configuration Editor](#5-configuration-editor) guidelines when creating or modifying Configuration Editors for Integration Cards.
44
+
42
45
  ## 2. Validation
43
46
  - **ALWAYS** ensure that `manifest.json` file is valid JSON.
44
47
  - **ALWAYS** ensure that in `manifest.json` file the property `sap.app/type` is set to `"card"`.
@@ -50,13 +53,268 @@
50
53
  - The Card Explorer provides detailed documentation for the Integration Cards schema, including descriptions of every property, guidance for integrating cards into hosting environments, configuration editor documentation with examples, and broader best practices. It is available at: https://ui5.sap.com/test-resources/sap/ui/integration/demokit/cardExplorer/webapp/index.html
51
54
 
52
55
  ## 4. Preview Instructions
53
- - **ALWAYS** check the card folder for an existing preview file and any accompanying instructions or scripts, and reuse them if available.
56
+ - If preview of the card must be shown, **ALWAYS** check the card folder for an existing preview file and any accompanying instructions or scripts, and reuse them if available.
54
57
  * for example, in NodeJS-based projects, search the `package.json` file for `start` or similar script. If such is available, use it
55
58
  * also search in the `README.md` file.
56
59
  - If preview instructions are not available, you have to create an HTML page that contains a `ui-integration` card element which references the card manifest. Then serve the HTML page using `http` server.
57
60
 
58
61
  ## 5. Configuration Editor
59
- - When a Configuration Editor is available, make as many Integration Card fields editable as possible.
62
+ Configuration Editor allows different personas to customize Integration Cards without modifying the manifest file directly.
63
+ The following roles/personas are supported:
64
+ - Administrator
65
+ - Page/Content Administrator
66
+ - Translator
67
+
68
+ The Configuration Editor is implemented through two key components:
69
+
70
+ 1. **Definition file**: Create a `dt/Configuration.js` file that exports a Designtime definition object
71
+ 2. **Manifest reference**: Reference this definition in the `manifest.json` under the `sap.card/configuration/editor` property
72
+
73
+ The `dt/Configuration.js` file defines the Configuration Editor's structure by specifying:
74
+ - Form layout and field definitions
75
+ - Input controls and visualizations
76
+ - Validation rules and field relationships
77
+ - Grouping and organization of configuration options
78
+
79
+ When creating or modifying Integration Cards, follow these guidelines for Configuration Editors:
80
+ - Assume the role of Administrator persona when designing the Configuration Editor.
81
+ - **ALWAYS** ensure that the Configuration Editor reflects the current structure and fields of the `manifest.json`.
82
+ - **ALWAYS** make the existing fields in the `manifest.json` configurable via the editor. For example manifest parameters, title, subtitle, icon of the header, etc.
83
+ - **NEVER** add fields to the editor that do not exist in the `manifest.json`.
84
+ - **ALWAYS** remove fields from the editor when removing them from the `manifest.json`.
85
+ - **ALWAYS** add fields in the Configuration Editor when adding them to the `manifest.json`.
86
+
87
+ ### 5.1 Example:
88
+ `manifest.json` file:
89
+ ```json
90
+ {
91
+ "sap.app": {
92
+ "id": "test.editor",
93
+ "type": "card",
94
+ "title": "Test Card",
95
+ "applicationVersion": {
96
+ "version": "1.0.0"
97
+ }
98
+ },
99
+ "sap.ui": {
100
+ "technology": "UI5"
101
+ },
102
+ "sap.card": {
103
+ "type": "List",
104
+ "configuration": {
105
+ "editor": "./dt/Configuration",
106
+ "parameters": {
107
+ "cardTitle": {
108
+ "value": "Customers"
109
+ },
110
+ "icon": {
111
+ "value": "sap-icon://account"
112
+ },
113
+ "maxItems": {
114
+ "value": 3
115
+ },
116
+ "showDescription": {
117
+ "value": true
118
+ },
119
+ "dateContext": {
120
+ "value": "2020-09-02"
121
+ },
122
+ "Customers": {
123
+ "value": ["ALFKI"]
124
+ },
125
+ "northwindDestination": {
126
+ "value": "northwind"
127
+ }
128
+ },
129
+ "destinations": {
130
+ "northwind": {
131
+ "name": "Northwind_V4",
132
+ "defaultUrl": "https://services.odata.org/V4/Northwind/Northwind.svc"
133
+ }
134
+ }
135
+ },
136
+ "data": {
137
+ "request": {
138
+ "url": "{{destinations.northwind}}/Customers",
139
+ "parameters": {
140
+ "$select": "CustomerID,CompanyName,ContactName",
141
+ "$top": "{parameters>/maxItems/value}"
142
+ }
143
+ }
144
+ },
145
+ "header": {
146
+ "title": "{parameters>/cardTitle/value}",
147
+ "subtitle": "As of {parameters>/dateContext/value}",
148
+ "icon": {
149
+ "src": "{parameters>/icon/value}",
150
+ "shape": "Circle"
151
+ }
152
+ },
153
+ "content": {
154
+ "data": {
155
+ "path": "/value"
156
+ },
157
+ "item": {
158
+ "title": "{CompanyName}",
159
+ "description": "{= ${parameters>/showDescription/value} ? ${ContactName} : '' }"
160
+ },
161
+ "maxItems": "{parameters>/maxItems/value}"
162
+ }
163
+ }
164
+ }
165
+ ```
166
+
167
+ `dt/Configuration.js` file:
168
+ ```javascript
169
+ sap.ui.define(["sap/ui/integration/Designtime"], function (Designtime) {
170
+ "use strict";
171
+
172
+ return function () {
173
+ return new Designtime({
174
+ form: {
175
+ items: {
176
+
177
+ /* =======================
178
+ General
179
+ ======================= */
180
+ generalGroup: {
181
+ type: "group",
182
+ label: "General"
183
+ },
184
+
185
+ cardTitle: {
186
+ manifestpath: "/sap.card/configuration/parameters/cardTitle/value",
187
+ type: "string",
188
+ label: "Card Title",
189
+ translatable: true,
190
+ required: true,
191
+ allowDynamicValues: true
192
+ },
193
+
194
+ icon: {
195
+ manifestpath: "/sap.card/header/icon/src",
196
+ type: "string",
197
+ label: "Icon",
198
+ visualization: {
199
+ type: "IconSelect",
200
+ settings: {
201
+ value: "{currentSettings>value}",
202
+ editable: "{currentSettings>editable}"
203
+ }
204
+ }
205
+ },
206
+
207
+ iconShape: {
208
+ manifestpath: "/sap.card/header/icon/shape",
209
+ type: "string",
210
+ label: "Icon Shape",
211
+ visualization: {
212
+ type: "ShapeSelect",
213
+ settings: {
214
+ value: "{currentSettings>value}",
215
+ editable: "{currentSettings>editable}"
216
+ }
217
+ },
218
+ cols: 1
219
+ },
220
+
221
+ iconBackground: {
222
+ manifestpath: "/sap.card/header/icon/backgroundColor",
223
+ type: "string",
224
+ label: "Icon Background",
225
+ visualization: {
226
+ type: "ColorSelect",
227
+ settings: {
228
+ enumValue: "{currentSettings>value}",
229
+ editable: "{currentSettings>editable}"
230
+ }
231
+ },
232
+ cols: 1
233
+ },
234
+
235
+ /* =======================
236
+ Data & Behavior
237
+ ======================= */
238
+ dataGroup: {
239
+ type: "group",
240
+ label: "Data & Behavior"
241
+ },
242
+
243
+ maxItems: {
244
+ manifestpath: "/sap.card/configuration/parameters/maxItems/value",
245
+ type: "integer",
246
+ label: "Maximum Items",
247
+ visualization: {
248
+ type: "Slider",
249
+ settings: {
250
+ value: "{currentSettings>value}",
251
+ min: 1,
252
+ max: 10,
253
+ width: "100%",
254
+ enabled: "{currentSettings>editable}"
255
+ }
256
+ }
257
+ },
258
+
259
+ showDescription: {
260
+ manifestpath: "/sap.card/configuration/parameters/showDescription/value",
261
+ type: "boolean",
262
+ label: "Show Contact Name",
263
+ visualization: {
264
+ type: "Switch",
265
+ settings: {
266
+ state: "{currentSettings>value}",
267
+ customTextOn: "Show",
268
+ customTextOff: "Hide",
269
+ enabled: "{currentSettings>editable}"
270
+ }
271
+ }
272
+ },
273
+
274
+ dateContext: {
275
+ manifestpath: "/sap.card/configuration/parameters/dateContext/value",
276
+ type: "date",
277
+ label: "Date Context"
278
+ },
279
+
280
+ /* =======================
281
+ Filtering
282
+ ======================= */
283
+ filterGroup: {
284
+ type: "group",
285
+ label: "Customer Filter"
286
+ },
287
+
288
+ CustomerID: {
289
+ manifestpath: "/sap.card/configuration/parameters/CustomerID/value",
290
+ type: "string",
291
+ label: "Customer ID",
292
+ values: {
293
+ data: {
294
+ request: {
295
+ url: "{{destinations.northwind}}/Customers",
296
+ parameters: {
297
+ "$select": "CustomerID,CompanyName"
298
+ }
299
+ },
300
+ path: "/value"
301
+ },
302
+ item: {
303
+ key: "{CustomerID}",
304
+ text: "{CompanyName}"
305
+ }
306
+ }
307
+ }
308
+ }
309
+ },
310
+ preview: {
311
+ modes: "None"
312
+ }
313
+ });
314
+ };
315
+ });
316
+
317
+ ```
60
318
 
61
319
  ## 6. Analytical Cards Coding Guidelines
62
320
  - **ALWAYS** set `sap.card/content/chartType` property.
@@ -19,6 +19,16 @@
19
19
  "sap.card": {
20
20
  "type": "<%= cardType %>",
21
21
  "configuration": {
22
+ <% if (destinations && destinations.length > 0) { %>
23
+ "destinations": {
24
+ <% destinations.forEach(function(destination, index) { %>
25
+ "<%= destination.name %>": {
26
+ "name": "<%= destination.name %>",
27
+ "defaultUrl": "<%= destination.defaultUrl %>"
28
+ }<%= index < destinations.length - 1 ? ',' : '' %>
29
+ <% }); %>
30
+ },
31
+ <% } %>
22
32
  "editor": "./dt/Configuration"
23
33
  },
24
34
  <% if (cardType === "Analytical") { %>
@@ -7,13 +7,20 @@ sap.ui.define(["sap/ui/integration/Host"], async (Host) => {
7
7
  const card = document.getElementById("card");
8
8
  const applyChangesBtn = document.getElementById("applyChangesBtn");
9
9
  const resetBtn = document.getElementById("resetBtn");
10
+ const destinations = {
11
+ <%_ if (destinations && destinations.length > 0) { -%>
12
+ <%_ destinations.forEach(function(destination, index) { -%>
13
+ "<%= destination.name %>": "<%= destination.defaultUrl %>"<%= index < destinations.length - 1 ? ',' : '' %>
14
+ <%_ }); -%>
15
+ <%_ } -%>
16
+ };
10
17
  const host = new Host({
11
- resolveDestination: function(sDestinationName) {
12
- if (sDestinationName === "Northwind") {
13
- return "https://services.odata.org/V4/Northwind/Northwind.svc/";
18
+ resolveDestination: function(destinationName) {
19
+ if (destinations[destinationName]) {
20
+ return destinations[destinationName];
14
21
  }
15
22
 
16
- throw new Error("Destination " + sDestinationName + " not found!");
23
+ return Promise.reject("Destination " + destinationName + " not found!");
17
24
  },
18
25
  actions: [
19
26
  {
@@ -27,6 +34,15 @@ sap.ui.define(["sap/ui/integration/Host"], async (Host) => {
27
34
  ]
28
35
  });
29
36
 
37
+ // Called by the Configuration Editor to show a list of available destinations
38
+ host.getDestinations = function() {
39
+ return Promise.resolve(Object.entries(destinations).map(([name, url]) => {
40
+ return {
41
+ name,
42
+ };
43
+ }));
44
+ };
45
+
30
46
  card.host = host.getId();
31
47
  card.manifest = "../card/manifest.json";
32
48
 
@@ -17,6 +17,10 @@ body {
17
17
  flex-direction: column;
18
18
  }
19
19
 
20
+ #editorSection {
21
+ --sapUiIntegrationEditorFormHeight: auto;
22
+ }
23
+
20
24
  .button-container {
21
25
  display: flex;
22
26
  justify-content: flex-end;
@@ -23,9 +23,7 @@
23
23
  <div class="card-section">
24
24
  <h2>Integration Card</h2>
25
25
  <ui-integration-card
26
- id="card"
27
- width="300px"
28
- height="400px">
26
+ id="card">
29
27
  </ui-integration-card>
30
28
  </div>
31
29
  <div id="editorSection"
@@ -18,7 +18,11 @@
18
18
  "odataVersion": "4.0"
19
19
  }
20
20
  }
21
- }<% } %>
21
+ }<% } %>,
22
+ "sourceTemplate": {
23
+ "id": "@ui5/mcp-server:js",
24
+ "version": "<%= mcpServerVersion %>"
25
+ }
22
26
  },
23
27
 
24
28
  "sap.ui": {
@@ -18,7 +18,11 @@
18
18
  "odataVersion": "4.0"
19
19
  }
20
20
  }
21
- }<% } %>
21
+ }<% } %>,
22
+ "sourceTemplate": {
23
+ "id": "@ui5/mcp-server:ts",
24
+ "version": "<%= mcpServerVersion %>"
25
+ }
22
26
  },
23
27
 
24
28
  "sap.ui": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"isValidUrl.js","sourceRoot":"","sources":["../../../src/tools/create_ui5_app/isValidUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,iBAAiB,EAAC,MAAM,gBAAgB,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CACjC,SAAiB,EACjB,kBAA4B,EAAE,EAC9B,oBAA8B,CAAC,MAAM,EAAE,OAAO,CAAC;IAE/C,IAAI,GAAQ,CAAC;IAEb,sDAAsD;IACtD,IAAI,CAAC;QACJ,GAAG,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,IAAI,EAAE,CAAC;QACf,gEAAgE;QAChE,OAAO,KAAK,CAAC;IACd,CAAC;IAED,4BAA4B;IAC5B,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,+DAA+D;QAC/D,uCAAuC;QACvC,MAAM,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACd,CAAC;IACF,CAAC;IAED,mCAAmC;IACnC,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;QAE9B,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,EAAE;YAC9D,+CAA+C;YAC/C,IAAI,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACnC,2DAA2D;gBAC3D,mDAAmD;gBACnD,uDAAuD;gBACvD,OAAO,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YACzC,CAAC;YAED,qBAAqB;YACrB,OAAO,QAAQ,KAAK,aAAa,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,EAAE,CAAC;YACtB,MAAM,IAAI,iBAAiB,CAC1B,WAAW,QAAQ,0CAA0C,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ;gBAC/F,qGAAqG,CAAC,CAAC;QACzG,CAAC;IACF,CAAC;IAED,wCAAwC;IACxC,OAAO,IAAI,CAAC;AACb,CAAC;AAAA,CAAC"}