roku-mcp 1.3.2 → 1.4.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.
package/README.md CHANGED
@@ -197,6 +197,18 @@ Or simply add the two expected variables to your `.env` alongside your existing
197
197
  | `roku_console_send` | Send a command to the debug console and auto-disconnect |
198
198
  | `roku_console_disconnect` | Close the console connection (safety net) |
199
199
 
200
+ ### BrightScript Profiler
201
+
202
+ Analyze `.bsprof` files generated by Roku devices. These tools use [bsprof-cli](https://www.npmjs.com/package/bsprof-cli) to parse the binary profiler format and return structured JSON reports.
203
+
204
+ | Tool | Description |
205
+ |---|---|
206
+ | `analyze_bsprof` | Analyze a .bsprof file — memory leaks, CPU hot paths, full report, or summary. Supports filtering by module/file and sorting options. |
207
+ | `compare_bsprof` | Compare two .bsprof profiles to detect regressions, improvements, new leaks, and resolved leaks. |
208
+ | `bsprof_info` | Get header metadata (target name, device, firmware, format version, features) without full parsing. |
209
+
210
+ To generate a `.bsprof` file, enable the profiler in your Roku app's `manifest` (`bs_prof_enabled=true`), run the app, and download the profile from `http://<device-ip>:8080`.
211
+
200
212
  ## Requirements
201
213
 
202
214
  - Node.js 18+
package/dist/index.d.ts CHANGED
@@ -1,3 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
  import 'dotenv/config';
3
+ export default function createServer(_options?: {
4
+ config?: Record<string, string>;
5
+ }): import("@modelcontextprotocol/sdk/server").Server<{
6
+ method: string;
7
+ params?: {
8
+ [x: string]: unknown;
9
+ _meta?: {
10
+ [x: string]: unknown;
11
+ progressToken?: string | number | undefined;
12
+ "io.modelcontextprotocol/related-task"?: {
13
+ taskId: string;
14
+ } | undefined;
15
+ } | undefined;
16
+ } | undefined;
17
+ }, {
18
+ method: string;
19
+ params?: {
20
+ [x: string]: unknown;
21
+ _meta?: {
22
+ [x: string]: unknown;
23
+ progressToken?: string | number | undefined;
24
+ "io.modelcontextprotocol/related-task"?: {
25
+ taskId: string;
26
+ } | undefined;
27
+ } | undefined;
28
+ } | undefined;
29
+ }, {
30
+ [x: string]: unknown;
31
+ _meta?: {
32
+ [x: string]: unknown;
33
+ progressToken?: string | number | undefined;
34
+ "io.modelcontextprotocol/related-task"?: {
35
+ taskId: string;
36
+ } | undefined;
37
+ } | undefined;
38
+ }>;
3
39
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC;AAQvB,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,QAAQ,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAalF"}
package/dist/index.js CHANGED
@@ -1,19 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
  import 'dotenv/config';
3
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
4
  import { registerDeployTools } from './tools/deploy.js';
6
5
  import { registerEcpTools } from './tools/ecp.js';
7
6
  import { registerScreenshotTools } from './tools/screenshot.js';
8
7
  import { registerConsoleTools } from './tools/console.js';
9
- const server = new McpServer({
10
- name: 'roku-mcp',
11
- version: '1.3.2',
12
- });
13
- registerDeployTools(server);
14
- registerEcpTools(server);
15
- registerScreenshotTools(server);
16
- registerConsoleTools(server);
17
- const transport = new StdioServerTransport();
18
- await server.connect(transport);
8
+ import { registerBsprofTools } from './tools/bsprof.js';
9
+ export default function createServer(_options) {
10
+ const server = new McpServer({
11
+ name: 'roku-mcp',
12
+ version: '1.4.0',
13
+ });
14
+ registerDeployTools(server);
15
+ registerEcpTools(server);
16
+ registerScreenshotTools(server);
17
+ registerConsoleTools(server);
18
+ registerBsprofTools(server);
19
+ return server.server;
20
+ }
21
+ const isDirectRun = typeof process !== 'undefined' &&
22
+ process.argv[1] &&
23
+ (process.argv[1].endsWith('/index.js') || process.argv[1].endsWith('/roku-mcp'));
24
+ if (isDirectRun) {
25
+ (async () => {
26
+ const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
27
+ const server = new McpServer({
28
+ name: 'roku-mcp',
29
+ version: '1.4.0',
30
+ });
31
+ registerDeployTools(server);
32
+ registerEcpTools(server);
33
+ registerScreenshotTools(server);
34
+ registerConsoleTools(server);
35
+ registerBsprofTools(server);
36
+ const transport = new StdioServerTransport();
37
+ await server.connect(transport);
38
+ })();
39
+ }
19
40
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAE1D,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAChC,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,QAA8C;IACjF,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,UAAU;QAChB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACzB,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAChC,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC7B,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE5B,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED,MAAM,WAAW,GACf,OAAO,OAAO,KAAK,WAAW;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACf,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC;AAEnF,IAAI,WAAW,EAAE,CAAC;IAChB,CAAC,KAAK,IAAI,EAAE;QACV,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,2CAA2C,CAAC,CAAC;QAC3F,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;YAC3B,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,OAAO;SACjB,CAAC,CAAC;QAEH,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACzB,uBAAuB,CAAC,MAAM,CAAC,CAAC;QAChC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC7B,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAE5B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC,CAAC,EAAE,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare function registerBsprofTools(server: McpServer): void;
3
+ //# sourceMappingURL=bsprof.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bsprof.d.ts","sourceRoot":"","sources":["../../src/tools/bsprof.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAsCpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6I3D"}
@@ -0,0 +1,140 @@
1
+ import { z } from 'zod';
2
+ import { readFileSync } from 'fs';
3
+ import { parseBsprof, analyzeMemory, analyzeCpu, compareBsprof, buildHeaderInfo, buildParseStats, aggregate, rankFunctions, } from 'bsprof-cli';
4
+ import { friendlyError } from '../roku-config.js';
5
+ function jsonify(value) {
6
+ return JSON.stringify(value, (_k, v) => (typeof v === 'bigint' ? Number(v) : v), 2);
7
+ }
8
+ function buildOptions(params) {
9
+ return {
10
+ top: params.top ?? 30,
11
+ sortBy: params.sortBy,
12
+ filterModule: params.filterModule,
13
+ excludeModule: params.excludeModule,
14
+ filterFile: params.filterFile,
15
+ threshold: params.threshold ?? 0,
16
+ };
17
+ }
18
+ export function registerBsprofTools(server) {
19
+ server.registerTool('analyze_bsprof', {
20
+ description: 'Analyze a BrightScript Profiler (.bsprof) file from a Roku device. Supports memory leak detection, CPU hot-path analysis, combined full reports, and one-page summaries. Returns structured JSON.',
21
+ inputSchema: {
22
+ filePath: z.string().describe('Absolute path to the .bsprof file'),
23
+ mode: z
24
+ .enum(['memory', 'cpu', 'full', 'summary'])
25
+ .describe('Analysis mode: memory (retained bytes, leaks), cpu (self time, hot functions), full (both), summary (key metrics overview)'),
26
+ top: z.number().optional().describe('Number of entries in ranked lists (default 30)'),
27
+ sortBy: z
28
+ .string()
29
+ .optional()
30
+ .describe('Sort field: retained, allocated, allocCount, cpuSelf, wallSelf, callCount'),
31
+ filterModule: z.string().optional().describe('Filter results to a specific module/thread'),
32
+ excludeModule: z.string().optional().describe('Exclude a module (e.g. roku_ads_lib)'),
33
+ filterFile: z.string().optional().describe('Glob pattern for file filtering'),
34
+ threshold: z
35
+ .number()
36
+ .optional()
37
+ .describe('Only show entries exceeding this value (bytes for memory, microseconds for CPU)'),
38
+ },
39
+ }, async (params) => {
40
+ try {
41
+ const buffer = readFileSync(params.filePath);
42
+ const profile = parseBsprof(buffer);
43
+ const options = buildOptions(params);
44
+ let report;
45
+ switch (params.mode) {
46
+ case 'memory':
47
+ report = analyzeMemory(profile, options);
48
+ break;
49
+ case 'cpu':
50
+ report = analyzeCpu(profile, options);
51
+ break;
52
+ case 'full': {
53
+ const memory = analyzeMemory(profile, options);
54
+ const cpu = analyzeCpu(profile, options);
55
+ const fullReport = { header: memory.header, memory, cpu };
56
+ report = fullReport;
57
+ break;
58
+ }
59
+ case 'summary': {
60
+ const header = buildHeaderInfo(profile);
61
+ const parseStats = buildParseStats(profile);
62
+ const agg = aggregate(profile, options);
63
+ const allFuncs = [...agg.byFunction.values()];
64
+ const summaryReport = {
65
+ header,
66
+ parseStats,
67
+ topMemoryLeaks: rankFunctions(allFuncs, 'retained', options.top),
68
+ topCpuConsumers: rankFunctions(allFuncs, 'cpuSelf', options.top),
69
+ moduleOverview: [...agg.byModule.values()],
70
+ };
71
+ report = summaryReport;
72
+ break;
73
+ }
74
+ }
75
+ return {
76
+ content: [{ type: 'text', text: jsonify(report) }],
77
+ };
78
+ }
79
+ catch (error) {
80
+ return {
81
+ content: [{ type: 'text', text: `Analysis failed: ${friendlyError(error)}` }],
82
+ isError: true,
83
+ };
84
+ }
85
+ });
86
+ server.registerTool('compare_bsprof', {
87
+ description: 'Compare two BrightScript Profiler (.bsprof) files to detect regressions, improvements, new memory leaks, resolved leaks, and CPU time deltas between runs.',
88
+ inputSchema: {
89
+ beforePath: z.string().describe('Absolute path to the "before" .bsprof file'),
90
+ afterPath: z.string().describe('Absolute path to the "after" .bsprof file'),
91
+ top: z.number().optional().describe('Number of entries in ranked lists (default 30)'),
92
+ filterModule: z.string().optional().describe('Filter results to a specific module/thread'),
93
+ excludeModule: z.string().optional().describe('Exclude a module (e.g. roku_ads_lib)'),
94
+ threshold: z
95
+ .number()
96
+ .optional()
97
+ .describe('Only show deltas exceeding this value (bytes or microseconds)'),
98
+ },
99
+ }, async (params) => {
100
+ try {
101
+ const beforeBuf = readFileSync(params.beforePath);
102
+ const afterBuf = readFileSync(params.afterPath);
103
+ const before = parseBsprof(beforeBuf);
104
+ const after = parseBsprof(afterBuf);
105
+ const options = buildOptions(params);
106
+ const diff = compareBsprof(before, after, params.beforePath, params.afterPath, options);
107
+ return {
108
+ content: [{ type: 'text', text: jsonify(diff) }],
109
+ };
110
+ }
111
+ catch (error) {
112
+ return {
113
+ content: [{ type: 'text', text: `Comparison failed: ${friendlyError(error)}` }],
114
+ isError: true,
115
+ };
116
+ }
117
+ });
118
+ server.registerTool('bsprof_info', {
119
+ description: 'Get header metadata from a .bsprof file without full analysis — target name, device model, firmware, format version, duration, file size, and enabled features.',
120
+ inputSchema: {
121
+ filePath: z.string().describe('Absolute path to the .bsprof file'),
122
+ },
123
+ }, async (params) => {
124
+ try {
125
+ const buffer = readFileSync(params.filePath);
126
+ const profile = parseBsprof(buffer);
127
+ const info = buildHeaderInfo(profile);
128
+ return {
129
+ content: [{ type: 'text', text: jsonify(info) }],
130
+ };
131
+ }
132
+ catch (error) {
133
+ return {
134
+ content: [{ type: 'text', text: `Info failed: ${friendlyError(error)}` }],
135
+ isError: true,
136
+ };
137
+ }
138
+ });
139
+ }
140
+ //# sourceMappingURL=bsprof.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bsprof.js","sourceRoot":"","sources":["../../src/tools/bsprof.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "roku-mcp",
3
- "version": "1.3.2",
4
- "description": "MCP server for Roku device automation — deploy, ECP control, screenshots, and debug console",
3
+ "version": "1.4.0",
4
+ "description": "MCP server for Roku device automation — deploy, ECP control, screenshots, debug console, and BrightScript profiler analysis",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
+ "module": "src/index.ts",
7
8
  "bin": {
8
9
  "roku-mcp": "dist/index.js"
9
10
  },
@@ -40,6 +41,7 @@
40
41
  "dependencies": {
41
42
  "@modelcontextprotocol/sdk": "^1.28.0",
42
43
  "axios": "^1.13.6",
44
+ "bsprof-cli": "^1.0.0",
43
45
  "dotenv": "^17.3.1",
44
46
  "fast-xml-parser": "^5.5.9",
45
47
  "roku-deploy": "^3.16.3",