@sisense/mcp-server 0.2.1

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 (37) hide show
  1. package/LICENSE.md +35 -0
  2. package/README.md +121 -0
  3. package/dist/ai-hspmgr2c.js +3148 -0
  4. package/dist/fileFromPath-s6ap5vrh.js +128 -0
  5. package/dist/index-29n08mw7.js +95 -0
  6. package/dist/index-atgbxy7h.js +98603 -0
  7. package/dist/index-d6843g0v.js +372 -0
  8. package/dist/index-dcrjg3fk.js +207 -0
  9. package/dist/index-dxfb3krz.js +1489 -0
  10. package/dist/index-er0yspcy.js +918 -0
  11. package/dist/index-g8bgq79c.js +53 -0
  12. package/dist/index-p1pxtmwn.js +162 -0
  13. package/dist/index-qdth51hx.js +250 -0
  14. package/dist/index-tqba2rwh.js +603 -0
  15. package/dist/index-vrapm0b4.js +765 -0
  16. package/dist/index-vx54d05h.js +475 -0
  17. package/dist/sse-server-3343e7xh.js +117 -0
  18. package/dist/sse-server-36t17nga.js +12127 -0
  19. package/dist/sse-server-3e0efmg2.js +6276 -0
  20. package/dist/sse-server-4b60tg0c.js +136 -0
  21. package/dist/sse-server-4g9za0qq.js +89 -0
  22. package/dist/sse-server-4jjec4fz.js +9753 -0
  23. package/dist/sse-server-5tmgacdx.js +62 -0
  24. package/dist/sse-server-7wcvyxyj.js +31 -0
  25. package/dist/sse-server-brx9qtyd.js +2131 -0
  26. package/dist/sse-server-epd916s3.js +167 -0
  27. package/dist/sse-server-gt7tx6n2.js +2240 -0
  28. package/dist/sse-server-mkesh468.js +53 -0
  29. package/dist/sse-server-nwjjjz6x.js +113 -0
  30. package/dist/sse-server-qj4zxq0f.js +267 -0
  31. package/dist/sse-server-rr3dp62e.js +116721 -0
  32. package/dist/sse-server-ss0mydv4.js +3980 -0
  33. package/dist/sse-server-txz5g5t0.js +5328 -0
  34. package/dist/sse-server.js +30432 -0
  35. package/dist/view.html +3016 -0
  36. package/dist/widget-renderer-66ws3xtk.js +312 -0
  37. package/package.json +82 -0
@@ -0,0 +1,312 @@
1
+ import {
2
+ require_dist_cjs as require_dist_cjs2,
3
+ sanitizeError,
4
+ toKebabCase
5
+ } from "./sse-server-36t17nga.js";
6
+ import {
7
+ require_dist_cjs
8
+ } from "./index-p1pxtmwn.js";
9
+ import"./index-er0yspcy.js";
10
+ import {
11
+ Fs
12
+ } from "./sse-server-brx9qtyd.js";
13
+ import"./sse-server-3e0efmg2.js";
14
+ import"./sse-server-4b60tg0c.js";
15
+ import"./sse-server-4jjec4fz.js";
16
+ import"./sse-server-nwjjjz6x.js";
17
+ import"./sse-server-qj4zxq0f.js";
18
+ import"./sse-server-txz5g5t0.js";
19
+ import"./sse-server-epd916s3.js";
20
+ import"./sse-server-5tmgacdx.js";
21
+ import"./sse-server-4g9za0qq.js";
22
+ import"./index-g8bgq79c.js";
23
+ import"./sse-server-mkesh468.js";
24
+ import"./sse-server-3343e7xh.js";
25
+ import {
26
+ __toESM
27
+ } from "./sse-server-7wcvyxyj.js";
28
+
29
+ // src/utils/widget-renderer/widget-renderer.ts
30
+ var import_client_s3 = __toESM(require_dist_cjs2(), 1);
31
+ var import_credential_provider_web_identity = __toESM(require_dist_cjs(), 1);
32
+ import { readFileSync } from "node:fs";
33
+ import { basename } from "node:path";
34
+
35
+ // src/utils/widget-renderer/widget-ct-runner.ts
36
+ import { spawn } from "node:child_process";
37
+ import { writeFileSync, mkdirSync, existsSync } from "node:fs";
38
+ import { join, dirname } from "node:path";
39
+ import { tmpdir } from "node:os";
40
+ import { randomBytes } from "node:crypto";
41
+ import { fileURLToPath } from "node:url";
42
+ var __filename2 = fileURLToPath(import.meta.url);
43
+ var __dirname2 = dirname(__filename2);
44
+ function getProjectRoot() {
45
+ const cwd = process.cwd();
46
+ if (existsSync(join(cwd, "playwright-ct.config.ts"))) {
47
+ return cwd;
48
+ }
49
+ const relativePath = join(__dirname2, "..", "..", "..");
50
+ if (existsSync(join(relativePath, "playwright-ct.config.ts"))) {
51
+ return relativePath;
52
+ }
53
+ return cwd;
54
+ }
55
+ var PROJECT_ROOT = getProjectRoot();
56
+ async function renderChartWidgetWithPlaywrightCT(config) {
57
+ const startTime = Date.now();
58
+ const width = config.width || 1000;
59
+ const height = config.height || 600;
60
+ let screenshotPath = "";
61
+ try {
62
+ const testId = randomBytes(8).toString("hex");
63
+ const testDir = join(tmpdir(), `widget-ct-${testId}`);
64
+ mkdirSync(testDir, { recursive: true });
65
+ const configPath = join(testDir, "widget-config.json");
66
+ const configData = {
67
+ widgetProps: config.widgetProps,
68
+ sisenseContextProviderProps: config.sisenseContextProviderProps,
69
+ width,
70
+ height,
71
+ outputName: config.outputName
72
+ };
73
+ const serializedConfig = Fs.stringify(configData);
74
+ writeFileSync(configPath, serializedConfig, "utf8");
75
+ const screenshotsDir = join(PROJECT_ROOT, "__screenshots__");
76
+ mkdirSync(screenshotsDir, { recursive: true });
77
+ const chartTitleKebab = toKebabCase(config.outputName || "untitled-widget");
78
+ const timestamp = Date.now().toString();
79
+ const customFilename = `widget-${chartTitleKebab}-${timestamp}.png`;
80
+ screenshotPath = join(screenshotsDir, customFilename);
81
+ const testFilePath = join(PROJECT_ROOT, "src/utils/widget-renderer/widget-renderer.spec.tsx");
82
+ return await new Promise((resolve) => {
83
+ const renderStart = Date.now();
84
+ console.info("Starting Playwright CT", {
85
+ cwd: PROJECT_ROOT,
86
+ testFile: testFilePath,
87
+ configPath,
88
+ screenshotPath,
89
+ chromiumPath: process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH
90
+ });
91
+ const playwrightProcess = spawn("node", [
92
+ "./node_modules/.bin/playwright",
93
+ "test",
94
+ "--config=playwright-ct.config.ts",
95
+ testFilePath,
96
+ "--reporter=list"
97
+ ], {
98
+ cwd: PROJECT_ROOT,
99
+ env: {
100
+ ...process.env,
101
+ WIDGET_CONFIG_PATH: configPath,
102
+ SCREENSHOT_OUTPUT_PATH: screenshotPath
103
+ },
104
+ stdio: ["ignore", "pipe", "pipe"]
105
+ });
106
+ console.info("Playwright process spawned", { pid: playwrightProcess.pid });
107
+ let stdout = "";
108
+ let stderr = "";
109
+ playwrightProcess.stdout?.on("data", (data) => {
110
+ const chunk = data.toString();
111
+ stdout += chunk;
112
+ console.info("Playwright stdout:", chunk.trim());
113
+ });
114
+ playwrightProcess.stderr?.on("data", (data) => {
115
+ const chunk = data.toString();
116
+ stderr += chunk;
117
+ console.info("Playwright stderr:", chunk.trim());
118
+ });
119
+ const killTimeout = setTimeout(() => {
120
+ console.error("Playwright process timed out after 120s, killing...");
121
+ playwrightProcess.kill("SIGKILL");
122
+ }, 120000);
123
+ playwrightProcess.on("error", (err) => {
124
+ clearTimeout(killTimeout);
125
+ const totalMs = Date.now() - startTime;
126
+ resolve({
127
+ pngPath: screenshotPath,
128
+ success: false,
129
+ error: `Failed to spawn Playwright process: ${err.message}`,
130
+ timings: {
131
+ renderMs: 0,
132
+ totalMs
133
+ }
134
+ });
135
+ });
136
+ playwrightProcess.on("close", (code) => {
137
+ clearTimeout(killTimeout);
138
+ console.info("Playwright process exited", {
139
+ code,
140
+ stdoutLength: stdout.length,
141
+ stderrLength: stderr.length
142
+ });
143
+ const renderMs = Date.now() - renderStart;
144
+ const totalMs = Date.now() - startTime;
145
+ if (code === 0) {
146
+ resolve({
147
+ pngPath: screenshotPath,
148
+ success: true,
149
+ timings: {
150
+ renderMs,
151
+ totalMs
152
+ }
153
+ });
154
+ } else {
155
+ resolve({
156
+ pngPath: screenshotPath,
157
+ success: false,
158
+ error: stderr || stdout,
159
+ timings: {
160
+ renderMs,
161
+ totalMs
162
+ }
163
+ });
164
+ }
165
+ });
166
+ });
167
+ } catch (err) {
168
+ const totalMs = Date.now() - startTime;
169
+ return {
170
+ pngPath: screenshotPath,
171
+ success: false,
172
+ error: `Failed to create chart: ${err instanceof Error ? err.message : String(err)}`,
173
+ timings: {
174
+ renderMs: 0,
175
+ totalMs
176
+ }
177
+ };
178
+ }
179
+ }
180
+
181
+ // src/utils/widget-renderer/widget-renderer.ts
182
+ var s3Client;
183
+ function getS3Client() {
184
+ if (s3Client !== undefined) {
185
+ return s3Client;
186
+ }
187
+ if (!process.env.SCREENSHOTS_BUCKET) {
188
+ s3Client = null;
189
+ return null;
190
+ }
191
+ const region = process.env.AWS_REGION || "us-east-1";
192
+ if (process.env.AWS_WEB_IDENTITY_TOKEN_FILE) {
193
+ s3Client = new import_client_s3.S3Client({
194
+ region,
195
+ credentials: import_credential_provider_web_identity.fromTokenFile()
196
+ });
197
+ } else {
198
+ s3Client = new import_client_s3.S3Client({ region });
199
+ }
200
+ return s3Client;
201
+ }
202
+ async function renderChartWidget(args) {
203
+ const {
204
+ widgetProps,
205
+ width = 800,
206
+ height = 500,
207
+ outputName,
208
+ maxRetries = 2,
209
+ sisenseUrl,
210
+ sisenseToken,
211
+ baseUrl
212
+ } = args;
213
+ const sisenseContextProviderProps = {
214
+ url: sisenseUrl,
215
+ token: sisenseToken,
216
+ showRuntimeErrors: true
217
+ };
218
+ console.info("Rendering chart from WidgetProps", {
219
+ chartType: widgetProps.chartType,
220
+ title: widgetProps.title,
221
+ width,
222
+ height
223
+ });
224
+ let lastError = null;
225
+ for (let attempt = 0;attempt <= maxRetries; attempt++) {
226
+ try {
227
+ if (attempt > 0) {
228
+ console.info(`Retry attempt ${attempt}/${maxRetries}`);
229
+ }
230
+ const result = await renderChartWidgetWithPlaywrightCT({
231
+ widgetProps,
232
+ sisenseContextProviderProps,
233
+ width,
234
+ height,
235
+ outputName: outputName || widgetProps.title || "widget"
236
+ });
237
+ if (!result.success) {
238
+ throw new Error(result.error || "Widget rendering failed");
239
+ }
240
+ console.info("Reading generated widget image", {
241
+ path: result.pngPath
242
+ });
243
+ if (!result.pngPath) {
244
+ throw new Error("Widget rendering succeeded but no output path was returned");
245
+ }
246
+ const imageBuffer = readFileSync(result.pngPath);
247
+ const filename = basename(result.pngPath);
248
+ if (!filename) {
249
+ throw new Error(`Invalid screenshot path: ${result.pngPath}`);
250
+ }
251
+ const client = getS3Client();
252
+ if (client && process.env.SCREENSHOTS_BUCKET) {
253
+ const bucket = process.env.SCREENSHOTS_BUCKET;
254
+ try {
255
+ await client.send(new import_client_s3.PutObjectCommand({
256
+ Bucket: bucket,
257
+ Key: filename,
258
+ Body: imageBuffer,
259
+ ContentType: "image/png"
260
+ }));
261
+ console.info("Screenshot uploaded to S3", { bucket, filename });
262
+ } catch (s3Error) {
263
+ const sanitized2 = sanitizeError(s3Error);
264
+ console.error("Failed to upload screenshot to S3", {
265
+ bucket,
266
+ filename,
267
+ error: sanitized2.message
268
+ });
269
+ throw new Error(`S3 upload failed: ${sanitized2.message}`);
270
+ }
271
+ }
272
+ const publicUrl = `${baseUrl.replace(/\/$/, "")}/screenshots/${filename}`;
273
+ console.info("Widget rendered successfully", {
274
+ outputPath: result.pngPath,
275
+ imageSize: imageBuffer.length,
276
+ publicUrl,
277
+ timings: result.timings
278
+ });
279
+ const toolResult = {
280
+ content: [
281
+ {
282
+ type: "text",
283
+ text: publicUrl
284
+ }
285
+ ]
286
+ };
287
+ console.info(">>> CHART TOOL RESULT", {
288
+ contentCount: toolResult.content.length,
289
+ publicUrl
290
+ });
291
+ return toolResult;
292
+ } catch (error) {
293
+ lastError = error instanceof Error ? error : new Error(String(error));
294
+ if (attempt < maxRetries) {
295
+ const sanitized2 = sanitizeError(lastError);
296
+ console.warn(`Render attempt ${attempt + 1} failed, retrying...`, {
297
+ error: sanitized2.message
298
+ });
299
+ await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt)));
300
+ }
301
+ }
302
+ }
303
+ const sanitized = sanitizeError(lastError, false);
304
+ console.error("Failed to render widget after retries", {
305
+ attempts: maxRetries + 1,
306
+ error: sanitized.message
307
+ });
308
+ throw new Error(sanitized.message || "Widget rendering failed");
309
+ }
310
+ export {
311
+ renderChartWidget
312
+ };
package/package.json ADDED
@@ -0,0 +1,82 @@
1
+ {
2
+ "name": "@sisense/mcp-server",
3
+ "version": "0.2.1",
4
+ "mcpName": "io.github.sisense/mcp-server",
5
+ "homepage": "https://github.com/sisense/sisense-mcp-server#readme",
6
+ "description": "MCP server leveraging Sisense Intelligence for actionable insights and analytics.",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/sisense/sisense-mcp-server.git"
10
+ },
11
+ "keywords": [
12
+ "Sisense",
13
+ "Sisense Intelligence",
14
+ "MCP Server",
15
+ "Analytics"
16
+ ],
17
+ "author": "Sisense",
18
+ "license": "SEE LICENSE IN LICENSE.md",
19
+ "type": "module",
20
+ "main": "dist/sse-server.js",
21
+ "bin": {
22
+ "sisense-mcp-server": "dist/sse-server.js"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "README.md",
27
+ "LICENSE.md"
28
+ ],
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "scripts": {
33
+ "build": "cross-env INPUT=view.html vite build && bun build src/sse-server.ts --outdir dist --target node --format esm --splitting",
34
+ "build:view": "cross-env INPUT=view.html vite build",
35
+ "dev": "bun run --watch src/sse-server.ts",
36
+ "start": "bun run dist/sse-server.js",
37
+ "test": "bun test",
38
+ "test:e2e": "bun test e2e",
39
+ "lint": "eslint src/**/*.ts",
40
+ "type-check": "tsc --noEmit",
41
+ "format": "prettier --write \"src/**/*.{ts,tsx}\" \"e2e/**/*.{ts,tsx}\"",
42
+ "format:check": "prettier --check \"src/**/*.{ts,tsx}\" \"e2e/**/*.{ts,tsx}\"",
43
+ "postinstall": "playwright install chromium"
44
+ },
45
+ "dependencies": {
46
+ "@aws-sdk/client-s3": "^3.756.0",
47
+ "@aws-sdk/s3-request-presigner": "^3.756.0",
48
+ "@modelcontextprotocol/ext-apps": "1.0.1",
49
+ "@modelcontextprotocol/sdk": "1.26.0",
50
+ "@playwright/experimental-ct-react": "^1.56.1",
51
+ "@playwright/test": "^1.56.1",
52
+ "@sisense/sdk-ai-core": "0.5.1",
53
+ "@sisense/sdk-data": "2.20.0",
54
+ "@sisense/sdk-ui": "2.20.0",
55
+ "playwright": "^1.56.1",
56
+ "react": "^18.3.1",
57
+ "react-dom": "^18.3.1",
58
+ "zod": "^3.22.4"
59
+ },
60
+ "devDependencies": {
61
+ "@types/bun": "^1.0.0",
62
+ "@types/node": "^20.10.0",
63
+ "@vitejs/plugin-react": "^4.3.4",
64
+ "cross-env": "^7.0.3",
65
+ "@types/react": "^18.3.1",
66
+ "@types/react-dom": "^18.3.1",
67
+ "@typescript-eslint/eslint-plugin": "^6.13.0",
68
+ "@typescript-eslint/parser": "^6.13.0",
69
+ "eslint": "^8.54.0",
70
+ "prettier": "^3.0.0",
71
+ "typescript": "^5.3.3",
72
+ "vite": "^6.0.0",
73
+ "vite-plugin-singlefile": "^2.3.0"
74
+ },
75
+ "engines": {
76
+ "node": ">=18.0.0",
77
+ "bun": ">=1.0.0"
78
+ },
79
+ "bugs": {
80
+ "url": "https://github.com/sisense/sisense-mcp-server/issues"
81
+ }
82
+ }