Skip to content

Commit 51b2725

Browse files
Merge pull request #148 from executeautomation/Release-branch-for-v1.0.6
Release branch for v1.0.6
2 parents 7993f03 + 8ea8b3f commit 51b2725

File tree

10 files changed

+117
-56
lines changed

10 files changed

+117
-56
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ The evals package loads an mcp client that then runs the index.ts file, so there
124124
OPENAI_API_KEY=your-key npx mcp-eval src/evals/evals.ts src/tools/codegen/index.ts
125125
```
126126

127+
## Contributing
128+
129+
When adding new tools, please be mindful of the tool name length. Some clients, like Cursor, have a 60-character limit for the combined server and tool name (`server_name:tool_name`).
130+
131+
Our server name is `playwright-mcp`. Please ensure your tool names are short enough to not exceed this limit.
132+
127133
## Star History
128134

129135
[![Star History Chart](https://api.star-history.com/svg?repos=executeautomation/mcp-playwright&type=Date)](https://star-history.com/#executeautomation/mcp-playwright&Date)

docs/docs/release.mdx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ import YouTubeVideoEmbed from '@site/src/components/HomepageFeatures/YouTubeVide
55

66
# Release Notes
77

8+
## Version 1.0.6
9+
- **New Tool: `playwright_upload_file`**: Added a new tool to upload files to an `input[type='file']` element.
10+
- **Enhanced Content Extraction**:
11+
- Significantly improved `playwright_get_visible_text` tool for more accurate text extraction.
12+
- Added `playwright_get_visible_html` tool to retrieve the full HTML content of the page.
13+
- **By default, all `<script>` tags are now removed from the HTML output for `playwright_get_visible_html` (unless `removeScripts: false` is set). Output is also truncated to a safe length (default 20,000 characters) to prevent issues with LLM clients.**
14+
- **Improved Interactions**:
15+
- Updated `playwright_hover` functionality in the interaction tool.
16+
- **Browser Support**:
17+
- Added support for using locally installed browsers by specifying the Chrome executable path.
18+
- **Documentation Updates**:
19+
- Added a new local setup and installation guide.
20+
- Updated examples and documentation for the new and improved tools.
21+
- **Test Coverage**:
22+
- Added and updated tests for the new content extraction and interaction features.
23+
- **Version bump**: Incremented version to 1.0.6.
24+
825
## Version 1.0.5
926
- **Removed SSE (Server-Sent Events) Support**: All SSE-related code, endpoints, and documentation have been fully removed. The server now only supports STDIO transport for communication with clients.
1027
- **Codebase Cleanup**: Removed all references to SseServer, /events endpoint, and related event streaming features from the code and documentation.

package-lock.json

Lines changed: 30 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@executeautomation/playwright-mcp-server",
3-
"version": "1.0.5",
3+
"version": "1.0.6",
44
"description": "Model Context Protocol servers for Playwright",
55
"license": "MIT",
66
"author": "ExecuteAutomation, Ltd (https://executeautomation.com)",
@@ -28,12 +28,12 @@
2828
},
2929
"dependencies": {
3030
"@modelcontextprotocol/sdk": "1.11.1",
31-
"@playwright/browser-chromium": "1.52.0",
32-
"@playwright/browser-firefox": "1.52.0",
33-
"@playwright/browser-webkit": "1.52.0",
34-
"@playwright/test": "^1.52.0",
31+
"@playwright/browser-chromium": "1.53.1",
32+
"@playwright/browser-firefox": "1.53.1",
33+
"@playwright/browser-webkit": "1.53.1",
34+
"@playwright/test": "^1.53.1",
3535
"mcp-evals": "^1.0.18",
36-
"playwright": "1.52.0",
36+
"playwright": "1.53.1",
3737
"uuid": "11.1.0"
3838
},
3939
"keywords": [

src/__tests__/toolHandler.test.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,4 +374,28 @@ describe('Tool Handler', () => {
374374
]);
375375
});
376376
});
377+
378+
test('should use executablePath when CHROME_EXECUTABLE_PATH is set', async () => {
379+
const mockExecutablePath = '/path/to/chrome';
380+
process.env.CHROME_EXECUTABLE_PATH = mockExecutablePath;
381+
382+
// Call the navigation tool to trigger browser launch
383+
await handleToolCall('playwright_navigate', { url: 'about:blank' }, mockServer);
384+
385+
// This is a proxy for checking if the executable path is being used.
386+
// A more direct test would require exporting ensureBrowser and spying on it.
387+
// For now, we will just check if the tool call succeeds.
388+
const result = await handleToolCall('playwright_navigate', { url: 'about:blank' }, mockServer);
389+
expect(result.content[0].text).toContain('Navigated to');
390+
391+
// Clean up
392+
delete process.env.CHROME_EXECUTABLE_PATH;
393+
});
394+
395+
test('should not launch browser for API tools', async () => {
396+
const ensureBrowser = jest.spyOn(require('../toolHandler'), 'ensureBrowser');
397+
await handleToolCall('playwright_get', { url: 'https://api.restful-api.dev/objects' }, mockServer);
398+
expect(ensureBrowser).not.toHaveBeenCalled();
399+
ensureBrowser.mockRestore();
400+
});
377401
});

src/__tests__/tools/browser/visiblePage.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ describe('VisibleHtmlTool', () => {
127127
});
128128

129129
test('should retrieve HTML content', async () => {
130-
const args = {};
130+
const args = { removeScripts: false };
131131

132132
const result = await visibleHtmlTool.execute(args, mockContext);
133133

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { setupRequestHandlers } from "./requestHandler.js";
88
async function runServer() {
99
const server = new Server(
1010
{
11-
name: "executeautomation/playwright-mcp-server",
12-
version: "1.0.5",
11+
name: "playwright-mcp",
12+
version: "1.0.6",
1313
},
1414
{
1515
capabilities: {

src/toolHandler.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ async function registerConsoleMessage(page) {
155155
/**
156156
* Ensures a browser is launched and returns the page
157157
*/
158-
async function ensureBrowser(browserSettings?: BrowserSettings) {
158+
export async function ensureBrowser(browserSettings?: BrowserSettings) {
159159
try {
160160
// Check if browser exists but is disconnected
161161
if (browser && !browser.isConnected()) {
@@ -199,10 +199,14 @@ async function ensureBrowser(browserSettings?: BrowserSettings) {
199199
browserInstance = chromium;
200200
break;
201201
}
202-
// Read the Chrome executable path from the environment variable
203-
const executablePath = process.env.PLAYWRIGHT_CHROME_EXECUTABLE_PATH || undefined; // Fallback to default if not set
204202

205-
browser = await browserInstance.launch({ headless, executablePath });
203+
const executablePath = process.env.CHROME_EXECUTABLE_PATH;
204+
205+
browser = await browserInstance.launch({
206+
headless,
207+
executablePath: executablePath
208+
});
209+
206210
currentBrowserType = browserType;
207211

208212
// Add cleanup logic when browser is disconnected

src/tools.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,17 +350,18 @@ export function createToolDefinitions() {
350350
},
351351
{
352352
name: "playwright_get_visible_html",
353-
description: "Get the HTML content of the current page",
353+
description: "Get the HTML content of the current page. By default, all <script> tags are removed from the output unless removeScripts is explicitly set to false.",
354354
inputSchema: {
355355
type: "object",
356356
properties: {
357357
selector: { type: "string", description: "CSS selector to limit the HTML to a specific container" },
358-
removeScripts: { type: "boolean", description: "Remove all script tags from the HTML (default: false)" },
358+
removeScripts: { type: "boolean", description: "Remove all script tags from the HTML (default: true)" },
359359
removeComments: { type: "boolean", description: "Remove all HTML comments (default: false)" },
360360
removeStyles: { type: "boolean", description: "Remove all style tags from the HTML (default: false)" },
361361
removeMeta: { type: "boolean", description: "Remove all meta tags from the HTML (default: false)" },
362362
cleanHtml: { type: "boolean", description: "Perform comprehensive HTML cleaning (default: false)" },
363-
minify: { type: "boolean", description: "Minify the HTML output (default: false)" }
363+
minify: { type: "boolean", description: "Minify the HTML output (default: false)" },
364+
maxLength: { type: "number", description: "Maximum number of characters to return (default: 20000)" }
364365
},
365366
required: [],
366367
},

src/tools/browser/visiblePage.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,15 @@ export class VisibleTextTool extends BrowserToolBase {
5050
}
5151
return text.trim();
5252
});
53-
return createSuccessResponse(`Visible text content:\n${visibleText}`);
53+
// Truncate logic
54+
const maxLength = typeof args.maxLength === 'number' ? args.maxLength : 20000;
55+
let output = visibleText;
56+
let truncated = false;
57+
if (output.length > maxLength) {
58+
output = output.slice(0, maxLength) + '\n[Output truncated due to size limits]';
59+
truncated = true;
60+
}
61+
return createSuccessResponse(`Visible text content:\n${output}`);
5462
} catch (error) {
5563
return createErrorResponse(`Failed to get visible text content: ${(error as Error).message}`);
5664
}
@@ -83,7 +91,9 @@ export class VisibleHtmlTool extends BrowserToolBase {
8391
}
8492
return this.safeExecute(context, async (page) => {
8593
try {
86-
const { selector, removeScripts, removeComments, removeStyles, removeMeta, minify, cleanHtml } = args;
94+
const { selector, removeComments, removeStyles, removeMeta, minify, cleanHtml } = args;
95+
// Default removeScripts to true unless explicitly set to false
96+
const removeScripts = args.removeScripts === false ? false : true;
8797

8898
// Get the HTML content
8999
let htmlContent: string;
@@ -170,7 +180,13 @@ export class VisibleHtmlTool extends BrowserToolBase {
170180
);
171181
}
172182

173-
return createSuccessResponse(`HTML content:\n${htmlContent}`);
183+
// Truncate logic
184+
const maxLength = typeof args.maxLength === 'number' ? args.maxLength : 20000;
185+
let output = htmlContent;
186+
if (output.length > maxLength) {
187+
output = output.slice(0, maxLength) + '\n<!-- Output truncated due to size limits -->';
188+
}
189+
return createSuccessResponse(`HTML content:\n${output}`);
174190
} catch (error) {
175191
return createErrorResponse(`Failed to get visible HTML content: ${(error as Error).message}`);
176192
}

0 commit comments

Comments
 (0)