chore: refactor server, prepare for browser reuse (#490)

This commit is contained in:
Pavel Feldman
2025-05-28 16:55:47 -07:00
committed by GitHub
parent 3cd74a824a
commit 54ed7c3200
7 changed files with 105 additions and 118 deletions

View File

@@ -15,17 +15,12 @@
*/
import url from 'node:url';
import http from 'node:http';
import { spawn } from 'node:child_process';
import path from 'node:path';
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.
@@ -55,6 +50,7 @@ test('sse transport', async ({ serverEndpoint }) => {
const client = new Client({ name: 'test', version: '1.0.0' });
await client.connect(transport);
await client.ping();
await client.close();
});
test('streamable http transport', async ({ serverEndpoint }) => {
@@ -64,46 +60,3 @@ test('streamable http transport', async ({ serverEndpoint }) => {
await client.ping();
expect(transport.sessionId, 'has session support').toBeDefined();
});
test('sse transport via public API', async ({ server }, testInfo) => {
const userDataDir = testInfo.outputPath('user-data-dir');
const sessions = new Map<string, SSEServerTransport>();
const mcpServer = http.createServer(async (req, res) => {
if (req.method === 'GET') {
const connection = await createConnection({
browser: {
userDataDir,
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<void>(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=e1]: Hello, world!`);
await client.close();
mcpServer.close();
});