HTML实时同步服务器

一个基于模型上下文协议(MCP)构建的实时HTML同步服务器,支持热重载功能,使AI代理能够动态创建、更新和销毁HTML页面,所有连接的客户端都能实时接收更新。

  • by yujiosaka
  • TypeScript
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 yujiosaka/mcp-html-sync-server

使用说明

MCP HTML同步服务器

行为准则 | 贡献 | 安全

一个具有热重载功能的实时HTML同步服务器,使用模型上下文协议(MCP)构建。该服务器使AI代理能够动态创建、更新和销毁HTML页面,所有连接的客户端都能实时接收更新。

特性

  • 实时HTML同步:创建和更新HTML内容,并向所有连接的客户端提供即时更新
  • WebSocket热重加载:所有连接的浏览器在内容更改时自动刷新
  • 脚本管理:通过CDN URL或内联内容向页面添加JavaScript脚本
  • 样式表管理:通过CDN URL向页面添加CSS样式表
  • MCP集成:专为使用模型上下文协议的AI代理而设计
  • 页面生命周期管理:在可配置的时间段后自动过期页面
  • 连接限制:可配置的最大页数,自动清理最旧的页面
  • 简单API:易于使用的MCP工具,用于页面创建、更新和销毁
  • 轻量级:最小的依赖关系和高效的资源使用

建筑

flowchart LR
    AI[AI Agent] -->|MCP Protocol| MCP[MCP HTML Sync Server]
    MCP -->|Create/Update/Destroy/AddScripts/AddStylesheets| PM[Page Manager]
    PM -->|Store| Pages[(HTML Pages, Scripts & Stylesheets)]
    User[User Browser] -->|HTTP Request| HTTP[HTTP Server]
    HTTP -->|Fetch Page, Scripts & Stylesheets| PM
    User <-->|WebSocket| WS[WebSocket Server]
    WS <-->|Real-time Updates| PM

安装

使用Docker

docker pull yujiosaka/mcp-html-sync-server
docker run -p 3000:3000 yujiosaka/mcp-html-sync-server

Docker环境变量

而不是使用 .env 文件,您可以在运行时将环境变量直接传递给Docker容器:

docker run -p 3000:3000 \
  -e SERVER_PORT=3000 \
  -e BASE_URL=http://localhost:3000/ \
  -e PAGE_MAX_AGE=1h \
  -e PAGE_MAX_COUNT=1000 \
  yujiosaka/mcp-html-sync-server

建议将此方法用于生产部署,因为它允许您在不修改容器映像的情况下配置服务器。

使用NPX

NODE_ENV=production npx mcp-html-sync-server

来源

# Clone the repository
git clone https://github.com/yujiosaka/mcp-html-sync-server.git
cd mcp-html-sync-server

# Install dependencies
bun install

# Copy the example environment file
bun run config

# Start the server
bun run start

配置

编辑 .env 配置服务器的文件:

# Host address for the HTTP server (used for binding the server)
SERVER_HOST=localhost
# Port number for the HTTP server (used for binding the server)
SERVER_PORT=3000
# Base URL for the application (used for generating view URLs)
BASE_URL=http://localhost:3000/
# Maximum age of pages before they expire (e.g., 1h = 1 hour, uses ms library format)
PAGE_MAX_AGE=1h
# Maximum number of pages that can be stored (oldest pages are removed when limit is reached)
PAGE_MAX_COUNT=1000

配置选项

选项 描述 默认值 格式
SERVER_HOST 绑定HTTP服务器的主机地址 localhost 主机名
SERVER_PORT HTTP服务器的端口号 3000 编号
BASE_URL 生成视图URL的基本URL http://localhost:3000/ URL
PAGE_MAX_AGE 过期前页面的最大年龄 1h 时间字符串(例如,1h、30m、1d)
PAGE_MAX_COUNT 要保留的最大页数 1000 个数

使用MCP

与Claude Desktop集成

将此添加到您的 claude_desktop_config.json:

码头工人

{
  "mcpServers": {
    "html-sync-server": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-p",
        "3000:3000",
        "-e", "SERVER_PORT=3000",
        "-e", "BASE_URL=http://localhost:3000/",
        "-e", "PAGE_MAX_AGE=1h",
        "-e", "PAGE_MAX_COUNT=1000",
        "yujiosaka/mcp-html-sync-server"
      ]
    }
  }
}

NPX

{
  "mcpServers": {
    "html-sync-server": {
      "command": "npx",
      "args": ["-y", "mcp-html-sync-server"],
      "env": {
        "NODE_ENV": "production"
      }
    }
  }
}

与VS代码集成

为了快速安装,请使用下面的一键安装按钮之一:

手动安装

对于手动安装,请将以下JSON块添加到VS Code中的用户设置(JSON)文件中。您可以按 Ctrl + Shift + P 和打字 Preferences: Open Settings (JSON).

您可以选择将其添加到名为的文件中 .vscode/mcp.json 在您的工作空间中。这将允许您与他人共享配置。

请注意 mcp 中不需要密钥 .vscode/mcp.json 文件。

{
  "mcp": {
    "servers": {
      "html-sync-server": {
        "command": "npx",
        "args": ["-y", "mcp-html-sync-server"],
        "env": {
          "NODE_ENV": "production"
        }
      }
    }
  }
}

对于Docker安装:

{
  "mcp": {
    "servers": {
      "html-sync-server": {
        "command": "docker",
        "args": [
          "run",
          "-i",
          "--rm",
          "-p", "3000:3000",
          "-e", "SERVER_PORT=3000",
          "-e", "BASE_URL=http://localhost:3000/",
          "-e", "PAGE_MAX_AGE=1h",
          "-e", "PAGE_MAX_COUNT=1000",
          "yujiosaka/mcp-html-sync-server"
        ]
      }
    }
  }
}

MCP工具

服务器提供以下可供AI代理使用的MCP工具:

1.创建页面

使用指定内容创建新的HTML页面。

工具名称: create_page

输入架构:

{
  "type": "object",
  "properties": {
    "body": {
      "type": "string",
      "description": "HTML content for the page body (only the inner content)"
    },
    "scripts": {
      "type": "array",
      "description": "Optional array of JavaScript scripts to include in the page",
      "items": {
        "type": "object",
        "properties": {
          "src": {
            "type": "string",
            "description": "URL for external script"
          },
          "content": {
            "type": "string",
            "description": "Content for inline script"
          }
        },
        "description": "Either src or content must be provided",
        "oneOf": [
          { "required": ["src"] },
          { "required": ["content"] }
        ]
      }
    },
    "stylesheets": {
      "type": "array",
      "description": "Optional array of CSS stylesheets to include in the page",
      "items": {
        "type": "object",
        "properties": {
          "href": {
            "type": "string",
            "description": "URL for external stylesheet"
          }
        },
        "required": ["href"]
      }
    }
  },
  "required": ["body"]
}

示例请求:

{
  "name": "create_page",
  "arguments": {
    "body": "<h1>Hello World</h1><p>This is my page content.</p><button id='confetti-btn'>Click for Confetti!</button>",
    "scripts": [
      { "src": "https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/js/bootstrap.bundle.min.js" }
    ],
    "stylesheets": [
      { "href": "https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" }
    ]
  }
}

示例响应:

{
  "content": [
    {
      "type": "text",
      "text": "Page created successfully! A URL is provided below to view your page."
    },
    {
      "type": "text",
      "text": "View your HTML page in URL: http://localhost:3000/abc123"
    },
    {
      "type": "text",
      "text": "ID: abc123\nExpires at: 2023-04-15T12:34:56.789Z\n\nUse this ID for future updates before expiration."
    }
  ],
  "metadata": {
    "id": "abc123",
    "url": "http://localhost:3000/abc123",
    "expires_at": "2023-04-15T12:34:56.789Z"
  }
}

2.更新页面

用新内容更新现有页面。所有连接的客户端都将实时看到更新。如果页面不存在(已被删除或过期),将返回错误响应。

工具名称: update_page

输入架构:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID of the page to update"
    },
    "body": {
      "type": "string",
      "description": "New HTML content for the page body (only the inner content)"
    }
  },
  "required": ["id", "body"]
}

示例请求:

{
  "name": "update_page",
  "arguments": {
    "id": "abc123",
    "body": "<h1>Updated Content</h1><p>This content has been updated.</p>"
  }
}

示例响应:

{
  "content": [
    {
      "type": "text",
      "text": "Page updated successfully! A URL is provided below to view your updated page."
    },
    {
      "type": "text",
      "text": "View your HTML page in URL: http://localhost:3000/abc123"
    },
    {
      "type": "text",
      "text": "ID: abc123\nExpires at: 2023-04-15T12:34:56.789Z\n\nUse this ID for future updates before expiration."
    }
  ],
  "metadata": {
    "id": "abc123",
    "url": "http://localhost:3000/abc123",
    "expires_at": "2023-04-15T12:34:56.789Z"
  }
}

3.销毁页面

删除页面并断开所有客户端的连接。

工具名称: destroy_page

输入架构:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID of the page to destroy"
    }
  },
  "required": ["id"]
}

示例请求:

{
  "name": "destroy_page",
  "arguments": {
    "id": "abc123"
  }
}

示例响应:

{
  "success": true
}

4.向页面添加脚本

将JavaScript脚本添加到现有页面。所有连接的客户端都将实时接收脚本。

工具名称: add_scripts

输入架构:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID of the page to add scripts to"
    },
    "scripts": {
      "type": "array",
      "description": "Array of JavaScript scripts to add to the page",
      "items": {
        "type": "object",
        "properties": {
          "src": {
            "type": "string",
            "description": "URL for external script"
          },
          "content": {
            "type": "string",
            "description": "Content for inline script"
          }
        },
        "description": "Either src or content must be provided",
        "oneOf": [
          { "required": ["src"] },
          { "required": ["content"] }
        ]
      }
    }
  },
  "required": ["id", "scripts"]
}

示例请求:

{
  "name": "add_scripts",
  "arguments": {
    "id": "abc123",
    "scripts": [
      { "content": "alert('Hello World!')" }
    ]
  }
}

示例响应:

{
  "content": [
    {
      "type": "text",
      "text": "Scripts added successfully! A URL is provided below to view your page."
    },
    {
      "type": "text",
      "text": "View your HTML page in URL: http://localhost:3000/abc123"
    },
    {
      "type": "text",
      "text": "ID: abc123\nExpires at: 2023-04-15T12:34:56.789Z\n\nUse this ID for future updates before expiration."
    }
  ],
  "metadata": {
    "id": "abc123",
    "url": "http://localhost:3000/abc123",
    "expires_at": "2023-04-15T12:34:56.789Z"
  }
}

5.向页面添加样式表

将CSS样式表添加到现有页面。所有连接的客户端都将实时接收样式表。

工具名称: add_stylesheets

输入架构:

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID of the page to add stylesheets to"
    },
    "stylesheets": {
      "type": "array",
      "description": "Array of CSS stylesheets to add to the page",
      "items": {
        "type": "object",
        "properties": {
          "href": {
            "type": "string",
            "description": "URL for external stylesheet"
          }
        },
        "required": ["href"]
      }
    }
  },
  "required": ["id", "stylesheets"]
}

示例请求:

{
  "name": "add_stylesheets",
  "arguments": {
    "id": "abc123",
    "stylesheets": [
      { "href": "https://cdn.jsdelivr.net/npm/bootstrap@5.3.5/dist/css/bootstrap.min.css" }
    ]
  }
}

示例响应:

{
  "content": [
    {
      "type": "text",
      "text": "Stylesheets added successfully! A URL is provided below to view your page."
    },
    {
      "type": "text",
      "text": "View your HTML page in URL: http://localhost:3000/abc123"
    },
    {
      "type": "text",
      "text": "ID: abc123\nExpires at: 2023-04-15T12:34:56.789Z\n\nUse this ID for future updates before expiration."
    }
  ],
  "metadata": {
    "id": "abc123",
    "url": "http://localhost:3000/abc123",
    "expires_at": "2023-04-15T12:34:56.789Z"
  }
}

运作原理

  1. AI代理通过模型上下文协议(MCP)与服务器交互
  2. MCP服务器处理创建、更新或销毁HTML页面的请求
  3. 用户通过AI代理提供的URL查看这些页面
  4. 实时更新通过WebSockets传递给所有连接的客户端

手动测试

该项目包括一个手动测试脚本(manual-test.ts)演示了如何使用MCP服务器。此脚本:

  1. 使用CDN中的画布五彩纸屑创建新的HTML页面
  2. 更新页面内容
  3. 添加样式表以触发文本动画
  4. 添加脚本以触发五彩纸屑动画
  5. 删除页面

要运行手动测试,请执行以下操作:

# Run the test script
bun manual-test.ts

该脚本将提供您可以在浏览器中打开的URL,以查看页面并观察实时更新。它使用一种交互式方法,在每个步骤之间都有确认提示,允许您在继续下一步之前验证浏览器中的更改。

此测试脚本特别适用于:

  • 验证MCP服务器是否正常工作
  • 了解创建、更新和销毁页面的流程
  • 在浏览器中观察实时WebSocket更新

发展

# Run in development mode with auto-reload
bun run dev

# Build the project
bun run build

# Run linting
bun run check

# Fix linting issues
bun run check:write

故障排除

端口已在使用中

如果在启动服务器时看到以下错误:

[2025-04-28 18:28:48.370 +0900] ERROR: Error starting server
    err: {
      "type": "Error",
      "message": "Failed to start server. Is port 3000 in use?",
      "stack":
          Error
              at serve (unknown)
              at [kRealListen] (node:http:565:41)
              at listen (node:http:542:35)
              at <anonymous> (/Users/yujiisobe/work/mcp-html-sync-server/node_modules/fastify/lib/server.js:265:12)
              at processTicksAndRejections (unknown:7:39)
      "code": "EADDRINUSE",
      "syscall": "listen",
      "errno": 0
    }

这意味着端口3000(或您配置的任何端口)已被另一个应用程序使用。要解决此问题,请执行以下操作:

  1. 更改端口:编辑 .env 文件并更改 SERVER_PORT 转换为不同的值(例如,3001、8080等)

  2. 停止其他应用程序:查找并停止使用端口3000的应用程序。您可以使用以下命令之一查找使用端口的进程:

    # On macOS/Linux
    lsof -i :3000
    
    # On Windows
    netstat -ano | findstr :3000
    
  3. 重新启动计算机:在某些情况下,重新启动可以清除可能占用端口的孤立进程。

当将服务器与Claude Desktop或VS Code一起使用时,如果端口已在使用中,您还可能会看到JSON解析错误。出现这些错误是因为服务器无法正常启动,并且返回的是错误消息而不是有效的JSON响应。

构建Docker镜像

docker build -t yujiosaka/mcp-html-sync-server .

许可证

该项目根据MIT许可证获得许可。看 许可证 了解详情。