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