Skip to main content
Glama
rushxb

MCP HTML Deployment Server (Nginx Static File Hosting)

by rushxb

MCP HTML 部署服务器 (Nginx 静态文件托管)

这是一个企业级的 Model Context Protocol (MCP) 服务端,支持大语言模型 (LLM) 或客户端直接上传、部署、更新和管理服务器上的静态前端 HTML/CSS/JS/媒体文件。

本项目支持 API 密钥鉴权 以及 自定义静态网站存活时间 (TTL),并在后台自动执行过期站点的清理。


架构设计

为了避免每次部署都动态生成 Nginx 配置文件并重新加载 Nginx 服务(这会带来复杂的权限安全隐患和 Nginx 重启开销),本项目采用了 共享 URL 前缀模式 (Shared URL Prefix Pattern)

  1. 一次性 Nginx 配置:在 Nginx 中配置一个固定的前缀路径(如 /sites/)并指向存放静态网站的根目录。

  2. 动态文件夹部署:MCP 服务端直接在网站根目录下,为每次部署生成唯一的站点 ID(如 _J9EqMQT),解压并存放静态网页文件(如 /var/www/mcp-sites/_J9EqMQT/)。

  3. 即时访问:网页上传后即可通过对应的公网 URL(如 http://yourdomain.com/sites/_J9EqMQT/)进行实时访问,无需修改任何 Nginx 配置。

LLM / 客户端 ---[MCP 协议]---> MCP 服务端 (Streamable HTTP 或 SSE)
                                        |
                                        v (解压/拷贝至子目录)
                               /var/www/mcp-sites/
                                    |-- _J9EqMQT/ (index.html, css/, js/)
                                    `-- k8mP9a/ (index.html)
                                        ^
Nginx ---[转发 /sites/]-----------------| (静态文件托管)

Related MCP server: Hostsmith MCP Server

环境配置

您可以通过环境变量或在根目录下创建 .env 文件来定制配置:

环境变量

默认值

说明

MCP_PORT

3000

MCP 服务绑定的 HTTP 端口

MCP_HOST

0.0.0.0

监听的主机 IP 地址

MCP_DATA_DIR

./data

存放元数据和站点文件夹的父级目录

MCP_SITES_DIR

<DATA_DIR>/sites

部署的静态站点的物理存储绝对路径

MCP_BASE_URL

http://localhost/sites

访问静态站点的公网 URL 前缀(需与 Nginx 路径匹配)

MCP_DB_PATH

<DATA_DIR>/db.json

站点元数据 JSON 数据库路径

MCP_MAX_UPLOAD_BYTES

52428800 (50MB)

允许的最大上传大小(单文件/ZIP)

MCP_ALLOWED_EXTENSIONS

.html,.css,.js...

允许上传的文件后缀列表(以逗号分隔)

MCP_API_KEY

可选的安全密钥。若设置,客户端连接及消息发送必须携带该密钥。

MCP_DEFAULT_TTL

可选的默认站点存活时间(秒数或格式化字符串如 '30m', '12h', '7d')。

MCP_MAX_TTL

可选的最大站点存活时间,用于限制用户侧 ttl 不能超过企业策略。

MCP_CLEANUP_INTERVAL

60000

定时清理过期站点的检测间隔时间(毫秒)。


如何部署到服务器上?

推荐使用 Docker Compose 部署。这样服务器不需要安装 Node.js、pnpm 或 PM2,只需要有 Docker 即可运行 MCP 服务。

方案一:Docker Compose 部署(推荐)

1. 环境准备

服务器需要安装 Docker 和 Docker Compose 插件:

docker --version
docker compose version

2. 准备静态站点目录

该目录需要同时被 MCP 容器写入、被 Nginx 读取:

sudo mkdir -p /var/www/mcp-sites
sudo chown -R 10001:10001 /var/www/mcp-sites

镜像内的默认运行用户 UID 是 10001。核心要求是:容器内 /sites 可写,Nginx 可读。

3. 克隆项目

git clone <您的仓库地址> mcp-html-mcp-nginx
cd mcp-html-mcp-nginx

4. 修改 Compose 配置

编辑 compose.yaml,至少修改以下配置:

environment:
  MCP_BASE_URL: "https://yourdomain.com/sites"
  MCP_API_KEY: "请改成一段足够长的随机密钥"
  MCP_DEFAULT_TTL: "24h"
  MCP_MAX_TTL: "30d"
volumes:
  - ./data:/data
  - /var/www/mcp-sites:/sites

其中:

  • MCP_BASE_URL 必须与 Nginx 暴露给用户访问的共同前缀一致。

  • MCP_API_KEY 是 MCP 访问密钥,生产环境必须修改。

  • MCP_DEFAULT_TTL 是用户未指定时的默认站点存活时间。

  • MCP_MAX_TTL 是允许用户设置的最大站点存活时间。

  • /var/www/mcp-sites:/sites 表示容器将网页部署到宿主机 /var/www/mcp-sites

5. 启动服务

docker compose up -d --build

查看运行状态:

docker compose ps
docker compose logs -f

如果日志出现 EACCES: permission denied, open '/data/db.json',说明宿主机挂载的 ./data 目录不可写。新版镜像会在启动时自动修正 /data/sites 的权限;更新代码后请重新构建:

docker compose up -d --build

如果仍然失败,可以手动修复宿主机目录权限:

sudo mkdir -p ./data /var/www/mcp-sites
sudo chown -R 10001:10001 ./data /var/www/mcp-sites
docker compose restart

健康检查:

curl http://127.0.0.1:3091/health

6. 配置 Nginx 一次性静态目录

在您的 Nginx 配置文件(例如 /etc/nginx/sites-available/default)中添加以下 location 块:

server {
    listen 80;
    server_name yourdomain.com;

    # MCP 协议入口,可选:如果您希望通过域名访问 MCP,而不是直接开放 3091 端口
    location /mcp/ {
        proxy_pass http://127.0.0.1:3091/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }

    # SSE 传输会回调 /messages,必须代理到 MCP 服务
    location /messages {
        proxy_pass http://127.0.0.1:3091/messages;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering off;
    }

    # 真实文件上传入口,支持 multipart/form-data 多文件/文件夹上传
    location /upload/ {
        proxy_pass http://127.0.0.1:3091/upload/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_request_buffering off;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
    }

    # 所有部署网页共用这个前缀。
    # HTML 入口必须禁用强缓存,避免浏览器保留旧 index.html 后继续请求已删除的旧 assets。
    location /sites/ {
        alias /var/www/mcp-sites/;
        index index.html;
        try_files $uri $uri/ =404;
        add_header Cache-Control "no-cache, no-store, must-revalidate" always;
    }

    # 带内容哈希的前端构建产物可以长期缓存。
    # Vite / Vue / React 等构建产物通常位于 /assets/ 下,文件名变化即可触发缓存更新。
    location ~ ^/sites/(.+\.(?:js|css|png|jpg|jpeg|gif|svg|ico|webp|woff2?|ttf|eot|map))$ {
        alias /var/www/mcp-sites/$1;
        expires 1y;
        add_header Cache-Control "public, immutable, no-transform" always;
    }
}

如果部署的是 Vue Router / React Router 这类 history 模式 SPA,深链接刷新可能需要额外的 index.html fallback;否则 /sites/<siteId>/admin/users 这类地址会被 Nginx 当成真实文件路径而返回 404。共享 /sites/ 前缀下最稳妥的方案是前端使用正确的 base 路径或 hash history;MCP 工具返回的 validation.spa_hint 会提示这类风险。

重新加载 Nginx:

sudo nginx -t && sudo systemctl reload nginx

如果配置了上面的 /mcp/ 代理,则客户端连接地址通常是:

  • Streamable HTTP: https://yourdomain.com/mcp/mcp

  • SSE: https://yourdomain.com/mcp/sse?apiKey=your_super_secret_key

上传接口地址:

  • 文件上传: https://yourdomain.com/upload/files

  • ZIP 上传: https://yourdomain.com/upload/zip

如果不通过 Nginx 代理 MCP,只开放 3091 端口,则连接地址是:

  • Streamable HTTP: http://<服务器IP>:3091/mcp

  • SSE: http://<服务器IP>:3091/sse?apiKey=your_super_secret_key

  • 文件上传: http://<服务器IP>:3091/upload/files

  • ZIP 上传: http://<服务器IP>:3091/upload/zip

方案二:Node.js + PM2 部署(备选)

如果您希望直接在服务器上运行 Node.js,可以使用下面的方式。

1. 环境准备

确保服务器已安装 Node.js >= 20.0.0 及包管理器 pnpm

2. 克隆项目与安装依赖

git clone <您的仓库地址> mcp-html-mcp-nginx
cd mcp-html-mcp-nginx
pnpm install

3. 编译项目

pnpm run build

编译后的入口文件将生成在 dist/index.js

4. 编写配置文件

在项目根目录下创建 .env 文件,填入您的配置参数:

MCP_PORT=3000
MCP_HOST=0.0.0.0
MCP_BASE_URL=https://yourdomain.com/sites
MCP_SITES_DIR=/var/www/mcp-sites
MCP_API_KEY=your_super_secret_key
MCP_DEFAULT_TTL=24h
MCP_MAX_TTL=30d
MCP_CLEANUP_INTERVAL=60000

确保运行 Node.js 进程的用户有权读写 MCP_SITES_DIRMCP_DATA_DIR

5. 使用 PM2 进行守护运行

在生产环境中,建议使用 PM2 启动和守护该服务,以便于开机自启和故障恢复。

# 全局安装 PM2
npm install -g pm2

# 启动服务
pm2 start dist/index.js --name "mcp-html-nginx" --update-env

# 保存当前列表以实现开机自启
pm2 save
pm2 startup

用户怎么用?

由于该服务是一个 MCP 服务,用户一般不需要直接调用其 API,而是通过 大语言模型客户端 (Cursor / Claude Desktop 等) 间接使用。

1. 在 Cursor 中配置 (SSE 模式)

  1. 打开 Cursor 客户端,进入设置界面:Settings -> Features -> MCP

  2. 点击 + Add New MCP Server

  3. 在弹出的对话框中进行配置:

    • Name: mcp-html-nginx

    • Type: SSE

    • URL: https://yourdomain.com/mcp/sse?apiKey=your_super_secret_key (请替换为您的实际域名和密钥)

  4. 点击 Save。如果连接成功,Cursor 面板中会显示绿色的连接状态,并列出可用的工具列表。

如果 MCP 客户端支持自定义请求头,生产环境建议使用 Authorization: Bearer your_super_secret_keyx-api-key: your_super_secret_key,避免密钥出现在 URL、代理日志或浏览器历史中。SSE 初始化认证成功后,服务端会按 session 放行后续 /messages 请求,不会再把密钥写回 SSE endpoint 事件。

2. 在 Claude Desktop 中配置 (SSE 模式)

  1. 编辑 Claude Desktop 的配置文件:

    • Windows: %APPDATA%\Claude\claude_desktop_config.json

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  2. mcpServers 字段下添加 SSE 连接配置:

    {
      "mcpServers": {
        "mcp-html-nginx": {
          "sse": {
           "url": "https://yourdomain.com/mcp/sse?apiKey=your_super_secret_key"
          }
        }
      }
    }
  3. 重启 Claude Desktop。

3. LLM 交互与实战

当客户端连接上此 MCP 服务后,您的 AI 助手便拥有部署网页、查询站点、更新 TTL、删除站点的能力。

对于真实前端文件或文件夹,推荐走 HTTP 文件上传接口,不要让 AI 把大量 HTML/JS/CSS 内容塞进 MCP 参数。

curl -X POST 'https://yourdomain.com/upload/files' \
  -H 'Authorization: Bearer your_super_secret_key' \
  -F 'name=my-site' \
  -F 'ttl=72h' \
  -F 'paths=index.html' -F 'file=@./index.html;filename=index.html' \
  -F 'paths=assets/app.js' -F 'file=@./assets/app.js;filename=app.js'

对于 Vite / Vue / React 等完整构建产物,推荐先压缩 dist 目录内容,再直接上传 ZIP,避免 MCP JSON 参数中传输大体积 base64:

cd dist
zip -r ../dist.zip .
curl -X POST 'https://yourdomain.com/upload/zip?name=my-site&ttl=72h&spa=true' \
  -H 'Authorization: Bearer your_super_secret_key' \
  -H 'Content-Type: application/zip' \
  --data-binary '@../dist.zip'

上传成功后返回:

{
  "status": "deployed",
  "site_id": "abc12345",
  "url": "https://yourdomain.com/sites/abc12345/",
  "entry_url": "https://yourdomain.com/sites/abc12345/index.html",
  "expires_at": "2026-06-26T10:24:33.035Z",
  "validation": {
    "entry_file": "index.html",
    "asset_count": 2,
    "missing_assets": [],
    "warnings": [],
    "cache_hint": "Use no-cache for index.html and long immutable caching for hashed assets."
  }
}

LLM 交互示例:

  • 用户: "我有一个前端文件夹要部署,告诉我怎么上传。"

  • AI (自动分析):

    1. 调用 get_upload_instructions 获取上传入口和字段说明。

    2. 指导用户或客户端把真实文件以 multipart/form-data 上传到 /upload/files

    3. 上传成功后展示返回的 url

  • 用户: "把这个网站的存活时间缩短到 30 分钟,并更新一下标题。"

  • AI (自动分析):

    1. 自动调用 update_site,传入 site_id 并将 ttl 设为 "30m"

    2. 报告更新成功。


MCP 工具接口详细说明

1. get_upload_instructions (获取真实文件上传说明)

返回 /upload/files 上传接口说明。适合用户已有本地文件、文件夹、构建产物时使用。

上传接口支持:

  • 多个 file 文件字段。

  • 可选多个 paths 字段,用于指定文件在站点中的相对路径。

  • 可选 name 字段,指定站点名称。

  • 可选 ttl 字段,指定存活时间。

2. deploy_site (通过 MCP 参数部署静态站点)

通过 MCP 工具参数部署静态网页。适合小型 LLM 生成页面、服务端已有路径或程序化 base64 场景。真实文件/文件夹上传优先使用 get_upload_instructions + /upload/files。接受三种部署源模式之一(互斥,三选一):

  • files: 文件对象数组,每个对象包含 path(相对路径)和 content(Base64 编码的文本或二进制内容),适合单页应用或少量文件。

  • zip_base64: 整个站点的 Base64 编码 ZIP 压缩包,适合复杂的完整网站及带有多媒体资源的站点。

  • source_path: 服务器本地已存在的静态文件夹绝对路径。

输入参数:

  • name (string, 可选): 网站的友好名称。若缺省则自动生成。

  • files (array, 可选): [{ path: "index.html", content: "..." }]

  • zip_base64 (string, 可选): Base64 编码的 ZIP 压缩包。

  • source_path (string, 可选): 服务器本地的绝对路径。

  • ttl (number | string, 可选): 网站的存活时间(生命周期)。例如:3600(代表3600秒)、"30m"(30分钟)、"12h"(12小时)、"7d"(7天)、"never"(永久)。若不填,则遵循默认存活时间(若未配置默认值,则永久存活)。若服务端配置了 MCP_MAX_TTL,则不能超过该上限。

3. update_site (更新静态站点)

更新一个已经存在的站点,支持增量更新或清空覆盖。

输入参数:

  • site_id (string, 必填): 目标站点的唯一 ID。

  • files (array, 可选): 要更新或新增的文件列表。

  • zip_base64 (string, 可选): 用于更新的 Base64 ZIP 包(可解包覆盖或追加)。

  • clean (boolean, 可选, 默认 false): 设置为 true 时,会在写入新文件前清空该站点的旧目录。

  • ttl (number | string, 可选): 更新或延长网站的存活时间。可以只传 site_idttl 来续期,也可以传 "never" 取消过期时间。若服务端配置了 MCP_MAX_TTL,则不能超过该上限。

4. list_sites (列出静态站点)

列出当前所有已部署的静态网站信息(包括 ID、名称、URL、文件数量等)。

输入参数:

  • keyword (string, 可选): 站点 ID 或站点名称的模糊匹配过滤关键字(不区分大小写)。

4. delete_site (删除静态站点)

完全删除一个站点。从磁盘上移除对应文件夹,并从数据库中删除该条记录。

输入参数:

  • site_id (string, 必填): 目标站点的唯一 ID。


自动化测试

项目中提供了一个完整的集成测试脚本,模拟了标准的 SSE 协议交互与全部工具链调用:

node test_mcp.cjs
F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rushxb/mcp-html-mcp-nginx'

If you have feedback or need assistance with the MCP directory API, please join our Discord server