From 4532af33fbe9cbb3a8c8f1d3676cdbd1ea3571d4 Mon Sep 17 00:00:00 2001 From: StanPonomarev Date: Sat, 12 Sep 2026 19:17:30 +0200 Subject: [PATCH] fix: playwritgt timing out --- README.md | 4 +++- src/index.ts | 6 +++++- src/playwright.ts | 10 +--------- tests/plugin.test.ts | 22 ++++++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 1197842..46a7779 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,9 @@ For an installed plugin, use `./plugins/stanp-opencode` as the plugin package pa ## Playwright -The plugin prefers a local Playwright MCP installation. If no local installation is available, Docker is required for the automatic fallback. Existing `playwright` configuration is preserved. +The plugin prefers a local Playwright MCP installation. If ordinary Playwright is installed, it can download and run the MCP package with `npx`; otherwise Docker is required for the automatic fallback. Automatically configured servers allow five minutes for startup because the first launch may need to download a package or container image. Docker reuses its cached image on later launches. Existing `playwright` configuration, including its timeout, is preserved. + +If `opencode mcp list` reports `MCP error -32001: Request timed out`, prefetch the Docker fallback with `docker pull mcr.microsoft.com/playwright/mcp`, or install `@playwright/mcp` in the project so the plugin can launch it directly. Then reconnect the server from `/mcps` or restart OpenCode. A custom `playwright` entry under `mcp.servers` can also set its own `timeout.startup` in milliseconds. ## Uninstall diff --git a/src/index.ts b/src/index.ts index 535ea95..3a93cfa 100644 --- a/src/index.ts +++ b/src/index.ts @@ -118,7 +118,11 @@ export default Plugin.define({ await context.mcp.transform((editor) => { if (!editor.get("playwright")) - editor.set("playwright", { type: "local", command: playwrightCommand }); + editor.set("playwright", { + type: "local", + command: playwrightCommand, + timeout: { startup: 300_000 }, + }); hasCodegraph = editor.get("codegraph") !== undefined; if (hasCodegraph) editor.update("codegraph", (server) => { diff --git a/src/playwright.ts b/src/playwright.ts index a406430..2a7beed 100644 --- a/src/playwright.ts +++ b/src/playwright.ts @@ -3,15 +3,7 @@ import { constants } from "node:fs"; import { dirname, join, parse, resolve } from "node:path"; import { z } from "zod"; -const dockerCommand = [ - "docker", - "run", - "-i", - "--rm", - "--init", - "--pull=always", - "mcr.microsoft.com/playwright/mcp", -]; +const dockerCommand = ["docker", "run", "-i", "--rm", "--init", "mcr.microsoft.com/playwright/mcp"]; const directPackageManifest = z.object({ name: z.literal("@playwright/mcp"), bin: z.string(), diff --git a/tests/plugin.test.ts b/tests/plugin.test.ts index 92384c7..1ae4611 100644 --- a/tests/plugin.test.ts +++ b/tests/plugin.test.ts @@ -33,7 +33,13 @@ async function host( options: Plugin.Context["options"] = { provider: "test" }, configuredMcp: Record< string, - { type: "local"; command: string[]; codemode?: boolean; disabled?: boolean } + { + type: "local"; + command: string[]; + codemode?: boolean; + disabled?: boolean; + timeout?: { startup?: number; catalog?: number; execution?: number }; + } > = {}, configuredMcpTools: string[] = [], directory = "/test", @@ -440,6 +446,7 @@ test("playwright MCP prefers direct MCP, uses npx for Playwright, and preserves expect(local.mcpServers.get("playwright")).toEqual({ type: "local", command: [executable], + timeout: { startup: 300_000 }, }); const globalPackage = join(root, "global", "@playwright", "mcp"); @@ -530,15 +537,8 @@ test("playwright MCP prefers direct MCP, uses npx for Playwright, and preserves const fallback = await host(); expect(fallback.mcpServers.get("playwright")).toEqual({ type: "local", - command: [ - "docker", - "run", - "-i", - "--rm", - "--init", - "--pull=always", - "mcr.microsoft.com/playwright/mcp", - ], + command: ["docker", "run", "-i", "--rm", "--init", "mcr.microsoft.com/playwright/mcp"], + timeout: { startup: 300_000 }, }); const existing = await host( @@ -549,6 +549,7 @@ test("playwright MCP prefers direct MCP, uses npx for Playwright, and preserves type: "local", command: ["custom-playwright-mcp"], disabled: true, + timeout: { startup: 12_345 }, }, docs: { type: "local", command: ["docs"], codemode: true }, }, @@ -557,6 +558,7 @@ test("playwright MCP prefers direct MCP, uses npx for Playwright, and preserves type: "local", command: ["custom-playwright-mcp"], disabled: true, + timeout: { startup: 12_345 }, }); expect(existing.mcpServers.get("docs")?.codemode).toBe(true); } finally {