mirror of
https://github.com/microsoft/playwright-mcp.git
synced 2025-07-27 09:02:26 +08:00
chore: convert console resource to tool (#193)
This commit is contained in:
parent
e4331313f9
commit
5c2e11017d
@ -298,6 +298,12 @@ server.connect(transport);
|
|||||||
- Parameters:
|
- Parameters:
|
||||||
- `key` (string): Name of the key to press or a character to generate, such as `ArrowLeft` or `a`
|
- `key` (string): Name of the key to press or a character to generate, such as `ArrowLeft` or `a`
|
||||||
|
|
||||||
|
### Console
|
||||||
|
|
||||||
|
- **browser_console_messages**
|
||||||
|
- Description: Returns all console messages
|
||||||
|
- Parameters: None
|
||||||
|
|
||||||
### Files and Media
|
### Files and Media
|
||||||
|
|
||||||
- **browser_file_upload**
|
- **browser_file_upload**
|
||||||
|
@ -111,18 +111,21 @@ export class Context {
|
|||||||
|
|
||||||
if (this._currentTab === tab)
|
if (this._currentTab === tab)
|
||||||
this._currentTab = this._tabs[Math.min(index, this._tabs.length - 1)];
|
this._currentTab = this._tabs[Math.min(index, this._tabs.length - 1)];
|
||||||
const browser = this._browser;
|
if (this._browserContext && !this._tabs.length)
|
||||||
if (this._browserContext && !this._tabs.length) {
|
void this.close();
|
||||||
void this._browserContext.close().then(() => browser?.close()).catch(() => {});
|
|
||||||
this._browser = undefined;
|
|
||||||
this._browserContext = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
if (!this._browserContext)
|
if (!this._browserContext)
|
||||||
return;
|
return;
|
||||||
await this._browserContext.close();
|
const browserContext = this._browserContext;
|
||||||
|
const browser = this._browser;
|
||||||
|
this._browserContext = undefined;
|
||||||
|
this._browser = undefined;
|
||||||
|
|
||||||
|
await browserContext?.close().then(async () => {
|
||||||
|
await browser?.close();
|
||||||
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _ensureBrowserContext() {
|
private async _ensureBrowserContext() {
|
||||||
|
11
src/index.ts
11
src/index.ts
@ -20,6 +20,7 @@ import fs from 'fs';
|
|||||||
|
|
||||||
import { createServerWithTools } from './server';
|
import { createServerWithTools } from './server';
|
||||||
import common from './tools/common';
|
import common from './tools/common';
|
||||||
|
import console from './tools/console';
|
||||||
import files from './tools/files';
|
import files from './tools/files';
|
||||||
import install from './tools/install';
|
import install from './tools/install';
|
||||||
import keyboard from './tools/keyboard';
|
import keyboard from './tools/keyboard';
|
||||||
@ -28,15 +29,14 @@ import pdf from './tools/pdf';
|
|||||||
import snapshot from './tools/snapshot';
|
import snapshot from './tools/snapshot';
|
||||||
import tabs from './tools/tabs';
|
import tabs from './tools/tabs';
|
||||||
import screen from './tools/screen';
|
import screen from './tools/screen';
|
||||||
import { console as consoleResource } from './resources/console';
|
|
||||||
|
|
||||||
import type { Tool, ToolCapability } from './tools/tool';
|
import type { Tool, ToolCapability } from './tools/tool';
|
||||||
import type { Resource } from './resources/resource';
|
|
||||||
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
||||||
import type { LaunchOptions } from 'playwright';
|
import type { LaunchOptions } from 'playwright';
|
||||||
|
|
||||||
const snapshotTools: Tool[] = [
|
const snapshotTools: Tool[] = [
|
||||||
...common(true),
|
...common(true),
|
||||||
|
...console,
|
||||||
...files(true),
|
...files(true),
|
||||||
...install,
|
...install,
|
||||||
...keyboard(true),
|
...keyboard(true),
|
||||||
@ -48,6 +48,7 @@ const snapshotTools: Tool[] = [
|
|||||||
|
|
||||||
const screenshotTools: Tool[] = [
|
const screenshotTools: Tool[] = [
|
||||||
...common(false),
|
...common(false),
|
||||||
|
...console,
|
||||||
...files(false),
|
...files(false),
|
||||||
...install,
|
...install,
|
||||||
...keyboard(false),
|
...keyboard(false),
|
||||||
@ -57,10 +58,6 @@ const screenshotTools: Tool[] = [
|
|||||||
...tabs(false),
|
...tabs(false),
|
||||||
];
|
];
|
||||||
|
|
||||||
const resources: Resource[] = [
|
|
||||||
consoleResource,
|
|
||||||
];
|
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
browser?: string;
|
browser?: string;
|
||||||
userDataDir?: string;
|
userDataDir?: string;
|
||||||
@ -115,7 +112,7 @@ export async function createServer(options?: Options): Promise<Server> {
|
|||||||
name: 'Playwright',
|
name: 'Playwright',
|
||||||
version: packageJSON.version,
|
version: packageJSON.version,
|
||||||
tools,
|
tools,
|
||||||
resources,
|
resources: [],
|
||||||
browserName,
|
browserName,
|
||||||
userDataDir,
|
userDataDir,
|
||||||
launchOptions,
|
launchOptions,
|
||||||
|
@ -14,22 +14,32 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { Resource } from './resource';
|
import { z } from 'zod';
|
||||||
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
||||||
|
|
||||||
export const console: Resource = {
|
import type { Tool } from './tool';
|
||||||
|
|
||||||
|
const consoleSchema = z.object({});
|
||||||
|
|
||||||
|
const console: Tool = {
|
||||||
|
capability: 'core',
|
||||||
schema: {
|
schema: {
|
||||||
uri: 'browser://console',
|
name: 'browser_console_messages',
|
||||||
name: 'Page console',
|
description: 'Returns all console messages',
|
||||||
mimeType: 'text/plain',
|
inputSchema: zodToJsonSchema(consoleSchema),
|
||||||
},
|
},
|
||||||
|
handle: async context => {
|
||||||
read: async (context, uri) => {
|
|
||||||
const messages = await context.currentTab().console();
|
const messages = await context.currentTab().console();
|
||||||
const log = messages.map(message => `[${message.type().toUpperCase()}] ${message.text()}`).join('\n');
|
const log = messages.map(message => `[${message.type().toUpperCase()}] ${message.text()}`).join('\n');
|
||||||
return [{
|
return {
|
||||||
uri,
|
content: [{
|
||||||
mimeType: 'text/plain',
|
type: 'text',
|
||||||
text: log
|
text: log
|
||||||
}];
|
}],
|
||||||
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default [
|
||||||
|
console,
|
||||||
|
];
|
@ -211,14 +211,10 @@ test('browser_type', async ({ client }) => {
|
|||||||
submit: true,
|
submit: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const resource = await client.readResource({
|
expect(await client.callTool({
|
||||||
uri: 'browser://console',
|
name: 'browser_console_messages',
|
||||||
});
|
arguments: {},
|
||||||
expect(resource.contents).toEqual([{
|
})).toHaveTextContent('[LOG] Key pressed: Enter , Text: Hi!');
|
||||||
uri: 'browser://console',
|
|
||||||
mimeType: 'text/plain',
|
|
||||||
text: '[LOG] Key pressed: Enter , Text: Hi!',
|
|
||||||
}]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('browser_type (slowly)', async ({ client }) => {
|
test('browser_type (slowly)', async ({ client }) => {
|
||||||
@ -238,19 +234,15 @@ test('browser_type (slowly)', async ({ client }) => {
|
|||||||
slowly: true,
|
slowly: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const resource = await client.readResource({
|
expect(await client.callTool({
|
||||||
uri: 'browser://console',
|
name: 'browser_console_messages',
|
||||||
});
|
arguments: {},
|
||||||
expect(resource.contents).toEqual([{
|
})).toHaveTextContent([
|
||||||
uri: 'browser://console',
|
|
||||||
mimeType: 'text/plain',
|
|
||||||
text: [
|
|
||||||
'[LOG] Key pressed: H Text: ',
|
'[LOG] Key pressed: H Text: ',
|
||||||
'[LOG] Key pressed: i Text: H',
|
'[LOG] Key pressed: i Text: H',
|
||||||
'[LOG] Key pressed: ! Text: Hi',
|
'[LOG] Key pressed: ! Text: Hi',
|
||||||
'[LOG] Key pressed: Enter Text: Hi!',
|
'[LOG] Key pressed: Enter Text: Hi!',
|
||||||
].join('\n'),
|
].join('\n'));
|
||||||
}]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('browser_resize', async ({ client }) => {
|
test('browser_resize', async ({ client }) => {
|
||||||
|
@ -20,6 +20,7 @@ test('test snapshot tool list', async ({ client }) => {
|
|||||||
const { tools } = await client.listTools();
|
const { tools } = await client.listTools();
|
||||||
expect(new Set(tools.map(t => t.name))).toEqual(new Set([
|
expect(new Set(tools.map(t => t.name))).toEqual(new Set([
|
||||||
'browser_click',
|
'browser_click',
|
||||||
|
'browser_console_messages',
|
||||||
'browser_drag',
|
'browser_drag',
|
||||||
'browser_file_upload',
|
'browser_file_upload',
|
||||||
'browser_hover',
|
'browser_hover',
|
||||||
@ -47,6 +48,7 @@ test('test vision tool list', async ({ visionClient }) => {
|
|||||||
const { tools: visionTools } = await visionClient.listTools();
|
const { tools: visionTools } = await visionClient.listTools();
|
||||||
expect(new Set(visionTools.map(t => t.name))).toEqual(new Set([
|
expect(new Set(visionTools.map(t => t.name))).toEqual(new Set([
|
||||||
'browser_close',
|
'browser_close',
|
||||||
|
'browser_console_messages',
|
||||||
'browser_file_upload',
|
'browser_file_upload',
|
||||||
'browser_install',
|
'browser_install',
|
||||||
'browser_navigate_back',
|
'browser_navigate_back',
|
||||||
@ -70,12 +72,7 @@ test('test vision tool list', async ({ visionClient }) => {
|
|||||||
|
|
||||||
test('test resources list', async ({ client }) => {
|
test('test resources list', async ({ client }) => {
|
||||||
const { resources } = await client.listResources();
|
const { resources } = await client.listResources();
|
||||||
expect(resources).toEqual([
|
expect(resources).toEqual([]);
|
||||||
expect.objectContaining({
|
|
||||||
uri: 'browser://console',
|
|
||||||
mimeType: 'text/plain',
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('test capabilities', async ({ startClient }) => {
|
test('test capabilities', async ({ startClient }) => {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import { test, expect } from './fixtures';
|
import { test, expect } from './fixtures';
|
||||||
|
|
||||||
test('browser://console', async ({ client }) => {
|
test('browser_console_messages', async ({ client }) => {
|
||||||
await client.callTool({
|
await client.callTool({
|
||||||
name: 'browser_navigate',
|
name: 'browser_navigate',
|
||||||
arguments: {
|
arguments: {
|
||||||
@ -24,12 +24,12 @@ test('browser://console', async ({ client }) => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const resource = await client.readResource({
|
const resource = await client.callTool({
|
||||||
uri: 'browser://console',
|
name: 'browser_console_messages',
|
||||||
|
arguments: {},
|
||||||
});
|
});
|
||||||
expect(resource.contents).toEqual([{
|
expect(resource).toHaveTextContent([
|
||||||
uri: 'browser://console',
|
'[LOG] Hello, world!',
|
||||||
mimeType: 'text/plain',
|
'[ERROR] Error',
|
||||||
text: '[LOG] Hello, world!\n[ERROR] Error',
|
].join('\n'));
|
||||||
}]);
|
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user