From 65716b60dd5bc18f0504c15a7b05e86ed4ef1931 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Fri, 9 May 2025 21:50:38 +0200 Subject: [PATCH] fix: createConnection() via public API (#384) Fixes https://github.com/microsoft/playwright-mcp/issues/382 --- README.md | 2 +- index.js | 2 +- src/index.ts | 4 ++-- tests/sse.spec.ts | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 846f218..e4560b9 100644 --- a/README.md +++ b/README.md @@ -231,7 +231,7 @@ http.createServer(async (req, res) => { // ... // Creates a headless Playwright MCP server with SSE transport - const connection = await createConnection({ headless: true }); + const connection = await createConnection({ browser: { launchOptions: { headless: true } } }); const transport = new SSEServerTransport('/messages', res); await connection.connect(transport); diff --git a/index.js b/index.js index d4b94fb..74caea4 100755 --- a/index.js +++ b/index.js @@ -16,4 +16,4 @@ */ import { createConnection } from './lib/index'; -export default { createConnection }; +export { createConnection }; diff --git a/src/index.ts b/src/index.ts index 9fc7633..a7169e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,10 +14,10 @@ * limitations under the License. */ -import { Connection } from './connection.js'; +import { Connection, createConnection as createConnectionImpl } from './connection.js'; import type { Config } from '../config.js'; export async function createConnection(config: Config = {}): Promise { - return createConnection(config); + return createConnectionImpl(config); } diff --git a/tests/sse.spec.ts b/tests/sse.spec.ts index 21495bc..325055e 100644 --- a/tests/sse.spec.ts +++ b/tests/sse.spec.ts @@ -15,14 +15,19 @@ */ import url from 'node:url'; +import http from 'node:http'; import { spawn } from 'node:child_process'; import path from 'node:path'; -import { test as baseTest } from './fixtures.js'; -import { expect } from 'playwright/test'; +import type { AddressInfo } from 'node:net'; import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'; +import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { createConnection } from '@playwright/mcp'; + +import { test as baseTest, expect } from './fixtures.js'; + // NOTE: Can be removed when we drop Node.js 18 support and changed to import.meta.filename. const __filename = url.fileURLToPath(import.meta.url); @@ -59,3 +64,40 @@ test('streamable http transport', async ({ serverEndpoint }) => { await client.ping(); expect(transport.sessionId, 'has session support').toBeDefined(); }); + +test('sse transport via public API', async ({ server }) => { + const sessions = new Map(); + const mcpServer = http.createServer(async (req, res) => { + if (req.method === 'GET') { + const connection = await createConnection({ browser: { launchOptions: { headless: true } } }); + const transport = new SSEServerTransport('/sse', res); + sessions.set(transport.sessionId, transport); + await connection.connect(transport); + } else if (req.method === 'POST') { + const url = new URL(`http://localhost${req.url}`); + const sessionId = url.searchParams.get('sessionId'); + if (!sessionId) { + res.statusCode = 400; + return res.end('Missing sessionId'); + } + const transport = sessions.get(sessionId); + if (!transport) { + res.statusCode = 404; + return res.end('Session not found'); + } + void transport.handlePostMessage(req, res); + } + }); + await new Promise(resolve => mcpServer.listen(0, () => resolve())); + const serverUrl = `http://localhost:${(mcpServer.address() as AddressInfo).port}/sse`; + const transport = new SSEClientTransport(new URL(serverUrl)); + const client = new Client({ name: 'test', version: '1.0.0' }); + await client.connect(transport); + await client.ping(); + expect(await client.callTool({ + name: 'browser_navigate', + arguments: { url: server.HELLO_WORLD }, + })).toContainTextContent(`- generic [ref=s1e2]: Hello, world!`); + await client.close(); + mcpServer.close(); +});