@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 +4 -0
- package/dist/server.js +20 -4
- package/dist/telemetry/index.d.ts +68 -0
- package/dist/telemetry/index.js +146 -0
- package/package.json +9 -5
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
|
-
|
|
74
|
+
break;
|
|
63
75
|
case 'list-functionality':
|
|
64
76
|
result = await (0, tools_1.listFunctionalities)(args);
|
|
65
|
-
|
|
77
|
+
break;
|
|
66
78
|
case 'get-functionality-details':
|
|
67
79
|
result = await (0, tools_1.getFunctionalityDetails)(args);
|
|
68
|
-
|
|
80
|
+
break;
|
|
69
81
|
case 'execute-functionality':
|
|
70
82
|
result = await (0, tools_1.executeFunctionality)(args);
|
|
71
|
-
|
|
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.
|
|
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"
|