Repository navigation
[Website] Add WebMCP support to the Playground website - #3298
Conversation
9078c79 to
897f99b
Compare
5c3bd15 to
40515af
Compare
e39ba48 to
e6daa82
Compare
There was a problem hiding this comment.
Pull request overview
Adds WebMCP (navigator.modelContext) support to the Playground website so browser-native AI agents can invoke Playground tools directly, while preserving the existing WebSocket MCP bridge as an opt-in path.
Changes:
- Registers Playground toolset via a new
registerWebMCPTools()API and wires it into the website initialization flow. - Refactors bridge initialization to share a single
mcpConfigbetween WebMCP registration and the WebSocket bridge. - Reorganizes tests and adds Vitest/Playwright configuration plus new WebMCP e2e coverage.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/playground/website/src/lib/state/redux/init-mcp-bridge.ts | Creates shared mcpConfig, registers WebMCP tools on load, and gates only the WebSocket bridge behind ?mcp=yes. |
| packages/playground/mcp/vite.config.ts | Adds Vitest configuration for unit tests under tests/unit. |
| packages/playground/mcp/tsconfig.spec.json | Introduces TS config for tests/spec compilation. |
| packages/playground/mcp/tsconfig.json | Adds project reference to tsconfig.spec.json. |
| packages/playground/mcp/tests/unit/bridge-server.spec.ts | Updates import path after test directory restructure. |
| packages/playground/mcp/tests/e2e/webmcp.spec.ts | Adds Playwright e2e tests for WebMCP tool registration/execution using a mocked navigator.modelContext. |
| packages/playground/mcp/tests/e2e/mcp-tools.spec.ts | Fixes relative paths for server startup after moving e2e tests under tests/e2e. |
| packages/playground/mcp/src/webmcp.ts | New module registering tools with navigator.modelContext and implementing site-management tools. |
| packages/playground/mcp/src/client.ts | Re-exports registerWebMCPTools from the package entry point. |
| packages/playground/mcp/project.json | Splits test target into test:unit (Vitest) and test:e2e (Playwright), with test:mcp depending on both. |
| packages/playground/mcp/playwright.config.ts | Updates Playwright testDir to tests/e2e. |
| packages/playground/mcp/README.md | Documents WebMCP support and draft-status caveat. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…3416) `registerWebMCPTools()` would re-register tools on every call (HMR, re-initialization), potentially causing duplicate tool exposure. The fix checks `navigator.modelContext.tools` directly to skip already-registered tools. ## Changes - **`webmcp.ts`**: Add `readonly tools: ModelContextTool[]` to the `ModelContext` interface; guard each `registerTool()` call by checking `navigator.modelContext.tools` for an existing tool with the same name - **`webmcp.ts`**: Remove unused `clearContext()` and `unregisterTool()` from the `ModelContext` interface - **`webmcp.spec.ts`**: Add a `tools` getter to the test mock returning the registered tools array; remove the now-unused `clearContext` and `unregisterTool` stubs ```ts for (const tool of tools) { const alreadyRegistered = navigator.modelContext.tools.some( (t) => t.name === tool.name ); if (!alreadyRegistered) { navigator.modelContext.registerTool(tool); } } ``` <!-- START COPILOT CODING AGENT TIPS --> --- 📍 Connect Copilot coding agent with [Jira](https://gh.io/cca-jira-docs), [Azure Boards](https://gh.io/cca-azure-boards-docs) or [Linear](https://gh.io/cca-linear-docs) to delegate work to Copilot in one click without leaving your project management tool. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bgrgicak <1199991+bgrgicak@users.noreply.github.com> Co-authored-by: Bero <berislav.grgicak@gmail.com>
…ebsite-webmcp-support
| ): ModelContextTool[] { | ||
| function getActiveSite() { | ||
| const sites = config.getSites(); | ||
| const active = sites.find((s) => s.isActive); |
There was a problem hiding this comment.
We can have a generic getActiveSIte(config). We have the same code in getActiveClient
There was a problem hiding this comment.
Good point, I added a shared getActiveSite in dccde37
| webmcpPage: async ({ page }, use) => { | ||
| // WebMCP (navigator.modelContext) is only available in | ||
| // Chrome 146+ Canary behind the "WebMCP for testing" | ||
| // flag. Playwright uses a stock Chromium that doesn't |
There was a problem hiding this comment.
Let's add chrome://flags/#enable-webmcp-testing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Motivation for the change, related issues
Adds WebMCP support to the Playground website, so browser-native AI agents (via Chrome's
navigator.modelContextAPI) can interact with Playground directly — no WebSocket bridge or Node.js server needed.The MCP server in #3290 requires a Node.js process as an intermediary between AI clients and the browser. Chrome's experimental WebMCP API (
navigator.modelContext) lets the browser expose tools directly to built-in AI features, removing that hop entirely.Implementation details
WebMCP tool registration
webmcp.ts— New module that registers all 16 playground tools withnavigator.modelContext.registerTool(). CallsPlaygroundClientdirectly instead of going through the WebSocket bridge. Silently no-ops whennavigator.modelContextis unavailable.client.ts— ExportsregisterWebMCPToolsalongsidestartMcpBridgefrom the@wp-playground/mcp/cliententry point.README.md— Adds a WebMCP section documenting the feature and its draft status.Shared
mcpConfigrefactorinit-mcp-bridge.ts— Extracts themcpConfigobject (site listing, client lookup, save, rename) so it's created once and shared betweenregisterWebMCPTools()andstartMcpBridge(). WebMCP tools are registered unconditionally on page load; the WebSocket bridge still requires?mcp=yes.Test reorganization and infrastructure
e2e/totests/e2e/and unit tests fromsrc/totests/unit/for consistent structure.test:mcptarget inproject.jsonintotest:unit(Vitest) andtest:e2e(Playwright), withtest:mcpas a noop that depends on both.tsconfig.spec.jsonand Vitest config invite.config.tsto support unit tests in the newtests/directory.webmcp.spec.ts— Playwright e2e tests that mocknavigator.modelContextviaaddInitScript, then exercise tool registration and execution (PHP, filesystem, site management).Testing Instructions