@sap-ux/fiori-mcp-server 0.0.5 → 0.0.6

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/dist/server.d.ts CHANGED
@@ -14,6 +14,10 @@ export declare class FioriFunctionalityServer {
14
14
  * Logs MCP errors and handles the SIGINT signal for graceful shutdown.
15
15
  */
16
16
  private setupErrorHandling;
17
+ /**
18
+ * Sets up telemetry.
19
+ */
20
+ private setupTelemetry;
17
21
  /**
18
22
  * Sets up handlers for various MCP tools.
19
23
  * Configures handlers for listing tools, and calling specific Fiori functionality tools.
package/dist/server.js CHANGED
@@ -10,6 +10,7 @@ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
10
10
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
11
11
  const package_json_1 = __importDefault(require("../package.json"));
12
12
  const tools_1 = require("./tools");
13
+ const telemetry_1 = require("./telemetry");
13
14
  /**
14
15
  * Sets up and manages an MCP (Model Context Protocol) server that provides Fiori-related tools.
15
16
  */
@@ -42,6 +43,12 @@ class FioriFunctionalityServer {
42
43
  process.exit(0);
43
44
  });
44
45
  }
46
+ /**
47
+ * Sets up telemetry.
48
+ */
49
+ async setupTelemetry() {
50
+ await telemetry_1.TelemetryHelper.initTelemetrySettings();
51
+ }
45
52
  /**
46
53
  * Sets up handlers for various MCP tools.
47
54
  * Configures handlers for listing tools, and calling specific Fiori functionality tools.
@@ -56,22 +63,30 @@ class FioriFunctionalityServer {
56
63
  const { name, arguments: args } = request.params;
57
64
  try {
58
65
  let result;
66
+ telemetry_1.TelemetryHelper.markToolStartTime();
67
+ const telemetryProperties = {
68
+ tool: name,
69
+ functionalityId: args?.functionalityId
70
+ };
59
71
  switch (name) {
60
72
  case 'list-fiori-apps':
61
73
  result = await (0, tools_1.listFioriApps)(args);
62
- return this.convertResultToCallToolResult(result);
74
+ break;
63
75
  case 'list-functionality':
64
76
  result = await (0, tools_1.listFunctionalities)(args);
65
- return this.convertResultToCallToolResult(result);
77
+ break;
66
78
  case 'get-functionality-details':
67
79
  result = await (0, tools_1.getFunctionalityDetails)(args);
68
- return this.convertResultToCallToolResult(result);
80
+ break;
69
81
  case 'execute-functionality':
70
82
  result = await (0, tools_1.executeFunctionality)(args);
71
- return this.convertResultToCallToolResult(result);
83
+ break;
72
84
  default:
85
+ await telemetry_1.TelemetryHelper.sendTelemetry(telemetry_1.unknownTool, telemetryProperties, args?.appPath);
73
86
  throw new Error(`Unknown tool: ${name}. Try one of: list-fiori-apps, list-functionality, get-functionality-details, execute-functionality.`);
74
87
  }
88
+ await telemetry_1.TelemetryHelper.sendTelemetry(name, telemetryProperties, args?.appPath);
89
+ return this.convertResultToCallToolResult(result);
75
90
  }
76
91
  catch (error) {
77
92
  const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
@@ -113,6 +128,7 @@ class FioriFunctionalityServer {
113
128
  async run() {
114
129
  const transport = new stdio_js_1.StdioServerTransport();
115
130
  await this.server.connect(transport);
131
+ await this.setupTelemetry();
116
132
  console.error('Fiori Functionality MCP Server running on stdio');
117
133
  }
118
134
  }
@@ -0,0 +1,68 @@
1
+ import { type TelemetryProperties, type ToolsSuiteTelemetryInitSettings } from '@sap-ux/telemetry';
2
+ export declare const mcpServerName = "@sap-ux/fiori-mcp-server";
3
+ export declare const unknownTool = "unknown-tool";
4
+ export interface TelemetryData {
5
+ [key: string]: string;
6
+ }
7
+ /**
8
+ * Helper class for intialising and preparing event data for telemetry.
9
+ */
10
+ export declare abstract class TelemetryHelper {
11
+ private static _telemetryData;
12
+ private static _previousEventTimestamp;
13
+ /**
14
+ * Returns the telemetry data.
15
+ *
16
+ * @returns telemetry data
17
+ */
18
+ static get telemetryData(): TelemetryData;
19
+ /**
20
+ * Load telemetry settings.
21
+ *
22
+ * @param options - tools suite telemetry init settings
23
+ */
24
+ static initTelemetrySettings(options?: ToolsSuiteTelemetryInitSettings): Promise<void>;
25
+ /**
26
+ * Creates telemetry data and adds default telemetry props.
27
+ *
28
+ * @param additionalData - set additional properties to be reported by telemetry
29
+ * @param filterDups - filters duplicates by returning undefined if it's suspected to be a repeated event based on previous telemetry data & timestamp (1 second)
30
+ * @returns telemetry data
31
+ */
32
+ static createTelemetryData<T extends TelemetryProperties>(additionalData?: Partial<T>, filterDups?: boolean): TelemetryData | undefined;
33
+ /**
34
+ * Prepares the telemetry event by calculating the generation time if a mark name is provided.
35
+ *
36
+ * @param telemetryEventName - The name of the telemetry event
37
+ * @param telemetryData - The telemetry data
38
+ * @returns The prepared telemetry event
39
+ */
40
+ private static prepareTelemetryEvent;
41
+ /**
42
+ * Marks the start time. Example usage:
43
+ * At the start of the MCP tool calling phase.
44
+ * It should not be updated everytime calling createTelemetryData().
45
+ */
46
+ static markToolStartTime(): void;
47
+ /**
48
+ * Marks the end time. Example usage:
49
+ * At the end of the writing phase of the MCP tool calling phase.
50
+ */
51
+ static markToolsEndTime(): void;
52
+ /**
53
+ * Sends the telemetry event to the telemetry client.
54
+ *
55
+ * @param telemetryEventName - the event name to be reported
56
+ * @param telemetryData - the telemetry data
57
+ * @param appPath - the path of the application
58
+ * @returns - a promise that resolves when the event is sent
59
+ */
60
+ static sendTelemetry(telemetryEventName: string, telemetryData: TelemetryData, appPath?: string): Promise<void>;
61
+ /**
62
+ * Gets the telemetry name of the module.
63
+ *
64
+ * @returns The module telemetry name.
65
+ */
66
+ static getTelemetryName(): string;
67
+ }
68
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.TelemetryHelper = exports.unknownTool = exports.mcpServerName = void 0;
7
+ const telemetry_1 = require("@sap-ux/telemetry");
8
+ const feature_toggle_1 = require("@sap-ux/feature-toggle");
9
+ const btp_utils_1 = require("@sap-ux/btp-utils");
10
+ const os_name_1 = __importDefault(require("os-name"));
11
+ const i18next_1 = __importDefault(require("i18next"));
12
+ const package_json_1 = require("../../package.json");
13
+ exports.mcpServerName = '@sap-ux/fiori-mcp-server';
14
+ exports.unknownTool = 'unknown-tool';
15
+ const resourceId = '0a65e45d-6bf4-421d-b845-61e888c50e9e';
16
+ /**
17
+ * Helper class for intialising and preparing event data for telemetry.
18
+ */
19
+ class TelemetryHelper {
20
+ static _telemetryData;
21
+ static _previousEventTimestamp;
22
+ /**
23
+ * Returns the telemetry data.
24
+ *
25
+ * @returns telemetry data
26
+ */
27
+ static get telemetryData() {
28
+ return this._telemetryData;
29
+ }
30
+ /**
31
+ * Load telemetry settings.
32
+ *
33
+ * @param options - tools suite telemetry init settings
34
+ */
35
+ static async initTelemetrySettings(options) {
36
+ const telemetryOptions = {
37
+ consumerModule: {
38
+ name: exports.mcpServerName,
39
+ version: package_json_1.version
40
+ },
41
+ watchTelemetrySettingStore: false,
42
+ internalFeature: (0, feature_toggle_1.isInternalFeaturesSettingEnabled)(),
43
+ resourceId,
44
+ ...options
45
+ };
46
+ await (0, telemetry_1.initTelemetrySettings)(telemetryOptions);
47
+ }
48
+ /**
49
+ * Creates telemetry data and adds default telemetry props.
50
+ *
51
+ * @param additionalData - set additional properties to be reported by telemetry
52
+ * @param filterDups - filters duplicates by returning undefined if it's suspected to be a repeated event based on previous telemetry data & timestamp (1 second)
53
+ * @returns telemetry data
54
+ */
55
+ static createTelemetryData(additionalData, filterDups = false) {
56
+ const currentTimestamp = new Date().getTime();
57
+ if (!this._previousEventTimestamp) {
58
+ filterDups = false; // can't filter duplicates if no previous event timestamp
59
+ this._previousEventTimestamp = currentTimestamp;
60
+ }
61
+ if (!this._telemetryData) {
62
+ let osVersionName = i18next_1.default.t('telemetry.unknownOs');
63
+ try {
64
+ osVersionName = (0, os_name_1.default)();
65
+ }
66
+ catch {
67
+ // no matched os name, possible beta or unreleased version
68
+ }
69
+ this._telemetryData = {
70
+ Platform: (0, btp_utils_1.isAppStudio)() ? 'SBAS' : 'VSCode',
71
+ OperatingSystem: osVersionName
72
+ };
73
+ }
74
+ if (filterDups) {
75
+ const newTelemData = { ...this._telemetryData, ...additionalData };
76
+ if (Math.abs(this._previousEventTimestamp - currentTimestamp) < 1000 &&
77
+ JSON.stringify(newTelemData) === JSON.stringify(this._telemetryData)) {
78
+ return undefined;
79
+ }
80
+ }
81
+ this._previousEventTimestamp = currentTimestamp;
82
+ this._telemetryData = Object.assign(this._telemetryData, additionalData);
83
+ return this._telemetryData;
84
+ }
85
+ /**
86
+ * Prepares the telemetry event by calculating the generation time if a mark name is provided.
87
+ *
88
+ * @param telemetryEventName - The name of the telemetry event
89
+ * @param telemetryData - The telemetry data
90
+ * @returns The prepared telemetry event
91
+ */
92
+ static prepareTelemetryEvent(telemetryEventName, telemetryData) {
93
+ // Make sure performance measurement end is called
94
+ this.markToolsEndTime();
95
+ const requestTime = telemetryData.markName
96
+ ? telemetry_1.PerformanceMeasurementAPI.getMeasurementDuration(telemetryData.markName)
97
+ : undefined;
98
+ return {
99
+ eventName: telemetryEventName,
100
+ properties: telemetryData,
101
+ measurements: requestTime ? { RequestTime: requestTime } : {}
102
+ };
103
+ }
104
+ /**
105
+ * Marks the start time. Example usage:
106
+ * At the start of the MCP tool calling phase.
107
+ * It should not be updated everytime calling createTelemetryData().
108
+ */
109
+ static markToolStartTime() {
110
+ this.createTelemetryData({
111
+ markName: telemetry_1.PerformanceMeasurementAPI.startMark('MCP_LOADING_TIME')
112
+ });
113
+ }
114
+ /**
115
+ * Marks the end time. Example usage:
116
+ * At the end of the writing phase of the MCP tool calling phase.
117
+ */
118
+ static markToolsEndTime() {
119
+ if (this._telemetryData?.markName) {
120
+ telemetry_1.PerformanceMeasurementAPI.endMark(this._telemetryData.markName);
121
+ telemetry_1.PerformanceMeasurementAPI.measure(this._telemetryData.markName);
122
+ }
123
+ }
124
+ /**
125
+ * Sends the telemetry event to the telemetry client.
126
+ *
127
+ * @param telemetryEventName - the event name to be reported
128
+ * @param telemetryData - the telemetry data
129
+ * @param appPath - the path of the application
130
+ * @returns - a promise that resolves when the event is sent
131
+ */
132
+ static async sendTelemetry(telemetryEventName, telemetryData, appPath) {
133
+ const telemetryEvent = this.prepareTelemetryEvent(telemetryEventName, telemetryData);
134
+ await telemetry_1.ClientFactory.getTelemetryClient().reportEvent(telemetryEvent, telemetry_1.SampleRate.NoSampling, appPath ? { appPath } : undefined);
135
+ }
136
+ /**
137
+ * Gets the telemetry name of the module.
138
+ *
139
+ * @returns The module telemetry name.
140
+ */
141
+ static getTelemetryName() {
142
+ return exports.mcpServerName;
143
+ }
144
+ }
145
+ exports.TelemetryHelper = TelemetryHelper;
146
+ //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sap-ux/fiori-mcp-server",
3
3
  "description": "SAP Fiori - Model Context Protocol (MCP) server",
4
- "version": "0.0.5",
4
+ "version": "0.0.6",
5
5
  "keywords": [
6
6
  "SAP Fiori tools",
7
7
  "SAP Fiori elements",
@@ -31,19 +31,23 @@
31
31
  "@types/json-schema": "7.0.5",
32
32
  "@types/mem-fs": "1.1.2",
33
33
  "@sap-ux/i18n": "0.3.3",
34
- "@sap-ux/text-document-utils": "0.3.1",
35
34
  "@sap-ux/odata-annotation-core-types": "0.4.5",
36
- "@sap-ux/odata-entity-model": "0.3.1"
35
+ "@sap-ux/odata-entity-model": "0.3.1",
36
+ "@sap-ux/text-document-utils": "0.3.1"
37
37
  },
38
38
  "dependencies": {
39
39
  "@modelcontextprotocol/sdk": "1.17.4",
40
- "@sap/ux-specification": "1.136.4",
41
40
  "@sap-ux/annotation-converter": "0.10.3",
41
+ "@sap/ux-specification": "1.136.4",
42
42
  "i18next": "25.3.0",
43
+ "os-name": "4.0.1",
43
44
  "zod": "4.1.5",
45
+ "@sap-ux/btp-utils": "1.1.1",
44
46
  "@sap-ux/fiori-annotation-api": "0.6.17",
45
47
  "@sap-ux/nodejs-utils": "0.2.3",
46
- "@sap-ux/project-access": "1.30.13"
48
+ "@sap-ux/project-access": "1.30.13",
49
+ "@sap-ux/feature-toggle": "0.3.1",
50
+ "@sap-ux/telemetry": "0.6.19"
47
51
  },
48
52
  "engines": {
49
53
  "node": ">=20.x"