关于我
MCP 全解:从理解到深度开发开发案例集锦

Puppeteer 控制本地浏览器

用 MCP 底层 Server 类封装 Puppeteer,让 Cursor 直接驱动本地浏览器完成导航、搜索等任务——附核心实现与完整仓库地址。

MCP 本质上是用一种统一的模型解决 LLM 与数据源交互的问题,充满想象空间,例如可以用 MCP 协议控制本地浏览器:

使用 browser-mcp 打开百度,并搜索什么是 Monorepo

之后,Cursor 会自行根据任务拆解子任务,最终实现 prompt 提及的诉求:

🖼️ 配图待补:TOT4bEQgbopNudxrAZ4cC78Sn5e

代码实现也很简单(完整代码在 github),核心:

import { Server } from '@modelcontextprotocol/sdk/server/index.js';

// Define the tools once to avoid repetition
const TOOLS: Tool[] = [
  {
    name: 'puppeteer_navigate',
    description: 'Navigate to a URL',
    inputSchema: {
      type: 'object',
      properties: {
        url: { type: 'string' },
      },
      required: ['url'],
    },
  }
  // ... other tools
];

async function ensureBrowser(server: Server) {
  if (!browser) {
    const npx_args = { headless: false };
    const docker_args = {
      headless: true,
      args: ['--no-sandbox', '--single-process', '--no-zygote'],
    };
    browser = await puppeteer.launch(process.env.DOCKER_CONTAINER ? docker_args : npx_args);
    const pages = await browser.pages();
    page = pages[0];
  }
  return page!;
}

async function handleToolCall(name: string, args: any, server: Server): Promise<CallToolResult> {
  const page = await ensureBrowser(server);

  switch (name) {
    case 'puppeteer_navigate':
      await page.goto(args.url);
      return {
        content: [
          {
            type: 'text',
            text: `Navigated to ${args.url}`,
          },
        ],
        isError: false,
      };
      // ...
  }
}

export const createMcp = async () => {
  const server = new Server(
    {
      name: 'example-servers/puppeteer',
      version: '0.1.0',
    },
    {
      capabilities: {
        resources: {},
        tools: {},
      },
    }
  );

  server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: TOOLS,
  }));

  server.setRequestHandler(CallToolRequestSchema, async (request) =>
    handleToolCall(request.params.name, request.params.arguments ?? {}, server)
  );

  return server;
};

关键点:

  1. 相比前面的示例,这里使用了 MCP 的底层 Server 类而不是高级 McpServer 类,更底层也更灵活可控;
  2. 使用统一的 TOOLS 数组定义所有可用工具,每个工具都遵循 MCP 规范,包含 namedescriptioninputSchema;
  3. ensureBrowser 函数根据上下文状态创建 puppeteer 实例;
  4. 使用 handleToolCall 函数统一处理所有工具调用,并返回标准化的 CallToolResult 响应;
  5. 最重要的一点,使用底层 Server 类时,需要通过 server.setRequestHandler 接口定义协议内容,例如上述示例中注册 ListToolsRequestSchema 返回可用工具列表,注册 CallToolRequestSchema 处理具体的工具调用。

建议到 github 上查看完整实例代码:github.com/Tecvan-fe/mcp-demo/blob/main/packages/3_puppeteer