Skip to content

Commit bfdb501

Browse files
committed
chore: code review
1 parent 8f3e45d commit bfdb501

4 files changed

Lines changed: 22 additions & 63 deletions

File tree

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,10 @@ The Chrome DevTools MCP server supports the following configuration option:
495495
If enabled, ignores errors relative to self-signed and expired certificates. Use with caution.
496496
- **Type:** boolean
497497

498+
- **`--experimentalScreencast`/ `--experimental-screencast`**
499+
Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.
500+
- **Type:** boolean
501+
498502
- **`--chromeArg`/ `--chrome-arg`**
499503
Additional arguments for Chrome. Only applies when Chrome is launched by chrome-devtools-mcp.
500504
- **Type:** array

src/cli.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ export const cliOptions = {
175175
},
176176
experimentalScreencast: {
177177
type: 'boolean',
178-
describe: 'Whether to enable screencast tools',
179-
hidden: true,
178+
describe:
179+
'Exposes experimental screencast tools (requires ffmpeg). Install ffmpeg https://www.ffmpeg.org/download.html and ensure it is available in the MCP server PATH.',
180180
},
181181
chromeArg: {
182182
type: 'array',

src/tools/screencast.ts

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {zod} from '../third_party/index.js';
1212
import type {ScreenRecorder} from '../third_party/index.js';
1313

1414
import {ToolCategory} from './categories.js';
15-
import type {Context, Response} from './ToolDefinition.js';
1615
import {defineTool} from './ToolDefinition.js';
1716

1817
async function generateTempFilePath(): Promise<string> {
@@ -23,7 +22,7 @@ async function generateTempFilePath(): Promise<string> {
2322
export const startScreencast = defineTool({
2423
name: 'screencast_start',
2524
description:
26-
'Starts recording a screencast (video) of the selected page in mp4 format. Requires ffmpeg to be installed on the system.',
25+
'Starts recording a screencast (video) of the selected page in mp4 format.',
2726
annotations: {
2827
category: ToolCategory.DEBUGGING,
2928
readOnlyHint: false,
@@ -70,7 +69,7 @@ export const startScreencast = defineTool({
7069
context.setScreenRecorder({recorder, filePath: resolvedPath});
7170

7271
response.appendResponseLine(
73-
`Screencast recording started. The recording will be saved to ${resolvedPath}. Use screencast_stop to stop recording.`,
72+
`Screencast recording started. The recording will be saved to ${resolvedPath}. Use ${stopScreencast.name} to stop recording.`,
7473
);
7574
},
7675
});
@@ -85,24 +84,17 @@ export const stopScreencast = defineTool({
8584
},
8685
schema: {},
8786
handler: async (_request, response, context) => {
88-
await stopScreencastAndAppendOutput(response, context);
87+
const data = context.getScreenRecorder();
88+
if (!data) {
89+
return;
90+
}
91+
try {
92+
await data.recorder.stop();
93+
response.appendResponseLine(
94+
`The screencast recording has been stopped and saved to ${data.filePath}.`,
95+
);
96+
} finally {
97+
context.setScreenRecorder(null);
98+
}
8999
},
90100
});
91-
92-
async function stopScreencastAndAppendOutput(
93-
response: Response,
94-
context: Context,
95-
): Promise<void> {
96-
const data = context.getScreenRecorder();
97-
if (!data) {
98-
return;
99-
}
100-
try {
101-
await data.recorder.stop();
102-
response.appendResponseLine(
103-
`The screencast recording has been stopped and saved to ${data.filePath}.`,
104-
);
105-
} finally {
106-
context.setScreenRecorder(null);
107-
}
108-
}

tests/tools/screencast.test.ts

Lines changed: 2 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,7 @@ describe('screencast', () => {
6060
.stub(selectedPage, 'screencast')
6161
.resolves(mockRecorder as never);
6262

63-
await startScreencast.handler(
64-
{params: {}},
65-
response,
66-
context,
67-
);
63+
await startScreencast.handler({params: {}}, response, context);
6864

6965
sinon.assert.calledOnce(screencastStub);
7066
const callArgs = screencastStub.firstCall.args[0];
@@ -74,35 +70,6 @@ describe('screencast', () => {
7470
});
7571
});
7672

77-
it('passes format and quality options', async () => {
78-
await withMcpContext(async (response, context) => {
79-
const mockRecorder = createMockRecorder();
80-
const selectedPage = context.getSelectedPage();
81-
const screencastStub = sinon
82-
.stub(selectedPage, 'screencast')
83-
.resolves(mockRecorder as never);
84-
85-
await startScreencast.handler(
86-
{
87-
params: {
88-
path: '/tmp/test.mp4',
89-
},
90-
},
91-
response,
92-
context,
93-
);
94-
95-
sinon.assert.calledOnce(screencastStub);
96-
const callArgs = screencastStub.firstCall.args[0];
97-
assert.ok(callArgs);
98-
assert.strictEqual(callArgs.format, 'mp4');
99-
assert.strictEqual(callArgs.quality, 20);
100-
assert.strictEqual(callArgs.fps, 24);
101-
assert.strictEqual(callArgs.scale, 0.5);
102-
assert.strictEqual(callArgs.speed, 2);
103-
});
104-
});
105-
10673
it('errors if a recording is already active', async () => {
10774
await withMcpContext(async (response, context) => {
10875
const mockRecorder = createMockRecorder();
@@ -114,11 +81,7 @@ describe('screencast', () => {
11481
const selectedPage = context.getSelectedPage();
11582
const screencastStub = sinon.stub(selectedPage, 'screencast');
11683

117-
await startScreencast.handler(
118-
{params: {}},
119-
response,
120-
context,
121-
);
84+
await startScreencast.handler({params: {}}, response, context);
12285

12386
sinon.assert.notCalled(screencastStub);
12487
assert.ok(

0 commit comments

Comments
 (0)