chore: move from esm to cjs before upstreaming (#986)

This commit is contained in:
Pavel Feldman
2025-09-03 08:00:58 -07:00
committed by GitHub
parent 8d86ce4958
commit 2461f32d05
92 changed files with 250 additions and 259 deletions

2
cli.js
View File

@@ -15,4 +15,4 @@
* limitations under the License. * limitations under the License.
*/ */
import './lib/program.js'; require('./lib/program');

View File

@@ -14,16 +14,12 @@
* limitations under the License. * limitations under the License.
*/ */
import typescriptEslint from "@typescript-eslint/eslint-plugin"; const typescriptEslint = require("@typescript-eslint/eslint-plugin");
import tsParser from "@typescript-eslint/parser"; const tsParser = require("@typescript-eslint/parser");
import notice from "eslint-plugin-notice"; const notice = require("eslint-plugin-notice");
import path from "path"; const path = require("path");
import { fileURLToPath } from "url"; const stylistic = require("@stylistic/eslint-plugin");
import stylistic from "@stylistic/eslint-plugin"; const importRules = require("eslint-plugin-import");
import importRules from "eslint-plugin-import";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const plugins = { const plugins = {
"@stylistic": stylistic, "@stylistic": stylistic,
@@ -32,8 +28,7 @@ const plugins = {
import: importRules, import: importRules,
}; };
export const baseRules = { const baseRules = {
"import/extensions": ["error", "ignorePackages", {ts: "always"}],
"@typescript-eslint/no-floating-promises": "error", "@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-unused-vars": [ "@typescript-eslint/no-unused-vars": [
2, 2,
@@ -188,7 +183,7 @@ const languageOptions = {
ecmaVersion: 9, ecmaVersion: 9,
sourceType: "module", sourceType: "module",
parserOptions: { parserOptions: {
project: path.join(fileURLToPath(import.meta.url), "..", "tsconfig.all.json"), project: path.join(__filename, "..", "tsconfig.all.json"),
} }
}; };
@@ -217,7 +212,7 @@ const noBooleanCompareRules = {
"@typescript-eslint/no-unnecessary-boolean-literal-compare": 2, "@typescript-eslint/no-unnecessary-boolean-literal-compare": 2,
}; };
export default [ module.exports = [
{ {
ignores: ["**/*.js"], ignores: ["**/*.js"],
}, },

View File

@@ -14,7 +14,7 @@
"<all_urls>" "<all_urls>"
], ],
"background": { "background": {
"service_worker": "lib/background.js", "service_worker": "lib/background.mjs",
"type": "module" "type": "module"
}, },
"action": { "action": {

View File

@@ -2,7 +2,6 @@
"name": "@playwright/mcp-extension", "name": "@playwright/mcp-extension",
"version": "0.0.36", "version": "0.0.36",
"description": "Playwright MCP Browser Extension", "description": "Playwright MCP Browser Extension",
"type": "module",
"private": true, "private": true,
"repository": { "repository": {
"type": "git", "type": "git",
@@ -17,8 +16,8 @@
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"scripts": { "scripts": {
"build": "tsc --project . && tsc --project tsconfig.ui.json && vite build", "build": "tsc --project . && tsc --project tsconfig.ui.json && vite build && vite build --config vite.sw.config.mts",
"watch": "tsc --watch --project . & tsc --watch --project tsconfig.ui.json & vite build --watch", "watch": "tsc --watch --project . & tsc --watch --project tsconfig.ui.json & vite build --watch & vite build --watch --config vite.sw.config.mts",
"test": "playwright test", "test": "playwright test",
"clean": "rm -rf dist" "clean": "rm -rf dist"
}, },

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { RelayConnection, debugLog } from './relayConnection.js'; import { RelayConnection, debugLog } from './relayConnection';
type PageMessage = { type PageMessage = {
type: 'connectToMCPRelay'; type: 'connectToMCPRelay';

View File

@@ -16,7 +16,6 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { fileURLToPath } from 'url';
import { chromium } from 'playwright'; import { chromium } from 'playwright';
import { test as base, expect } from '../../tests/fixtures.js'; import { test as base, expect } from '../../tests/fixtures.js';
@@ -38,7 +37,7 @@ type TestFixtures = {
const test = base.extend<TestFixtures>({ const test = base.extend<TestFixtures>({
pathToExtension: async ({}, use) => { pathToExtension: async ({}, use) => {
await use(fileURLToPath(new URL('../dist', import.meta.url))); await use(path.resolve(__dirname, '../dist'));
}, },
browserWithExtension: async ({ mcpBrowser, pathToExtension }, use, testInfo) => { browserWithExtension: async ({ mcpBrowser, pathToExtension }, use, testInfo) => {
@@ -126,7 +125,7 @@ async function startWithExtensionFlag(browserWithExtension: BrowserWithExtension
const testWithOldExtensionVersion = test.extend({ const testWithOldExtensionVersion = test.extend({
pathToExtension: async ({}, use, testInfo) => { pathToExtension: async ({}, use, testInfo) => {
const extensionDir = testInfo.outputPath('extension'); const extensionDir = testInfo.outputPath('extension');
const oldPath = fileURLToPath(new URL('../dist', import.meta.url)); const oldPath = path.resolve(__dirname, '../dist');
await fs.promises.cp(oldPath, extensionDir, { recursive: true }); await fs.promises.cp(oldPath, extensionDir, { recursive: true });
const manifestPath = path.join(extensionDir, 'manifest.json'); const manifestPath = path.join(extensionDir, 'manifest.json');

View File

@@ -10,7 +10,8 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"types": ["chrome"], "types": ["chrome"],
"jsx": "react-jsx", "jsx": "react-jsx",
"jsxImportSource": "react" "jsxImportSource": "react",
"noEmit": true
}, },
"include": [ "include": [
"src", "src",

View File

@@ -0,0 +1,31 @@
/**
* Copyright (c) Microsoft Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { resolve } from 'path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/background.ts'),
fileName: 'lib/background',
formats: ['es']
},
outDir: 'dist',
emptyOutDir: false,
minify: false
}
});

2
index.d.ts vendored
View File

@@ -16,7 +16,7 @@
*/ */
import type { Server } from '@modelcontextprotocol/sdk/server/index.js'; import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
import type { Config } from './config.js'; import type { Config } from './config';
import type { BrowserContext } from 'playwright'; import type { BrowserContext } from 'playwright';
export declare function createConnection(config?: Config, contextGetter?: () => Promise<BrowserContext>): Promise<Server>; export declare function createConnection(config?: Config, contextGetter?: () => Promise<BrowserContext>): Promise<Server>;

View File

@@ -15,5 +15,5 @@
* limitations under the License. * limitations under the License.
*/ */
import { createConnection } from './lib/index.js'; const { createConnection } = require('./lib/index.js');
export { createConnection }; module.exports = { createConnection };

View File

@@ -2,7 +2,6 @@
"name": "@playwright/mcp", "name": "@playwright/mcp",
"version": "0.0.36", "version": "0.0.36",
"description": "Playwright Tools for MCP", "description": "Playwright Tools for MCP",
"type": "module",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/microsoft/playwright-mcp.git" "url": "git+https://github.com/microsoft/playwright-mcp.git"

View File

@@ -16,7 +16,7 @@
import { defineConfig } from '@playwright/test'; import { defineConfig } from '@playwright/test';
import type { TestOptions } from './tests/fixtures.js'; import type { TestOptions } from './tests/fixtures';
export default defineConfig<TestOptions>({ export default defineConfig<TestOptions>({
testDir: './tests', testDir: './tests',

View File

@@ -23,11 +23,11 @@ import * as playwright from 'playwright';
import { registryDirectory } from 'playwright-core/lib/server/registry/index'; import { registryDirectory } from 'playwright-core/lib/server/registry/index';
// @ts-ignore // @ts-ignore
import { startTraceViewerServer } from 'playwright-core/lib/server'; import { startTraceViewerServer } from 'playwright-core/lib/server';
import { logUnhandledError, testDebug } from './utils/log.js'; import { logUnhandledError, testDebug } from './utils/log';
import { createHash } from './utils/guid.js'; import { createHash } from './utils/guid';
import { outputFile } from './config.js'; import { outputFile } from './config';
import type { FullConfig } from './config.js'; import type { FullConfig } from './config';
export function contextFactory(config: FullConfig): BrowserContextFactory { export function contextFactory(config: FullConfig): BrowserContextFactory {
if (config.browser.remoteEndpoint) if (config.browser.remoteEndpoint)

View File

@@ -15,18 +15,18 @@
*/ */
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import { FullConfig } from './config.js'; import { FullConfig } from './config';
import { Context } from './context.js'; import { Context } from './context';
import { logUnhandledError } from './utils/log.js'; import { logUnhandledError } from './utils/log';
import { Response } from './response.js'; import { Response } from './response';
import { SessionLog } from './sessionLog.js'; import { SessionLog } from './sessionLog';
import { filteredTools } from './tools.js'; import { filteredTools } from './tools';
import { toMcpTool } from './mcp/tool.js'; import { toMcpTool } from './mcp/tool';
import type { Tool } from './tools/tool.js'; import type { Tool } from './tools/tool';
import type { BrowserContextFactory } from './browserContextFactory.js'; import type { BrowserContextFactory } from './browserContextFactory';
import type * as mcpServer from './mcp/server.js'; import type * as mcpServer from './mcp/server';
import type { ServerBackend } from './mcp/server.js'; import type { ServerBackend } from './mcp/server';
export class BrowserServerBackend implements ServerBackend { export class BrowserServerBackend implements ServerBackend {
private _tools: Tool[]; private _tools: Tool[];

View File

@@ -18,7 +18,7 @@ import fs from 'fs';
import os from 'os'; import os from 'os';
import path from 'path'; import path from 'path';
import { devices } from 'playwright'; import { devices } from 'playwright';
import { sanitizeForFilePath } from './utils/fileUtils.js'; import { sanitizeForFilePath } from './utils/fileUtils';
import type { Config, ToolCapability } from '../config.js'; import type { Config, ToolCapability } from '../config.js';
import type { BrowserContextOptions, LaunchOptions } from 'playwright'; import type { BrowserContextOptions, LaunchOptions } from 'playwright';

View File

@@ -17,15 +17,15 @@
import debug from 'debug'; import debug from 'debug';
import * as playwright from 'playwright'; import * as playwright from 'playwright';
import { logUnhandledError } from './utils/log.js'; import { logUnhandledError } from './utils/log';
import { Tab } from './tab.js'; import { Tab } from './tab';
import { outputFile } from './config.js'; import { outputFile } from './config';
import type { FullConfig } from './config.js'; import type { FullConfig } from './config';
import type { Tool } from './tools/tool.js'; import type { Tool } from './tools/tool';
import type { BrowserContextFactory, ClientInfo } from './browserContextFactory.js'; import type { BrowserContextFactory, ClientInfo } from './browserContextFactory';
import type * as actions from './actions.js'; import type * as actions from './actions';
import type { SessionLog } from './sessionLog.js'; import type { SessionLog } from './sessionLog';
const testDebug = debug('pw:mcp:test'); const testDebug = debug('pw:mcp:test');

View File

@@ -26,17 +26,19 @@ import { spawn } from 'child_process';
import http from 'http'; import http from 'http';
import debug from 'debug'; import debug from 'debug';
import { WebSocket, WebSocketServer } from 'ws'; import { WebSocket, WebSocketServer } from 'ws';
// @ts-ignore
import { registry } from 'playwright-core/lib/server/registry/index';
import { httpAddressToString } from '../mcp/http.js'; import { httpAddressToString } from '../mcp/http.js';
import { logUnhandledError } from '../utils/log.js'; import { logUnhandledError } from '../utils/log.js';
import { ManualPromise } from '../mcp/manualPromise.js'; import { ManualPromise } from '../mcp/manualPromise.js';
import * as protocol from './protocol.js'; import * as protocol from './protocol';
import type websocket from 'ws'; import type websocket from 'ws';
import type { ClientInfo } from '../browserContextFactory.js'; import type { ClientInfo } from '../browserContextFactory.js';
import type { ExtensionCommand, ExtensionEvents } from './protocol.js'; import type { ExtensionCommand, ExtensionEvents } from './protocol';
// @ts-ignore
const { registry } = await import('playwright-core/lib/server/registry/index');
const debugLogger = debug('pw:mcp:relay'); const debugLogger = debug('pw:mcp:relay');

View File

@@ -17,7 +17,7 @@
import debug from 'debug'; import debug from 'debug';
import * as playwright from 'playwright'; import * as playwright from 'playwright';
import { startHttpServer } from '../mcp/http.js'; import { startHttpServer } from '../mcp/http.js';
import { CDPRelayServer } from './cdpRelay.js'; import { CDPRelayServer } from './cdpRelay';
import type { BrowserContextFactory, ClientInfo } from '../browserContextFactory.js'; import type { BrowserContextFactory, ClientInfo } from '../browserContextFactory.js';

View File

@@ -14,15 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
import { BrowserServerBackend } from './browserServerBackend.js'; import { BrowserServerBackend } from './browserServerBackend';
import { resolveConfig } from './config.js'; import { resolveConfig } from './config';
import { contextFactory } from './browserContextFactory.js'; import { contextFactory } from './browserContextFactory';
import * as mcpServer from './mcp/server.js'; import * as mcpServer from './mcp/server';
import { packageJSON } from './utils/package.js'; import { packageJSON } from './utils/package';
import type { Config } from '../config.js'; import type { Config } from '../config.js';
import type { BrowserContext } from 'playwright'; import type { BrowserContext } from 'playwright';
import type { BrowserContextFactory } from './browserContextFactory.js'; import type { BrowserContextFactory } from './browserContextFactory';
import type { Server } from '@modelcontextprotocol/sdk/server/index.js'; import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
export async function createConnection(userConfig: Config = {}, contextGetter?: () => Promise<BrowserContext>): Promise<Server> { export async function createConnection(userConfig: Config = {}, contextGetter?: () => Promise<BrowserContext>): Promise<Server> {

View File

@@ -15,7 +15,7 @@
*/ */
import type Anthropic from '@anthropic-ai/sdk'; import type Anthropic from '@anthropic-ai/sdk';
import type { LLMDelegate, LLMConversation, LLMToolCall, LLMTool } from './loop.js'; import type { LLMDelegate, LLMConversation, LLMToolCall, LLMTool } from './loop';
import type { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Tool } from '@modelcontextprotocol/sdk/types.js';
const model = 'claude-sonnet-4-20250514'; const model = 'claude-sonnet-4-20250514';
@@ -26,7 +26,7 @@ export class ClaudeDelegate implements LLMDelegate {
async anthropic(): Promise<Anthropic> { async anthropic(): Promise<Anthropic> {
if (!this._anthropic) { if (!this._anthropic) {
const anthropic = await import('@anthropic-ai/sdk'); const anthropic = await import('@anthropic-ai/sdk');
this._anthropic = new anthropic.Anthropic(); this._anthropic = new anthropic.Anthropic() as unknown as Anthropic;
} }
return this._anthropic; return this._anthropic;
} }

View File

@@ -15,7 +15,7 @@
*/ */
import type OpenAI from 'openai'; import type OpenAI from 'openai';
import type { LLMDelegate, LLMConversation, LLMToolCall, LLMTool } from './loop.js'; import type { LLMDelegate, LLMConversation, LLMToolCall, LLMTool } from './loop';
import type { Tool } from '@modelcontextprotocol/sdk/types.js'; import type { Tool } from '@modelcontextprotocol/sdk/types.js';
const model = 'gpt-4.1'; const model = 'gpt-4.1';
@@ -26,7 +26,7 @@ export class OpenAIDelegate implements LLMDelegate {
async openai(): Promise<OpenAI> { async openai(): Promise<OpenAI> {
if (!this._openai) { if (!this._openai) {
const oai = await import('openai'); const oai = await import('openai');
this._openai = new oai.OpenAI(); this._openai = new oai.OpenAI() as unknown as OpenAI;
} }
return this._openai; return this._openai;
} }

View File

@@ -17,28 +17,25 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import path from 'path'; import path from 'path';
import url from 'url';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import { program } from 'commander'; import { program } from 'commander';
import * as mcpBundle from '../mcp/bundle.js'; import * as mcpBundle from '../mcp/bundle.js';
import { OpenAIDelegate } from './loopOpenAI.js'; import { OpenAIDelegate } from './loopOpenAI';
import { ClaudeDelegate } from './loopClaude.js'; import { ClaudeDelegate } from './loopClaude';
import { runTask } from './loop.js'; import { runTask } from './loop';
import type { LLMDelegate } from './loop.js'; import type { LLMDelegate } from './loop';
dotenv.config(); dotenv.config();
const __filename = url.fileURLToPath(import.meta.url);
async function run(delegate: LLMDelegate) { async function run(delegate: LLMDelegate) {
const transport = new mcpBundle.StdioClientTransport({ const transport = new mcpBundle.StdioClientTransport({
command: 'node', command: 'node',
args: [ args: [
path.resolve(__filename, '../../../cli.js'), path.resolve(__dirname, '../../cli.js'),
'--save-session', '--save-session',
'--output-dir', path.resolve(__filename, '../../../sessions') '--output-dir', path.resolve(__dirname, '../../sessions')
], ],
stderr: 'inherit', stderr: 'inherit',
env: process.env as Record<string, string>, env: process.env as Record<string, string>,

View File

@@ -18,14 +18,14 @@ import dotenv from 'dotenv';
import * as mcpServer from '../mcp/server.js'; import * as mcpServer from '../mcp/server.js';
import { packageJSON } from '../utils/package.js'; import { packageJSON } from '../utils/package.js';
import { Context } from './context.js'; import { Context } from './context';
import { perform } from './perform.js'; import { perform } from './perform';
import { snapshot } from './snapshot.js'; import { snapshot } from './snapshot';
import { toMcpTool } from '../mcp/tool.js'; import { toMcpTool } from '../mcp/tool.js';
import type { FullConfig } from '../config.js'; import type { FullConfig } from '../config.js';
import type { ServerBackend } from '../mcp/server.js'; import type { ServerBackend } from '../mcp/server.js';
import type { Tool } from './tool.js'; import type { Tool } from './tool';
export async function runLoopTools(config: FullConfig) { export async function runLoopTools(config: FullConfig) {
dotenv.config(); dotenv.config();

View File

@@ -16,7 +16,7 @@
import type { z } from 'zod'; import type { z } from 'zod';
import type * as mcpServer from '../mcp/server.js'; import type * as mcpServer from '../mcp/server.js';
import type { Context } from './context.js'; import type { Context } from './context';
import type { ToolSchema } from '../mcp/tool.js'; import type { ToolSchema } from '../mcp/tool.js';

View File

@@ -21,10 +21,10 @@ import crypto from 'crypto';
import debug from 'debug'; import debug from 'debug';
import * as mcpBundle from './bundle.js'; import * as mcpBundle from './bundle';
import * as mcpServer from './server.js'; import * as mcpServer from './server';
import type { ServerBackendFactory } from './server.js'; import type { ServerBackendFactory } from './server';
import type { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import type { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import type { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';

View File

@@ -16,12 +16,12 @@
import debug from 'debug'; import debug from 'debug';
import { defineToolSchema } from './tool.js'; import { defineToolSchema } from './tool';
import * as mcpBundle from './bundle.js'; import * as mcpBundle from './bundle';
import * as mcpServer from './server.js'; import * as mcpServer from './server';
import * as mcpHttp from './http.js'; import * as mcpHttp from './http';
import { wrapInProcess } from './server.js'; import { wrapInProcess } from './server';
import { ManualPromise } from './manualPromise.js'; import { ManualPromise } from './manualPromise';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; import type { Client } from '@modelcontextprotocol/sdk/client/index.js';

View File

@@ -16,9 +16,9 @@
import debug from 'debug'; import debug from 'debug';
import * as mcpBundle from './bundle.js'; import * as mcpBundle from './bundle';
import type { ServerBackend, ClientVersion, Root, Server } from './server.js'; import type { ServerBackend, ClientVersion, Root, Server } from './server';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
import type { Tool, CallToolResult, CallToolRequest } from '@modelcontextprotocol/sdk/types.js'; import type { Tool, CallToolResult, CallToolRequest } from '@modelcontextprotocol/sdk/types.js';
import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; import type { Client } from '@modelcontextprotocol/sdk/client/index.js';

View File

@@ -16,9 +16,9 @@
import debug from 'debug'; import debug from 'debug';
import * as mcpBundle from './bundle.js'; import * as mcpBundle from './bundle';
import { httpAddressToString, installHttpTransport, startHttpServer } from './http.js'; import { httpAddressToString, installHttpTransport, startHttpServer } from './http';
import { InProcessTransport } from './inProcessTransport.js'; import { InProcessTransport } from './inProcessTransport';
import type { Tool, CallToolResult, CallToolRequest, Root } from '@modelcontextprotocol/sdk/types.js'; import type { Tool, CallToolResult, CallToolRequest, Root } from '@modelcontextprotocol/sdk/types.js';
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';

View File

@@ -17,7 +17,7 @@
import { zodToJsonSchema } from '../mcp/bundle.js'; import { zodToJsonSchema } from '../mcp/bundle.js';
import type { z } from 'zod'; import type { z } from 'zod';
import type * as mcpServer from './server.js'; import type * as mcpServer from './server';
export type ToolSchema<Input extends z.Schema> = { export type ToolSchema<Input extends z.Schema> = {
name: string; name: string;

View File

@@ -15,18 +15,18 @@
*/ */
import { program, Option } from 'commander'; import { program, Option } from 'commander';
import * as mcpServer from './mcp/server.js'; import * as mcpServer from './mcp/server';
import { commaSeparatedList, resolveCLIConfig, semicolonSeparatedList } from './config.js'; import { commaSeparatedList, resolveCLIConfig, semicolonSeparatedList } from './config';
import { packageJSON } from './utils/package.js'; import { packageJSON } from './utils/package';
import { Context } from './context.js'; import { Context } from './context';
import { contextFactory } from './browserContextFactory.js'; import { contextFactory } from './browserContextFactory';
import { runLoopTools } from './loopTools/main.js'; import { runLoopTools } from './loopTools/main';
import { ProxyBackend } from './mcp/proxyBackend.js'; import { ProxyBackend } from './mcp/proxyBackend';
import { BrowserServerBackend } from './browserServerBackend.js'; import { BrowserServerBackend } from './browserServerBackend';
import { ExtensionContextFactory } from './extension/extensionContextFactory.js'; import { ExtensionContextFactory } from './extension/extensionContextFactory';
import { runVSCodeTools } from './vscode/host.js'; import { runVSCodeTools } from './vscode/host';
import type { MCPProvider } from './mcp/proxyBackend.js'; import type { MCPProvider } from './mcp/proxyBackend';
program program
.version('Version ' + packageJSON.version) .version('Version ' + packageJSON.version)

View File

@@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { renderModalStates } from './tab.js'; import { renderModalStates } from './tab';
import type { Tab, TabSnapshot } from './tab.js'; import type { Tab, TabSnapshot } from './tab';
import type { ImageContent, TextContent } from '@modelcontextprotocol/sdk/types.js'; import type { ImageContent, TextContent } from '@modelcontextprotocol/sdk/types.js';
import type { Context } from './context.js'; import type { Context } from './context';
export class Response { export class Response {
private _result: string[] = []; private _result: string[] = [];

View File

@@ -17,13 +17,13 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { Response } from './response.js'; import { Response } from './response';
import { logUnhandledError } from './utils/log.js'; import { logUnhandledError } from './utils/log';
import { outputFile } from './config.js'; import { outputFile } from './config';
import type { FullConfig } from './config.js'; import type { FullConfig } from './config';
import type * as actions from './actions.js'; import type * as actions from './actions';
import type { Tab, TabSnapshot } from './tab.js'; import type { Tab, TabSnapshot } from './tab';
type LogEntry = { type LogEntry = {
timestamp: number; timestamp: number;

View File

@@ -16,12 +16,12 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import * as playwright from 'playwright'; import * as playwright from 'playwright';
import { callOnPageNoTrace, waitForCompletion } from './tools/utils.js'; import { callOnPageNoTrace, waitForCompletion } from './tools/utils';
import { logUnhandledError } from './utils/log.js'; import { logUnhandledError } from './utils/log';
import { ManualPromise } from './mcp/manualPromise.js'; import { ManualPromise } from './mcp/manualPromise';
import { ModalState } from './tools/tool.js'; import { ModalState } from './tools/tool';
import type { Context } from './context.js'; import type { Context } from './context';
type PageEx = playwright.Page & { type PageEx = playwright.Page & {
_snapshotForAI: () => Promise<string>; _snapshotForAI: () => Promise<string>;

View File

@@ -14,26 +14,26 @@
* limitations under the License. * limitations under the License.
*/ */
import common from './tools/common.js'; import common from './tools/common';
import console from './tools/console.js'; import console from './tools/console';
import dialogs from './tools/dialogs.js'; import dialogs from './tools/dialogs';
import evaluate from './tools/evaluate.js'; import evaluate from './tools/evaluate';
import files from './tools/files.js'; import files from './tools/files';
import form from './tools/form.js'; import form from './tools/form';
import install from './tools/install.js'; import install from './tools/install';
import keyboard from './tools/keyboard.js'; import keyboard from './tools/keyboard';
import mouse from './tools/mouse.js'; import mouse from './tools/mouse';
import navigate from './tools/navigate.js'; import navigate from './tools/navigate';
import network from './tools/network.js'; import network from './tools/network';
import pdf from './tools/pdf.js'; import pdf from './tools/pdf';
import snapshot from './tools/snapshot.js'; import snapshot from './tools/snapshot';
import tabs from './tools/tabs.js'; import tabs from './tools/tabs';
import screenshot from './tools/screenshot.js'; import screenshot from './tools/screenshot';
import wait from './tools/wait.js'; import wait from './tools/wait';
import verify from './tools/verify.js'; import verify from './tools/verify';
import type { Tool } from './tools/tool.js'; import type { Tool } from './tools/tool';
import type { FullConfig } from './config.js'; import type { FullConfig } from './config';
export const allTools: Tool<any>[] = [ export const allTools: Tool<any>[] = [
...common, ...common,

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool, defineTool } from './tool.js'; import { defineTabTool, defineTool } from './tool';
const close = defineTool({ const close = defineTool({
capability: 'core', capability: 'core',

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
const console = defineTabTool({ const console = defineTabTool({
capability: 'core', capability: 'core',

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
const handleDialog = defineTabTool({ const handleDialog = defineTabTool({
capability: 'core', capability: 'core',

View File

@@ -15,9 +15,9 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
import { generateLocator } from './utils.js'; import { generateLocator } from './utils';
import type * as playwright from 'playwright'; import type * as playwright from 'playwright';

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
const uploadFile = defineTabTool({ const uploadFile = defineTabTool({
capability: 'core', capability: 'core',

View File

@@ -15,8 +15,8 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import { generateLocator } from './utils.js'; import { generateLocator } from './utils';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
const fillForm = defineTabTool({ const fillForm = defineTabTool({

View File

@@ -16,10 +16,9 @@
import { fork } from 'child_process'; import { fork } from 'child_process';
import path from 'path'; import path from 'path';
import url from 'url';
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTool } from './tool.js'; import { defineTool } from './tool';
const install = defineTool({ const install = defineTool({
capability: 'core-install', capability: 'core-install',
@@ -33,8 +32,7 @@ const install = defineTool({
handle: async (context, params, response) => { handle: async (context, params, response) => {
const channel = context.config.browser?.launchOptions?.channel ?? context.config.browser?.browserName ?? 'chrome'; const channel = context.config.browser?.launchOptions?.channel ?? context.config.browser?.browserName ?? 'chrome';
const cliUrl = import.meta.resolve('playwright/package.json'); const cliPath = path.join(require.resolve('playwright/package.json'), '../cli.js');
const cliPath = path.join(url.fileURLToPath(cliUrl), '..', 'cli.js');
const child = fork(cliPath, ['install', channel], { const child = fork(cliPath, ['install', channel], {
stdio: 'pipe', stdio: 'pipe',
}); });

View File

@@ -15,9 +15,9 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import { elementSchema } from './snapshot.js'; import { elementSchema } from './snapshot';
import { generateLocator } from './utils.js'; import { generateLocator } from './utils';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
const pressKey = defineTabTool({ const pressKey = defineTabTool({

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
const elementSchema = z.object({ const elementSchema = z.object({
element: z.string().describe('Human-readable element description used to obtain permission to interact with the element'), element: z.string().describe('Human-readable element description used to obtain permission to interact with the element'),

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTool, defineTabTool } from './tool.js'; import { defineTool, defineTabTool } from './tool';
const navigate = defineTool({ const navigate = defineTool({
capability: 'core', capability: 'core',

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import type * as playwright from 'playwright'; import type * as playwright from 'playwright';

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
const pdfSchema = z.object({ const pdfSchema = z.object({

View File

@@ -15,9 +15,9 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
import { generateLocator } from './utils.js'; import { generateLocator } from './utils';
import type * as playwright from 'playwright'; import type * as playwright from 'playwright';

View File

@@ -15,9 +15,9 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool, defineTool } from './tool.js'; import { defineTabTool, defineTool } from './tool';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
import { generateLocator } from './utils.js'; import { generateLocator } from './utils';
const snapshot = defineTool({ const snapshot = defineTool({
capability: 'core', capability: 'core',

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTool } from './tool.js'; import { defineTool } from './tool';
const browserTabs = defineTool({ const browserTabs = defineTool({
capability: 'core-tabs', capability: 'core-tabs',

View File

@@ -15,9 +15,9 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTabTool } from './tool.js'; import { defineTabTool } from './tool';
import * as javascript from '../utils/codegen.js'; import * as javascript from '../utils/codegen.js';
import { generateLocator } from './utils.js'; import { generateLocator } from './utils';
const verifyElement = defineTabTool({ const verifyElement = defineTabTool({
capability: 'verify', capability: 'verify',

View File

@@ -15,7 +15,7 @@
*/ */
import { z } from '../mcp/bundle.js'; import { z } from '../mcp/bundle.js';
import { defineTool } from './tool.js'; import { defineTool } from './tool';
const wait = defineTool({ const wait = defineTool({
capability: 'core', capability: 'core',

View File

@@ -16,7 +16,5 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import url from 'url';
const __filename = url.fileURLToPath(import.meta.url); export const packageJSON = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', 'package.json'), 'utf8'));
export const packageJSON = JSON.parse(fs.readFileSync(path.join(path.dirname(__filename), '..', '..', 'package.json'), 'utf8'));

View File

@@ -14,7 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
import url from 'url';
import path from 'path'; import path from 'path';
import * as mcpBundle from '../mcp/bundle.js'; import * as mcpBundle from '../mcp/bundle.js';
@@ -137,7 +136,7 @@ class VSCodeProxyBackend implements ServerBackend {
command: process.execPath, command: process.execPath,
cwd: process.cwd(), cwd: process.cwd(),
args: [ args: [
path.join(url.fileURLToPath(import.meta.url), '..', 'main.js'), path.join(__dirname, 'main.js'),
JSON.stringify(this._config), JSON.stringify(this._config),
params.connectionString, params.connectionString,
params.lib, params.lib,

View File

@@ -69,8 +69,10 @@ async function main(config: FullConfig, connectionString: string, lib: string) {
); );
} }
await main( void (async () => {
await main(
JSON.parse(process.argv[2]), JSON.parse(process.argv[2]),
process.argv[3], process.argv[3],
process.argv[4] process.argv[4]
); );
})();

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('test snapshot tool list', async ({ client }) => { test('test snapshot tool list', async ({ client }) => {
const { tools } = await client.listTools(); const { tools } = await client.listTools();

View File

@@ -14,10 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
import url from 'node:url';
import path from 'node:path'; import path from 'node:path';
import { spawnSync } from 'node:child_process'; import { spawnSync } from 'node:child_process';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('cdp server', async ({ cdpServer, startClient, server }) => { test('cdp server', async ({ cdpServer, startClient, server }) => {
await cdpServer.start(); await cdpServer.start();
@@ -84,9 +83,6 @@ test('should throw connection error and allow re-connecting', async ({ cdpServer
}); });
}); });
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
const __filename = url.fileURLToPath(import.meta.url);
test('does not support --device', async () => { test('does not support --device', async () => {
const result = spawnSync('node', [ const result = spawnSync('node', [
path.join(__filename, '../../cli.js'), '--device=Pixel 5', '--cdp-endpoint=http://localhost:1234', path.join(__filename, '../../cli.js'), '--device=Pixel 5', '--cdp-endpoint=http://localhost:1234',

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_click', async ({ client, server, mcpBrowser }) => { test('browser_click', async ({ client, server, mcpBrowser }) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -17,7 +17,7 @@
import fs from 'node:fs'; import fs from 'node:fs';
import { Config } from '../config.js'; import { Config } from '../config.js';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('config user data dir', async ({ startClient, server, mcpMode }, testInfo) => { test('config user data dir', async ({ startClient, server, mcpMode }, testInfo) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_console_messages', async ({ client, server }) => { test('browser_console_messages', async ({ client, server }) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_navigate', async ({ client, server }) => { test('browser_navigate', async ({ client, server }) => {
expect(await client.callTool({ expect(await client.callTool({

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('--device should work', async ({ startClient, server, mcpMode }) => { test('--device should work', async ({ startClient, server, mcpMode }) => {
const { client } = await startClient({ const { client } = await startClient({

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('alert dialog', async ({ client, server }) => { test('alert dialog', async ({ client, server }) => {
server.setContent('/', `<button onclick="alert('Alert')">Button</button>`, 'text/html'); server.setContent('/', `<button onclick="alert('Alert')">Button</button>`, 'text/html');

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_evaluate', async ({ client, server }) => { test('browser_evaluate', async ({ client, server }) => {
expect(await client.callTool({ expect(await client.callTool({

View File

@@ -15,7 +15,7 @@
*/ */
import fs from 'fs/promises'; import fs from 'fs/promises';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_file_upload', async ({ client, server }, testInfo) => { test('browser_file_upload', async ({ client, server }, testInfo) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -15,7 +15,6 @@
*/ */
import fs from 'fs'; import fs from 'fs';
import url from 'url';
import path from 'path'; import path from 'path';
import { chromium } from 'playwright'; import { chromium } from 'playwright';
@@ -23,7 +22,7 @@ import { test as baseTest, expect as baseExpect } from '@playwright/test';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'; import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { ListRootsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { ListRootsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { TestServer } from './testserver/index.ts'; import { TestServer } from './testserver/index';
import type { Config } from '../config'; import type { Config } from '../config';
import type { BrowserContext } from 'playwright'; import type { BrowserContext } from 'playwright';
@@ -186,8 +185,6 @@ async function createTransport(args: string[], mcpMode: TestOptions['mcpMode'],
transport: Transport, transport: Transport,
stderr: Stream | null, stderr: Stream | null,
}> { }> {
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
const __filename = url.fileURLToPath(import.meta.url);
if (mcpMode === 'docker') { if (mcpMode === 'docker') {
const dockerArgs = ['run', '--rm', '-i', '--network=host', '-v', `${test.info().project.outputDir}:/app/test-results`]; const dockerArgs = ['run', '--rm', '-i', '--network=host', '-v', `${test.info().project.outputDir}:/app/test-results`];
const transport = new StdioClientTransport({ const transport = new StdioClientTransport({
@@ -202,7 +199,7 @@ async function createTransport(args: string[], mcpMode: TestOptions['mcpMode'],
const transport = new StdioClientTransport({ const transport = new StdioClientTransport({
command: 'node', command: 'node',
args: [path.join(path.dirname(__filename), '../cli.js'), ...args], args: [path.join(__dirname, '../cli.js'), ...args],
cwd: path.dirname(test.info().config.configFile!), cwd: path.dirname(test.info().config.configFile!),
stderr: 'pipe', stderr: 'pipe',
env: { env: {

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_fill_form (textbox)', async ({ client, server }) => { test('browser_fill_form (textbox)', async ({ client, server }) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
for (const mcpHeadless of [false, true]) { for (const mcpHeadless of [false, true]) {
test.describe(`mcpHeadless: ${mcpHeadless}`, () => { test.describe(`mcpHeadless: ${mcpHeadless}`, () => {

View File

@@ -14,20 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
import fs from 'node:fs'; import fs from 'fs';
import url from 'node:url';
import { ChildProcess, spawn } from 'node:child_process'; import { ChildProcess, spawn } from 'child_process';
import path from 'node:path'; import path from 'path';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { test as baseTest, expect } from './fixtures.js'; import { test as baseTest, expect } from './fixtures';
import type { Config } from '../config.d.ts'; import type { Config } from '../config.d.ts';
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
const __filename = url.fileURLToPath(import.meta.url);
const test = baseTest.extend<{ serverEndpoint: (options?: { args?: string[], noPort?: boolean }) => Promise<{ url: URL, stderr: () => string }> }>({ const test = baseTest.extend<{ serverEndpoint: (options?: { args?: string[], noPort?: boolean }) => Promise<{ url: URL, stderr: () => string }> }>({
serverEndpoint: async ({ mcpHeadless }, use, testInfo) => { serverEndpoint: async ({ mcpHeadless }, use, testInfo) => {
let cp: ChildProcess | undefined; let cp: ChildProcess | undefined;

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('stitched aria frames', async ({ client }) => { test('stitched aria frames', async ({ client }) => {
expect(await client.callTool({ expect(await client.callTool({

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_install', async ({ client, mcpBrowser }) => { test('browser_install', async ({ client, mcpBrowser }) => {
test.skip(mcpBrowser !== 'chromium', 'Test only chromium'); test.skip(mcpBrowser !== 'chromium', 'Test only chromium');

View File

@@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import { test, expect, formatOutput } from './fixtures.js'; import { test, expect, formatOutput } from './fixtures';
test('test reopen browser', async ({ startClient, server, mcpMode }) => { test('test reopen browser', async ({ startClient, server, mcpMode }) => {
const { client, stderr } = await startClient(); const { client, stderr } = await startClient();

View File

@@ -15,7 +15,7 @@
*/ */
import child_process from 'child_process'; import child_process from 'child_process';
import fs from 'fs/promises'; import fs from 'fs/promises';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('library can be used from CommonJS', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright-mcp/issues/456' } }, async ({}, testInfo) => { test('library can be used from CommonJS', { annotation: { type: 'issue', description: 'https://github.com/microsoft/playwright-mcp/issues/456' } }, async ({}, testInfo) => {
const file = testInfo.outputPath('main.cjs'); const file = testInfo.outputPath('main.cjs');

View File

@@ -21,7 +21,7 @@ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/
import { runMainBackend, runOnPauseBackendLoop } from '../src/mcp/mdb.js'; import { runMainBackend, runOnPauseBackendLoop } from '../src/mcp/mdb.js';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
import type * as mcpServer from '../src/mcp/server.js'; import type * as mcpServer from '../src/mcp/server.js';
import type { ServerBackendOnPause } from '../src/mcp/mdb.js'; import type { ServerBackendOnPause } from '../src/mcp/mdb.js';

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_network_requests', async ({ client, server }) => { test('browser_network_requests', async ({ client, server }) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('save as pdf unavailable', async ({ startClient, server }) => { test('save as pdf unavailable', async ({ startClient, server }) => {
const { client } = await startClient(); const { client } = await startClient();

View File

@@ -18,7 +18,7 @@ import fs from 'fs';
import path from 'path'; import path from 'path';
import { pathToFileURL } from 'url'; import { pathToFileURL } from 'url';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
import { createHash } from '../src/utils/guid.js'; import { createHash } from '../src/utils/guid.js';
const p = process.platform === 'win32' ? 'c:\\non\\existent\\folder' : '/non/existent/folder'; const p = process.platform === 'win32' ? 'c:\\non\\existent\\folder' : '/non/existent/folder';

View File

@@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_take_screenshot (viewport)', async ({ startClient, server }, testInfo) => { test('browser_take_screenshot (viewport)', async ({ startClient, server }, testInfo) => {
const { client } = await startClient({ const { client } = await startClient({

View File

@@ -17,7 +17,7 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('session log should record tool calls', async ({ startClient, server }, testInfo) => { test('session log should record tool calls', async ({ startClient, server }, testInfo) => {
const { client, stderr } = await startClient({ const { client, stderr } = await startClient({

View File

@@ -14,20 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
import fs from 'node:fs'; import fs from 'fs';
import url from 'node:url';
import { ChildProcess, spawn } from 'node:child_process'; import { ChildProcess, spawn } from 'child_process';
import path from 'node:path'; import path from 'path';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'; import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { test as baseTest, expect } from './fixtures.js'; import { test as baseTest, expect } from './fixtures';
import type { Config } from '../config.d.ts'; import type { Config } from '../config.d.ts';
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
const __filename = url.fileURLToPath(import.meta.url);
const test = baseTest.extend<{ serverEndpoint: (options?: { args?: string[], noPort?: boolean }) => Promise<{ url: URL, stderr: () => string }> }>({ const test = baseTest.extend<{ serverEndpoint: (options?: { args?: string[], noPort?: boolean }) => Promise<{ url: URL, stderr: () => string }> }>({
serverEndpoint: async ({ mcpHeadless }, use, testInfo) => { serverEndpoint: async ({ mcpHeadless }, use, testInfo) => {
let cp: ChildProcess | undefined; let cp: ChildProcess | undefined;

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
import type { Client } from '@modelcontextprotocol/sdk/client/index.js'; import type { Client } from '@modelcontextprotocol/sdk/client/index.js';

View File

@@ -16,7 +16,6 @@
*/ */
import fs from 'fs'; import fs from 'fs';
import url from 'node:url';
import http from 'http'; import http from 'http';
import https from 'https'; import https from 'https';
import path from 'path'; import path from 'path';
@@ -25,9 +24,6 @@ import debug from 'debug';
const fulfillSymbol = Symbol('fulfil callback'); const fulfillSymbol = Symbol('fulfil callback');
const rejectSymbol = Symbol('reject callback'); const rejectSymbol = Symbol('reject callback');
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
const __filename = url.fileURLToPath(import.meta.url);
export class TestServer { export class TestServer {
private _server: http.Server; private _server: http.Server;
readonly debugServer: any; readonly debugServer: any;

View File

@@ -16,7 +16,7 @@
import fs from 'fs'; import fs from 'fs';
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('check that trace is saved', async ({ startClient, server, mcpMode }, testInfo) => { test('check that trace is saved', async ({ startClient, server, mcpMode }, testInfo) => {
const outputDir = testInfo.outputPath('output'); const outputDir = testInfo.outputPath('output');

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_type', async ({ client, server }) => { test('browser_type', async ({ client, server }) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test.use({ mcpArgs: ['--caps=verify'] }); test.use({ mcpArgs: ['--caps=verify'] });

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_connect(vscode) works', async ({ startClient, playwright, browserName }) => { test('browser_connect(vscode) works', async ({ startClient, playwright, browserName }) => {
const { client } = await startClient({ const { client } = await startClient({
@@ -27,7 +27,7 @@ test('browser_connect(vscode) works', async ({ startClient, playwright, browserN
name: 'browser_connect', name: 'browser_connect',
arguments: { arguments: {
connectionString: server.wsEndpoint(), connectionString: server.wsEndpoint(),
lib: import.meta.resolve('playwright'), lib: require.resolve('playwright'),
} }
})).toHaveResponse({ })).toHaveResponse({
result: 'Successfully connected.' result: 'Successfully connected.'

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('browser_wait_for(text)', async ({ client, server }) => { test('browser_wait_for(text)', async ({ client, server }) => {
server.setContent('/', ` server.setContent('/', `

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { test, expect } from './fixtures.js'; import { test, expect } from './fixtures';
test('do not falsely advertise user agent as a test driver', async ({ client, server, mcpBrowser }) => { test('do not falsely advertise user agent as a test driver', async ({ client, server, mcpBrowser }) => {
test.skip(mcpBrowser === 'firefox'); test.skip(mcpBrowser === 'firefox');

View File

@@ -1,10 +1,9 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ESNext", "target": "ES2019",
"esModuleInterop": true, "esModuleInterop": true,
"moduleResolution": "nodenext",
"strict": true, "strict": true,
"module": "NodeNext", "module": "commonjs",
"rootDir": "src", "rootDir": "src",
"outDir": "./lib", "outDir": "./lib",
"resolveJsonModule": true "resolveJsonModule": true

View File

@@ -18,13 +18,10 @@
// @ts-check // @ts-check
import fs from 'fs'; const fs = require('fs');
import ts from 'typescript'; const ts = require('typescript');
import path from 'path'; const path = require('path');
import Module from 'module'; const Module = require('module');
const __dirname = path.dirname(new URL(import.meta.url).pathname);
const require = Module.createRequire(import.meta.url);
const builtins = new Set(Module.builtinModules); const builtins = new Set(Module.builtinModules);

View File

@@ -22,8 +22,6 @@ import path from 'path';
import child_process from 'child_process'; import child_process from 'child_process';
import { argv } from 'process'; import { argv } from 'process';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
const readJSON = async (filePath) => JSON.parse(await fs.promises.readFile(filePath, 'utf8')); const readJSON = async (filePath) => JSON.parse(await fs.promises.readFile(filePath, 'utf8'));
const writeJSON = async (filePath, json) => { const writeJSON = async (filePath, json) => {
await fs.promises.writeFile(filePath, JSON.stringify(json, null, 2) + '\n'); await fs.promises.writeFile(filePath, JSON.stringify(json, null, 2) + '\n');

View File

@@ -16,13 +16,12 @@
*/ */
// @ts-check // @ts-check
import fs from 'node:fs' const fs = require('fs')
import path from 'node:path' const path = require('path')
import url from 'node:url' const { zodToJsonSchema } = require('zod-to-json-schema')
import zodToJsonSchema from 'zod-to-json-schema' const { execSync } = require('child_process');
import { execSync } from 'node:child_process';
import { allTools } from '../lib/tools.js'; const { allTools } = require('../lib/tools.js');
const capabilities = { const capabilities = {
'core': 'Core automation', 'core': 'Core automation',
@@ -35,11 +34,8 @@ const capabilities = {
const toolsByCapability = Object.fromEntries(Object.entries(capabilities).map(([capability, title]) => [title, allTools.filter(tool => tool.capability === capability).sort((a, b) => a.schema.name.localeCompare(b.schema.name))])); const toolsByCapability = Object.fromEntries(Object.entries(capabilities).map(([capability, title]) => [title, allTools.filter(tool => tool.capability === capability).sort((a, b) => a.schema.name.localeCompare(b.schema.name))]));
// NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename.
const __filename = url.fileURLToPath(import.meta.url);
/** /**
* @param {import('../src/tools/tool.js').ToolSchema<any>} tool * @param {import('../src/mcp/tool.js').ToolSchema<any>} tool
* @returns {string[]} * @returns {string[]}
*/ */
function formatToolForReadme(tool) { function formatToolForReadme(tool) {