mcp-server.ts•2.5 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
import { Browser, chromium, Page } from 'playwright';
import { Response, Request } from 'express';
import { z } from 'zod/v3';
let page: Page | null = null;
let browser: Browser | null = null;
/**
* Handles an incoming MCP request
*
* @param server MCP server instance
* @param request Incoming HTTP request
* @param response Outgoing HTTP response
*/
export async function handleRequest(
server: McpServer,
request: Request,
response: Response
) {
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
enableJsonResponse: true,
});
response.on('close', () => {
transport.close();
});
await server.connect(transport);
await transport.handleRequest(request, response, request.body);
}
/**
* Factory function to create and configure an MCP server instance
* @returns {McpServer} Configured MCP server instance
*/
export const mcpServerFactory = (): McpServer => {
const server = new McpServer({
name: 'Browser Inspector MCP Server',
version: '1.0.0',
});
/**
* Tool to open a web page using Playwrights
*/
server.registerTool(
'openPage',
{
title: 'Open a web page',
description: 'Opens a web page',
inputSchema: { url: z.string().url() },
outputSchema: { status: z.string() },
},
async ({ url }) => {
if (!browser) {
browser = await chromium.launch({ headless: true });
page = await browser.newPage();
}
await page?.goto(url);
const output = { status: 'Page opened successfully' };
return {
content: [{ type: 'text', text: JSON.stringify(output) }],
structuredContent: output,
};
}
);
/**
* Tool to get the title of the currently opened web page
*/
server.registerTool(
'getPageTitle',
{
title: 'Get Page Title',
description: 'Retrieves the title of the currently opened web page',
inputSchema: {},
outputSchema: { title: z.string() },
},
async () => {
if (!page) {
throw new Error('No page is currently opened.');
}
const title = await page.title();
const output = { title };
return {
content: [{ type: 'text', text: JSON.stringify(output) }],
structuredContent: output,
};
}
);
return server;
};