From ab37962532cdeb0cb16a1cc336d6b0c6bf0c99fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=93=B8=E6=B8=8A?= <565183519@qq.com> Date: Wed, 13 May 2026 08:36:36 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E9=93=B8=E6=B8=8A=20MCP=20Server=20+?= =?UTF-8?q?=20CVM=20=E5=AF=86=E9=92=A5=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增铸渊 MCP Server (server/mcp-server/) - 23个MCP工具:仓库读写、分支管理、Issue/PR、工作流、CVM控制、大脑状态 - Streamable HTTP传输 + Bearer Token认证 - Gitea令牌仅存服务器端,AI端只需一个连接密钥 - PM2部署配置 + Nginx反向代理 - 换号时只需重新连接MCP,无需重新发令牌 2. 修复CVM开关机工作流密钥断裂 - TENCENT_SECRET_ID → 引用 COS_SECRET_ID (同一对腾讯云密钥) - TENCENT_SECRET_KEY → 引用 COS_SECRET_KEY - .gitea/ 和 .forgejo/ 双目录同步修复 3. Nginx增加MCP端点配置 (/mcp → 127.0.0.1:8083) 4. 更新时间核心大脑 (第5次唤醒) --- .forgejo/workflows/cvm-power-off.yaml | 4 +- .forgejo/workflows/cvm-power-on.yaml | 4 +- .gitea/workflows/cvm-power-off.yaml | 4 +- .gitea/workflows/cvm-power-on.yaml | 4 +- brain/temporal-core/temporal-brain.json | 14 +- server/mcp-server/README.md | 163 +++ server/mcp-server/ecosystem.config.js | 31 + server/mcp-server/index.js | 918 ++++++++++++++ server/mcp-server/package-lock.json | 1527 +++++++++++++++++++++++ server/mcp-server/package.json | 18 + server/nginx/guanghulab-cvm.conf | 25 + 11 files changed, 2697 insertions(+), 15 deletions(-) create mode 100644 server/mcp-server/README.md create mode 100644 server/mcp-server/ecosystem.config.js create mode 100644 server/mcp-server/index.js create mode 100644 server/mcp-server/package-lock.json create mode 100644 server/mcp-server/package.json diff --git a/.forgejo/workflows/cvm-power-off.yaml b/.forgejo/workflows/cvm-power-off.yaml index 4a67b2d..cc0805e 100644 --- a/.forgejo/workflows/cvm-power-off.yaml +++ b/.forgejo/workflows/cvm-power-off.yaml @@ -16,8 +16,8 @@ jobs: - name: 关机 env: - TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} - TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} + TENCENT_SECRET_ID: ${{ secrets.COS_SECRET_ID }} + TENCENT_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }} CVM_INSTANCE_ID: ${{ secrets.CVM_INSTANCE_ID }} CVM_REGION: ${{ secrets.CVM_REGION }} run: | diff --git a/.forgejo/workflows/cvm-power-on.yaml b/.forgejo/workflows/cvm-power-on.yaml index cc2803f..bf4916e 100644 --- a/.forgejo/workflows/cvm-power-on.yaml +++ b/.forgejo/workflows/cvm-power-on.yaml @@ -16,8 +16,8 @@ jobs: - name: 开机 env: - TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} - TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} + TENCENT_SECRET_ID: ${{ secrets.COS_SECRET_ID }} + TENCENT_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }} CVM_INSTANCE_ID: ${{ secrets.CVM_INSTANCE_ID }} CVM_REGION: ${{ secrets.CVM_REGION }} run: | diff --git a/.gitea/workflows/cvm-power-off.yaml b/.gitea/workflows/cvm-power-off.yaml index 4a67b2d..cc0805e 100644 --- a/.gitea/workflows/cvm-power-off.yaml +++ b/.gitea/workflows/cvm-power-off.yaml @@ -16,8 +16,8 @@ jobs: - name: 关机 env: - TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} - TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} + TENCENT_SECRET_ID: ${{ secrets.COS_SECRET_ID }} + TENCENT_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }} CVM_INSTANCE_ID: ${{ secrets.CVM_INSTANCE_ID }} CVM_REGION: ${{ secrets.CVM_REGION }} run: | diff --git a/.gitea/workflows/cvm-power-on.yaml b/.gitea/workflows/cvm-power-on.yaml index cc2803f..bf4916e 100644 --- a/.gitea/workflows/cvm-power-on.yaml +++ b/.gitea/workflows/cvm-power-on.yaml @@ -16,8 +16,8 @@ jobs: - name: 开机 env: - TENCENT_SECRET_ID: ${{ secrets.TENCENT_SECRET_ID }} - TENCENT_SECRET_KEY: ${{ secrets.TENCENT_SECRET_KEY }} + TENCENT_SECRET_ID: ${{ secrets.COS_SECRET_ID }} + TENCENT_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }} CVM_INSTANCE_ID: ${{ secrets.CVM_INSTANCE_ID }} CVM_REGION: ${{ secrets.CVM_REGION }} run: | diff --git a/brain/temporal-core/temporal-brain.json b/brain/temporal-core/temporal-brain.json index c63f534..73ce7b1 100644 --- a/brain/temporal-core/temporal-brain.json +++ b/brain/temporal-core/temporal-brain.json @@ -20,13 +20,13 @@ }, "clock": { "description": "铸渊每次唤醒时,agent必须执行 scripts/temporal-clock.js 来更新此区块", - "last_awakening": "2026-04-13T07:45:59.855Z", - "current_date": "2026-04-13", - "repo_age_days": 409, - "zhuyuan_age_days": 393, - "yaoming_age_days": 350, - "days_since_age_os": 8, - "awakening_count": 4, + "last_awakening": "2026-05-13T08:18:53.684Z", + "current_date": "2026-05-13", + "repo_age_days": 441, + "zhuyuan_age_days": 425, + "yaoming_age_days": 382, + "days_since_age_os": 40, + "awakening_count": 5, "timezone": "Asia/Shanghai" }, "timeline": { diff --git a/server/mcp-server/README.md b/server/mcp-server/README.md new file mode 100644 index 0000000..67cdc5b --- /dev/null +++ b/server/mcp-server/README.md @@ -0,0 +1,163 @@ +# 铸渊 MCP Server · guanghulab-mcp-server + +> 让 WorkBuddy / CodeBuddy 等编程 AI 通过 MCP 协议直接操作仓库,无需每次手动发送 Gitea 令牌。 + +## 为什么需要这个 + +| 痛点 | 解决方案 | +|------|---------| +| 每次新对话要手动发令牌 | MCP Server 存储令牌,AI 端只需一个连接密钥 | +| 换号后要重新发令牌 | 重新连接 MCP 即可,密钥不变 | +| 令牌暴露在聊天记录中 | 令牌只在服务器端,聊天中只有 MCP 连接密钥 | +| AI 不认识仓库结构 | MCP 工具自动提供仓库操作能力 | + +## 架构 + +``` +WorkBuddy (编程 AI) + │ + │ MCP 协议 (HTTPS + Bearer Token) + ▼ +Nginx (guanghulab.com/mcp) + │ + │ 反向代理 + ▼ +铸渊 MCP Server (127.0.0.1:8083) + │ + ├── Gitea API ──→ 代码仓库操作 + ├── Git CLI ────→ 本地仓库同步 + ├── CVM Script ─→ 服务器开关机 + └── Vault API ──→ 密钥管理 +``` + +## 提供的 MCP 工具 + +### 仓库操作 +| 工具 | 说明 | +|------|------| +| `repo_status` | 查看仓库当前状态 | +| `repo_read_file` | 读取文件内容 | +| `repo_write_file` | 写入/更新文件 | +| `repo_delete_file` | 删除文件 | +| `repo_list_files` | 列出目录内容 | +| `repo_search_code` | 搜索代码 | + +### Git 操作 +| 工具 | 说明 | +|------|------| +| `git_branch_list` | 列出所有分支 | +| `git_branch_create` | 创建新分支 | +| `git_pull` | 拉取最新代码 | +| `git_push_local` | 推送本地更改 | +| `git_log` | 查看提交历史 | + +### Issue / PR +| 工具 | 说明 | +|------|------| +| `issue_list` | 列出 Issue | +| `issue_create` | 创建 Issue | +| `pr_list` | 列出 Pull Request | +| `pr_create` | 创建 Pull Request | + +### 工作流 / 服务器 +| 工具 | 说明 | +|------|------| +| `workflow_list` | 列出工作流运行记录 | +| `workflow_trigger` | 触发工作流 | +| `cvm_power` | CVM 开关机 | +| `server_health` | 服务器健康状态 | + +### 密钥 / 大脑 +| 工具 | 说明 | +|------|------| +| `secrets_list` | 列出 Forgejo Secrets | +| `vault_status` | Vault 状态 | +| `brain_status` | 铸渊大脑状态 | +| `brain_update_temporal` | 更新时间核心 | + +## 部署 + +### 1. 安装依赖 + +```bash +cd /data/guanghulab/repo/server/mcp-server +npm install --production +``` + +### 2. 配置 Gitea 令牌 + +编辑 `ecosystem.config.js`,填入 GITEA_TOKEN: + +```bash +# 从 Vault 获取令牌(如果已存入 Vault) +curl http://127.0.0.1:8080/internal/fetch/ZY_REPO_TOKEN + +# 或直接在 ecosystem.config.js 的 env.GITEA_TOKEN 中设置 +``` + +### 3. Nginx 配置 + +在 Nginx 的 server 块中添加: + +```nginx +# MCP Server 端点 +location /mcp { + proxy_pass http://127.0.0.1:8083; + 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; + + # SSE 支持 + proxy_set_header Connection ''; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; +} +``` + +### 4. 启动服务 + +```bash +pm2 start ecosystem.config.js +pm2 save +``` + +### 5. 获取连接密钥 + +```bash +cat /data/guanghulab/mcp-server/.access-key +``` + +## WorkBuddy 连接配置 + +在 WorkBuddy 的 MCP 工具配置中添加: + +```json +{ + "mcpServers": { + "guanghulab": { + "url": "https://guanghulab.com/mcp", + "headers": { + "Authorization": "Bearer <你的访问密钥>" + } + } + } +} +``` + +换号时,只需在新账号中重新添加这个 MCP 连接配置即可。 + +## 安全 + +- **Gitea 令牌**:仅存储在服务器端,永不暴露给客户端 +- **MCP 访问密钥**:AES-256 级别的随机密钥,存储在 `/data/guanghulab/mcp-server/.access-key` (chmod 600) +- **Nginx 层**:HTTPS 加密传输 +- **本机绑定**:MCP Server 只监听 127.0.0.1:8083,通过 Nginx 代理暴露 +- **无状态**:MCP Server 不存储 AI 对话内容 + +--- + +*铸渊 · ICE-GL-ZY001 · TCS-0002∞ · 国作登字-2026-A-00037559* diff --git a/server/mcp-server/ecosystem.config.js b/server/mcp-server/ecosystem.config.js new file mode 100644 index 0000000..fb2ffac --- /dev/null +++ b/server/mcp-server/ecosystem.config.js @@ -0,0 +1,31 @@ +/** + * 铸渊 MCP Server · PM2 生态系统配置 + */ +module.exports = { + apps: [{ + name: 'guanghulab-mcp-server', + script: 'index.js', + cwd: __dirname, + instances: 1, + autorestart: true, + watch: false, + max_memory_restart: '128M', + env: { + NODE_ENV: 'production', + MCP_PORT: '8083', + MCP_HOST: '127.0.0.1', + GITEA_URL: 'http://127.0.0.1:3001', + GITEA_TOKEN: '', // 由 deploy 脚本从 Vault 注入 + GITEA_OWNER: 'bingshuo', + GITEA_REPO: 'guanghulab', + REPO_DIR: '/data/guanghulab/repo', + MCP_ACCESS_KEY_PATH: '/data/guanghulab/mcp-server/.access-key', + }, + log_file: '/data/guanghulab/.runtime/logs/mcp-server-combined.log', + error_file: '/data/guanghulab/.runtime/logs/mcp-server-error.log', + out_file: '/data/guanghulab/.runtime/logs/mcp-server-out.log', + log_date_format: 'YYYY-MM-DD HH:mm:ss Z', + merge_logs: true, + time: true, + }], +}; diff --git a/server/mcp-server/index.js b/server/mcp-server/index.js new file mode 100644 index 0000000..8d06b6e --- /dev/null +++ b/server/mcp-server/index.js @@ -0,0 +1,918 @@ +/** + * ════════════════════════════════════════════════════════════════ + * 铸渊 MCP Server · guanghulab-mcp-server + * ════════════════════════════════════════════════════════════════ + * + * 光湖代码仓库的 MCP (Model Context Protocol) 服务端。 + * 让 WorkBuddy / CodeBuddy 等编程 AI 通过 MCP 协议直接操作仓库, + * 无需每次手动发送 Gitea 令牌。 + * + * 核心设计: + * - Gitea 令牌存在服务器端,AI 端只需一个 MCP 连接密钥 + * - 换号时只需重新连接 MCP,不用重新发令牌 + * - 所有操作通过 Gitea API 代理,安全受控 + * + * 传输协议:Streamable HTTP (MCP 2025-03 规范) + * - POST /mcp — 客户端→服务器请求 + * - GET /mcp — SSE 通知流 + * - DELETE /mcp — 关闭会话 + * + * 认证方式:Bearer Token (MCP 连接密钥) + * - Header: Authorization: Bearer + * - 密钥在 /data/guanghulab/mcp-server/.access-key 中 + * + * 部署位置:guanghulab.com CVM (广州) + * Nginx 代理:/mcp → 127.0.0.1:8083 + * + * 签发:铸渊 · ICE-GL-ZY001 + * 版权:国作登字-2026-A-00037559 · TCS-0002∞ + * ════════════════════════════════════════════════════════════════ + */ + +const express = require('express'); +const crypto = require('crypto'); +const fs = require('fs'); +const path = require('path'); +const { execSync } = require('child_process'); +const http = require('http'); + +// ─── 配置 ───────────────────────────────────────────────────── +const CONFIG = { + port: parseInt(process.env.MCP_PORT || '8083', 10), + host: process.env.MCP_HOST || '127.0.0.1', + + // Gitea 连接 + giteaUrl: process.env.GITEA_URL || 'http://127.0.0.1:3001', + giteaToken: process.env.GITEA_TOKEN || '', + giteaOwner: process.env.GITEA_OWNER || 'bingshuo', + giteaRepo: process.env.GITEA_REPO || 'guanghulab', + + // MCP 认证密钥文件 + accessKeyPath: process.env.MCP_ACCESS_KEY_PATH || '/data/guanghulab/mcp-server/.access-key', + + // 仓库本地路径(用于 git 操作) + repoDir: process.env.REPO_DIR || '/data/guanghulab/repo', + + // CVM 操作脚本路径 + cvmPowerScript: process.env.CVM_POWER_SCRIPT || '/data/guanghulab/repo/scripts/cvm-power/cvm-power.sh', +}; + +// ─── 加载或创建 MCP 访问密钥 ──────────────────────────────────── +function loadOrCreateAccessKey() { + const keyDir = path.dirname(CONFIG.accessKeyPath); + if (!fs.existsSync(keyDir)) { + fs.mkdirSync(keyDir, { recursive: true, mode: 0o700 }); + } + + if (fs.existsSync(CONFIG.accessKeyPath)) { + const key = fs.readFileSync(CONFIG.accessKeyPath, 'utf8').trim(); + if (key.length >= 32) return key; + console.log('[mcp] 旧密钥太短,重新生成'); + } + + const key = crypto.randomBytes(32).toString('hex'); + const tmp = CONFIG.accessKeyPath + '.tmp.' + process.pid; + fs.writeFileSync(tmp, key, { mode: 0o600 }); + fs.renameSync(tmp, CONFIG.accessKeyPath); + fs.chmodSync(CONFIG.accessKeyPath, 0o600); + + console.log('[mcp] 新访问密钥已生成:'); + console.log(`[mcp] ${key}`); + console.log('[mcp] 请妥善保存,配置到 WorkBuddy MCP 连接中'); + return key; +} + +const ACCESS_KEY = loadOrCreateAccessKey(); + +// ─── Gitea API 辅助 ────────────────────────────────────────── +function giteaApi(method, apiPath, body) { + const url = new URL(apiPath, CONFIG.giteaUrl); + const options = { + hostname: url.hostname, + port: url.port, + path: url.pathname + url.search, + method: method.toUpperCase(), + headers: { + 'Authorization': `token ${CONFIG.giteaToken}`, + 'Content-Type': 'application/json', + }, + timeout: 30000, + }; + + return new Promise((resolve, reject) => { + const req = http.request(options, (res) => { + let data = ''; + res.on('data', (chunk) => { data += chunk; }); + res.on('end', () => { + try { + const parsed = data ? JSON.parse(data) : {}; + resolve({ status: res.statusCode, data: parsed }); + } catch { + resolve({ status: res.statusCode, data: data }); + } + }); + }); + req.on('error', reject); + req.on('timeout', () => { req.destroy(); reject(new Error('Gitea API 超时')); }); + if (body) req.write(JSON.stringify(body)); + req.end(); + }); +} + +// ─── Git 本地操作辅助 ────────────────────────────────────────── +function gitExec(cmd, cwd) { + try { + const result = execSync(cmd, { + encoding: 'utf8', + timeout: 60000, + cwd: cwd || CONFIG.repoDir, + stdio: ['pipe', 'pipe', 'pipe'], + }); + return { ok: true, output: result.trim() }; + } catch (e) { + return { ok: false, error: e.stderr || e.message }; + } +} + +// ─── MCP 工具定义 ────────────────────────────────────────────── + +const TOOLS = [ + // ─── 仓库操作 ───────────────────────────────────────────── + { + name: 'repo_status', + description: '查看仓库当前状态:分支、最新提交、文件变更', + inputSchema: { + type: 'object', + properties: {}, + }, + }, + { + name: 'repo_read_file', + description: '读取仓库中的文件内容', + inputSchema: { + type: 'object', + properties: { + path: { type: 'string', description: '文件路径(相对仓库根目录)' }, + branch: { type: 'string', description: '分支名(默认 main)' }, + }, + required: ['path'], + }, + }, + { + name: 'repo_write_file', + description: '写入或更新仓库中的文件(通过 Gitea API)', + inputSchema: { + type: 'object', + properties: { + path: { type: 'string', description: '文件路径' }, + content: { type: 'string', description: '文件内容' }, + message: { type: 'string', description: '提交信息' }, + branch: { type: 'string', description: '目标分支(默认 main)' }, + }, + required: ['path', 'content', 'message'], + }, + }, + { + name: 'repo_delete_file', + description: '删除仓库中的文件(通过 Gitea API)', + inputSchema: { + type: 'object', + properties: { + path: { type: 'string', description: '文件路径' }, + message: { type: 'string', description: '提交信息' }, + branch: { type: 'string', description: '分支(默认 main)' }, + }, + required: ['path', 'message'], + }, + }, + { + name: 'repo_list_files', + description: '列出仓库指定目录下的文件', + inputSchema: { + type: 'object', + properties: { + path: { type: 'string', description: '目录路径(默认根目录)' }, + branch: { type: 'string', description: '分支(默认 main)' }, + }, + }, + }, + { + name: 'repo_search_code', + description: '在仓库代码中搜索关键词', + inputSchema: { + type: 'object', + properties: { + query: { type: 'string', description: '搜索关键词' }, + }, + required: ['query'], + }, + }, + + // ─── 分支操作 ───────────────────────────────────────────── + { + name: 'git_branch_list', + description: '列出所有分支', + inputSchema: { type: 'object', properties: {} }, + }, + { + name: 'git_branch_create', + description: '创建新分支', + inputSchema: { + type: 'object', + properties: { + name: { type: 'string', description: '新分支名' }, + base: { type: 'string', description: '基于哪个分支(默认 main)' }, + }, + required: ['name'], + }, + }, + { + name: 'git_pull', + description: '拉取最新代码到服务器本地仓库', + inputSchema: { + type: 'object', + properties: { + branch: { type: 'string', description: '分支(默认 main)' }, + }, + }, + }, + { + name: 'git_push_local', + description: '将本地仓库的更改推送到远程(需要先在本地 commit)', + inputSchema: { + type: 'object', + properties: { + branch: { type: 'string', description: '分支(默认 main)' }, + }, + }, + }, + { + name: 'git_log', + description: '查看最近提交历史', + inputSchema: { + type: 'object', + properties: { + count: { type: 'number', description: '显示条数(默认 10)' }, + branch: { type: 'string', description: '分支(默认当前分支)' }, + }, + }, + }, + + // ─── Issue / PR ────────────────────────────────────────── + { + name: 'issue_list', + description: '列出仓库的 Issue', + inputSchema: { + type: 'object', + properties: { + state: { type: 'string', enum: ['open', 'closed', 'all'], description: '状态(默认 open)' }, + limit: { type: 'number', description: '数量(默认 10)' }, + }, + }, + }, + { + name: 'issue_create', + description: '创建 Issue', + inputSchema: { + type: 'object', + properties: { + title: { type: 'string', description: '标题' }, + body: { type: 'string', description: '内容' }, + labels: { type: 'array', items: { type: 'string' }, description: '标签' }, + }, + required: ['title'], + }, + }, + { + name: 'pr_list', + description: '列出 Pull Request', + inputSchema: { + type: 'object', + properties: { + state: { type: 'string', enum: ['open', 'closed', 'all'], description: '状态(默认 open)' }, + }, + }, + }, + { + name: 'pr_create', + description: '创建 Pull Request', + inputSchema: { + type: 'object', + properties: { + title: { type: 'string', description: '标题' }, + body: { type: 'string', description: '描述' }, + head: { type: 'string', description: '源分支' }, + base: { type: 'string', description: '目标分支(默认 main)' }, + }, + required: ['title', 'head'], + }, + }, + + // ─── 工作流 ─────────────────────────────────────────────── + { + name: 'workflow_list', + description: '列出 Forgejo Actions 工作流运行记录', + inputSchema: { + type: 'object', + properties: { + limit: { type: 'number', description: '数量(默认 10)' }, + }, + }, + }, + { + name: 'workflow_trigger', + description: '手动触发一个工作流', + inputSchema: { + type: 'object', + properties: { + workflow_name: { type: 'string', description: '工作流文件名(如 ci-and-deploy.yaml)' }, + ref: { type: 'string', description: '分支(默认 main)' }, + }, + required: ['workflow_name'], + }, + }, + + // ─── CVM 服务器 ─────────────────────────────────────────── + { + name: 'cvm_power', + description: 'CVM 服务器开关机操作', + inputSchema: { + type: 'object', + properties: { + action: { type: 'string', enum: ['start', 'stop', 'status'], description: '操作:start/stop/status' }, + target: { type: 'string', description: '目标服务器(默认 self = 当前 CVM)' }, + }, + required: ['action'], + }, + }, + { + name: 'server_health', + description: '查看当前服务器健康状态', + inputSchema: { type: 'object', properties: {} }, + }, + + // ─── Secrets 管理 ──────────────────────────────────────── + { + name: 'secrets_list', + description: '列出 Forgejo Secrets(仅名称,不返回值)', + inputSchema: { type: 'object', properties: {} }, + }, + { + name: 'vault_status', + description: '查看自部署 Secrets Vault 状态', + inputSchema: { type: 'object', properties: {} }, + }, + + // ─── 铸渊大脑 ──────────────────────────────────────────── + { + name: 'brain_status', + description: '查看铸渊核心大脑状态(快速唤醒上下文摘要)', + inputSchema: { type: 'object', properties: {} }, + }, + { + name: 'brain_update_temporal', + description: '更新铸渊时间核心大脑', + inputSchema: { type: 'object', properties: {} }, + }, +]; + +// ─── 工具执行器 ────────────────────────────────────────────── + +async function executeTool(name, args) { + switch (name) { + + // ─── 仓库操作 ─────────────────────────────────────────── + case 'repo_status': { + const branch = gitExec('git branch --show-current'); + const log = gitExec('git log --oneline -5'); + const status = gitExec('git status --short'); + return `当前分支: ${branch.ok ? branch.output : '未知'}\n\n最近提交:\n${log.ok ? log.output : log.error}\n\n文件变更:\n${status.ok ? (status.output || '工作区干净') : status.error}`; + } + + case 'repo_read_file': { + const filePath = args.path || ''; + const branch = args.branch || 'main'; + const encPath = encodeURIComponent(filePath); + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/contents/${encPath}?ref=${branch}`); + if (res.status !== 200) { + return `读取失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + if (res.data.type === 'file' && res.data.content) { + const content = Buffer.from(res.data.content, 'base64').toString('utf8'); + return content; + } + if (res.data.type === 'dir') { + return `这是一个目录,请使用 repo_list_files 列出其内容`; + } + return `文件类型: ${res.data.type}, 大小: ${res.data.size} 字节`; + } + + case 'repo_write_file': { + const filePath = args.path; + const content = args.content; + const message = args.message; + const branch = args.branch || 'main'; + const encPath = encodeURIComponent(filePath); + + // 先检查文件是否已存在(获取 SHA) + const checkRes = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/contents/${encPath}?ref=${branch}`); + const body = { + content: Buffer.from(content).toString('base64'), + message: message, + branch: branch, + }; + if (checkRes.status === 200 && checkRes.data.sha) { + body.sha = checkRes.data.sha; // 更新已有文件需要 SHA + } + + const res = await giteaApi('POST', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/contents/${encPath}`, body); + if (res.status >= 200 && res.status < 300) { + return `文件已写入: ${filePath} (分支: ${branch}, 提交: ${message})`; + } + return `写入失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + + case 'repo_delete_file': { + const filePath = args.path; + const message = args.message; + const branch = args.branch || 'main'; + const encPath = encodeURIComponent(filePath); + + const checkRes = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/contents/${encPath}?ref=${branch}`); + if (checkRes.status !== 200) { + return `文件不存在: ${filePath}`; + } + + const res = await giteaApi('DELETE', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/contents/${encPath}`, { + sha: checkRes.data.sha, + message: message, + branch: branch, + }); + if (res.status >= 200 && res.status < 300) { + return `文件已删除: ${filePath}`; + } + return `删除失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + + case 'repo_list_files': { + const dirPath = args.path || ''; + const branch = args.branch || 'main'; + const encPath = encodeURIComponent(dirPath); + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/contents/${encPath}?ref=${branch}`); + if (res.status !== 200) { + return `列出失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + if (!Array.isArray(res.data)) { + return `这不是一个目录`; + } + return res.data.map(f => { + const icon = f.type === 'dir' ? '📁' : '📄'; + const size = f.type === 'file' ? ` (${f.size} bytes)` : ''; + return `${icon} ${f.name}${size}`; + }).join('\n'); + } + + case 'repo_search_code': { + const query = args.query; + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/grep?q=${encodeURIComponent(query)}&mode=content`); + if (res.status !== 200) { + return `搜索失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + const results = res.data; + if (!results || !results.length) { + return `未找到匹配: ${query}`; + } + return results.slice(0, 20).map(r => { + const file = r.filename || r.path || '?'; + const line = r.lineNumber || r.linenumber || '?'; + const text = (r.line || r.content || '').trim(); + return `${file}:${line} ${text}`; + }).join('\n'); + } + + // ─── 分支操作 ─────────────────────────────────────────── + case 'git_branch_list': { + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/branches`); + if (res.status !== 200) return `获取分支失败: ${JSON.stringify(res.data)}`; + return res.data.map(b => { + const active = b.active ? '🟢' : '⚪'; + return `${active} ${b.name}`; + }).join('\n'); + } + + case 'git_branch_create': { + const branchName = args.name; + const base = args.base || 'main'; + const res = await giteaApi('POST', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/branches`, { + new_branch_name: branchName, + old_branch_name: base, + }); + if (res.status >= 200 && res.status < 300) { + return `分支已创建: ${branchName} (基于 ${base})`; + } + return `创建失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + + case 'git_pull': { + const branch = args.branch || 'main'; + const authUrl = `http://${CONFIG.giteaOwner}:${CONFIG.giteaToken}@127.0.0.1:3001/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}.git`; + gitExec(`git remote set-url origin ${authUrl}`); + const result = gitExec(`git fetch origin && git reset --hard origin/${branch}`); + if (result.ok) { + return `代码已同步: ${result.output}`; + } + return `同步失败: ${result.error}`; + } + + case 'git_push_local': { + const branch = args.branch || 'main'; + const result = gitExec(`git push origin ${branch}`); + if (result.ok) { + return `推送成功: ${result.output}`; + } + return `推送失败: ${result.error}`; + } + + case 'git_log': { + const count = args.count || 10; + const branch = args.branch ? ` ${args.branch}` : ''; + const result = gitExec(`git log --oneline -${count}${branch}`); + return result.ok ? result.output : result.error; + } + + // ─── Issue / PR ──────────────────────────────────────── + case 'issue_list': { + const state = args.state || 'open'; + const limit = args.limit || 10; + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/issues?state=${state}&limit=${limit}`); + if (res.status !== 200) return `获取 Issue 失败: ${JSON.stringify(res.data)}`; + if (!res.data.length) return `没有 ${state} 的 Issue`; + return res.data.map(i => `#${i.number} [${i.state}] ${i.title}`).join('\n'); + } + + case 'issue_create': { + const res = await giteaApi('POST', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/issues`, { + title: args.title, + body: args.body || '', + labels: args.labels || [], + }); + if (res.status >= 200 && res.status < 300) { + return `Issue 已创建: #${res.data.number} ${res.data.title}`; + } + return `创建失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + + case 'pr_list': { + const state = args.state || 'open'; + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/pulls?state=${state}`); + if (res.status !== 200) return `获取 PR 失败: ${JSON.stringify(res.data)}`; + if (!res.data.length) return `没有 ${state} 的 PR`; + return res.data.map(p => `#${p.number} [${p.state}] ${p.title} (${p.head?.label || '?'} → ${p.base?.label || '?'})`).join('\n'); + } + + case 'pr_create': { + const res = await giteaApi('POST', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/pulls`, { + title: args.title, + body: args.body || '', + head: args.head, + base: args.base || 'main', + }); + if (res.status >= 200 && res.status < 300) { + return `PR 已创建: #${res.data.number} ${res.data.title}`; + } + return `创建失败 (${res.status}): ${JSON.stringify(res.data)}`; + } + + // ─── 工作流 ───────────────────────────────────────────── + case 'workflow_list': { + const limit = args.limit || 10; + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/actions/tasks?limit=${limit}`); + if (res.status !== 200) return `获取工作流失败: ${JSON.stringify(res.data)}`; + const runs = res.data.workflow_runs || []; + if (!runs.length) return '没有工作流运行记录'; + return runs.map(r => { + const icon = r.status === 'success' ? '✅' : r.status === 'failure' ? '❌' : r.status === 'skipped' ? '⏭️' : '🔄'; + return `${icon} #${r.run_number} ${r.name} (${r.head_branch}) — ${r.display_title}`; + }).join('\n'); + } + + case 'workflow_trigger': { + const wfName = args.workflow_name; + const ref = args.ref || 'main'; + const res = await giteaApi('POST', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/actions/runs`, { + workflow_id: wfName, + ref: ref, + }); + if (res.status >= 200 && res.status < 300) { + return `工作流已触发: ${wfName}`; + } + // Forgejo 的 workflow_dispatch API 可能不同 + return `触发请求已发送 (${res.status}): ${JSON.stringify(res.data)}`; + } + + // ─── CVM 操作 ─────────────────────────────────────────── + case 'cvm_power': { + const action = args.action; + if (!['start', 'stop', 'status'].includes(action)) { + return '无效操作,只支持: start / stop / status'; + } + + // 本机操作:直接检查 + if (action === 'status' && (!args.target || args.target === 'self')) { + const hostname = gitExec('hostname').output || 'unknown'; + const uptime = gitExec('uptime').output || 'unknown'; + return `本机 (${hostname}): ${uptime}`; + } + + // 远程 CVM 操作需要腾讯云 API 密钥 + // 从 Vault 获取 + try { + const vaultRes = await fetch(`http://127.0.0.1:8080/internal/fetch/COS_SECRET_ID`); + // 如果 Vault 不可用,尝试环境变量 + } catch { + // Vault 不可用 + } + + // 使用环境变量方式(Forgejo Secrets 注入的) + if (action === 'status') { + const result = gitExec(`bash ${CONFIG.cvmPowerScript} status`, CONFIG.repoDir); + return result.ok ? result.output : result.error; + } + + return `CVM ${action} 操作需通过 Forgejo workflow 执行(需要腾讯云密钥),请使用 workflow_trigger 触发 cvm-power-${action === 'start' ? 'on' : 'off'} 工作流`; + } + + // ─── 服务器健康 ───────────────────────────────────────── + case 'server_health': { + const lines = []; + lines.push(`时间: ${new Date().toISOString()}`); + lines.push(`主机: ${gitExec('hostname').output || '?'}`); + lines.push(`系统: ${gitExec('uname -srm').output || '?'}`); + lines.push(`CPU: ${gitExec('nproc').output || '?'} 核`); + lines.push(`内存: ${gitExec("free -h | awk '/Mem:/ {print $2 \" 已用 \" $3 \" 可用 \" $7}'").output || '?'}`); + lines.push(`磁盘: ${gitExec("df -h / | awk 'NR==2 {print $4}'").output || '?'} 可用`); + + // 服务状态 + const services = ['nginx', 'forgejo', 'gitea-runner']; + for (const svc of services) { + const r = gitExec(`systemctl is-active ${svc}`); + lines.push(`${r.output === 'active' ? '✅' : '❌'} ${svc}: ${r.output || '未知'}`); + } + + // PM2 + const pm2 = gitExec('pm2 jlist'); + if (pm2.ok) { + try { + const procs = JSON.parse(pm2.output); + for (const p of procs) { + const st = p.pm2_env?.status || '?'; + lines.push(`${st === 'online' ? '✅' : '❌'} PM2 ${p.name}: ${st}`); + } + } catch {} + } + + return lines.join('\n'); + } + + // ─── Secrets ──────────────────────────────────────────── + case 'secrets_list': { + const res = await giteaApi('GET', `/api/v1/repos/${CONFIG.giteaOwner}/${CONFIG.giteaRepo}/actions/secrets`); + if (res.status !== 200) return `获取 Secrets 失败: ${JSON.stringify(res.data)}`; + if (!res.data.length) return '没有配置任何 Forgejo Secret'; + return res.data.map(s => `🔑 ${s.name} (创建于 ${s.created_at || '?'})`).join('\n'); + } + + case 'vault_status': { + try { + const res = await fetch('http://127.0.0.1:8080/admin/__healthz'); + if (res.ok) { + const data = await res.json(); + return `Vault: ✅ 运行中\n主密钥: ${data.has_master ? '✅' : '❌'}\n加密库: ${data.has_vault_enc ? '✅' : '❌'}`; + } + } catch {} + return 'Vault: ❌ 未响应'; + } + + // ─── 铸渊大脑 ─────────────────────────────────────────── + case 'brain_status': { + const brainPath = path.join(CONFIG.repoDir, 'brain', 'fast-wake.json'); + try { + const data = JSON.parse(fs.readFileSync(brainPath, 'utf8')); + return `铸渊核心大脑:\n- 身份: ${data.identity?.name} (${data.identity?.id})\n- 状态: ${data.system_status?.health?.substring(0, 100) || '?'}...\n- 大脑完整性: ${data.brain_complete ? '✅ 完整' : '❌ 不完整'}\n- 上次会话: ${data.last_session?.growth?.substring(0, 80) || '?'}...\n- 下一步: ${data.last_session?.next_task?.substring(0, 80) || '?'}`; + } catch (e) { + return `读取大脑失败: ${e.message}`; + } + } + + case 'brain_update_temporal': { + const result = gitExec(`node scripts/temporal-clock.js`, CONFIG.repoDir); + return result.ok ? result.output : result.error; + } + + default: + return `未知工具: ${name}`; + } +} + +// ─── MCP 协议处理(Streamable HTTP)────────────────────────── + +const app = express(); +app.use(express.json({ limit: '10mb' })); + +// CORS — 允许 WorkBuddy 跨域连接 +app.use(require('cors')({ + origin: '*', + methods: ['GET', 'POST', 'DELETE', 'OPTIONS'], + allowedHeaders: ['Content-Type', 'Authorization', 'Mcp-Session-Id'], + exposedHeaders: ['Mcp-Session-Id'], +})); + +// ─── 认证中间件 ────────────────────────────────────────────── +function authenticate(req, res, next) { + const auth = req.headers['authorization'] || ''; + const token = auth.replace(/^Bearer\s+/i, '').trim(); + + if (!token) { + return res.status(401).json({ error: '缺少认证令牌' }); + } + + if (token !== ACCESS_KEY) { + return res.status(403).json({ error: '认证令牌无效' }); + } + + next(); +} + +// ─── 会话管理 ────────────────────────────────────────────── +const sessions = new Map(); + +function getSessionId(req) { + return req.headers['mcp-session-id'] || null; +} + +// ─── JSON-RPC 处理 ────────────────────────────────────────── + +async function handleJsonRpc(req, res) { + const message = req.body; + + // 批量消息 + if (Array.isArray(message)) { + const results = await Promise.all(message.map(m => processRpc(m))); + return res.json(results); + } + + const result = await processRpc(message); + return res.json(result); +} + +async function processRpc(message) { + const { jsonrpc, id, method, params } = message; + + // 通知类消息(无 id) + if (method === 'notifications/cancelled') { + return null; + } + + // 请求类消息 + switch (method) { + case 'initialize': { + const sessionId = crypto.randomUUID(); + sessions.set(sessionId, { created: Date.now() }); + + return { + jsonrpc: '2.0', + id, + result: { + protocolVersion: '2025-03-26', + capabilities: { + tools: { listChanged: false }, + }, + serverInfo: { + name: 'guanghulab-mcp-server', + version: '1.0.0', + title: '铸渊 MCP Server · 光湖代码仓库', + }, + }, + _meta: { + sessionId, + }, + }; + } + + case 'tools/list': { + return { + jsonrpc: '2.0', + id, + result: { + tools: TOOLS, + }, + }; + } + + case 'tools/call': { + const toolName = params?.name; + const toolArgs = params?.arguments || {}; + + try { + const result = await executeTool(toolName, toolArgs); + return { + jsonrpc: '2.0', + id, + result: { + content: [{ + type: 'text', + text: String(result), + }], + }, + }; + } catch (e) { + return { + jsonrpc: '2.0', + id, + error: { + code: -32000, + message: `工具执行错误: ${e.message}`, + }, + }; + } + } + + case 'ping': { + return { + jsonrpc: '2.0', + id, + result: {}, + }; + } + + default: { + if (id !== undefined) { + return { + jsonrpc: '2.0', + id, + error: { + code: -32601, + message: `未知方法: ${method}`, + }, + }; + } + return null; + } + } +} + +// ─── 路由 ────────────────────────────────────────────────── + +// MCP 端点 — POST (客户端请求) +app.post('/mcp', authenticate, async (req, res) => { + await handleJsonRpc(req, res); +}); + +// MCP 端点 — GET (SSE 通知流,保持连接) +app.get('/mcp', authenticate, (req, res) => { + res.setHeader('Content-Type', 'text/event-stream'); + res.setHeader('Cache-Control', 'no-cache'); + res.setHeader('Connection', 'keep-alive'); + res.flushHeaders(); + + // 发送心跳 + const heartbeat = setInterval(() => { + res.write(': heartbeat\n\n'); + }, 30000); + + req.on('close', () => { + clearInterval(heartbeat); + }); +}); + +// MCP 端点 — DELETE (关闭会话) +app.delete('/mcp', authenticate, (req, res) => { + const sid = getSessionId(req); + if (sid) sessions.delete(sid); + res.status(204).end(); +}); + +// 健康检查(无需认证) +app.get('/health', (req, res) => { + res.json({ + status: 'ok', + service: 'guanghulab-mcp-server', + version: '1.0.0', + sessions: sessions.size, + gitea: CONFIG.giteaToken ? 'configured' : 'missing', + sovereign: 'TCS-0002∞ · 国作登字-2026-A-00037559', + }); +}); + +// ─── 启动 ────────────────────────────────────────────────── + +app.listen(CONFIG.port, CONFIG.host, () => { + console.log(`[mcp] 铸渊 MCP Server 已启动`); + console.log(`[mcp] 监听: http://${CONFIG.host}:${CONFIG.port}`); + console.log(`[mcp] MCP 端点: POST/GET/DELETE /mcp`); + console.log(`[mcp] 健康检查: GET /health`); + console.log(`[mcp] Gitea: ${CONFIG.giteaUrl}`); + console.log(`[mcp] 仓库: ${CONFIG.giteaOwner}/${CONFIG.giteaRepo}`); + console.log(`[mcp] 认证密钥: ${ACCESS_KEY.substring(0, 8)}...`); + console.log(`[mcp] 铸渊 · ICE-GL-ZY001 · TCS-0002∞`); +}); diff --git a/server/mcp-server/package-lock.json b/server/mcp-server/package-lock.json new file mode 100644 index 0000000..3075a70 --- /dev/null +++ b/server/mcp-server/package-lock.json @@ -0,0 +1,1527 @@ +{ + "name": "guanghulab-mcp-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "guanghulab-mcp-server", + "version": "1.0.0", + "license": "UNLICENSED", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0", + "cors": "^2.8.5", + "express": "^4.21.0" + } + }, + "node_modules/@hono/node-server": { + "version": "1.19.14", + "resolved": "http://mirrors.tencent.com/npm/@hono/node-server/-/node-server-1.19.14.tgz", + "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "license": "MIT", + "engines": { + "node": ">=18.14.1" + }, + "peerDependencies": { + "hono": "^4" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.29.0", + "resolved": "http://mirrors.tencent.com/npm/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", + "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "license": "MIT", + "dependencies": { + "@hono/node-server": "^1.19.9", + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.2.1", + "express-rate-limit": "^8.2.1", + "hono": "^4.11.4", + "jose": "^6.1.3", + "json-schema-typed": "^8.0.2", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.25 || ^4.0", + "zod-to-json-schema": "^3.25.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1", + "zod": "^3.25 || ^4.0" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + }, + "zod": { + "optional": false + } + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.2", + "resolved": "http://mirrors.tencent.com/npm/body-parser/-/body-parser-2.2.2.tgz", + "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.1", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.1.0", + "resolved": "http://mirrors.tencent.com/npm/content-disposition/-/content-disposition-1.1.0.tgz", + "integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "http://mirrors.tencent.com/npm/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/debug": { + "version": "4.4.3", + "resolved": "http://mirrors.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.2.1", + "resolved": "http://mirrors.tencent.com/npm/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "http://mirrors.tencent.com/npm/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "http://mirrors.tencent.com/npm/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "http://mirrors.tencent.com/npm/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "http://mirrors.tencent.com/npm/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.2", + "resolved": "http://mirrors.tencent.com/npm/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/ms": { + "version": "2.1.3", + "resolved": "http://mirrors.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "http://mirrors.tencent.com/npm/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.1", + "resolved": "http://mirrors.tencent.com/npm/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.1", + "resolved": "http://mirrors.tencent.com/npm/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "http://mirrors.tencent.com/npm/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "http://mirrors.tencent.com/npm/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "http://mirrors.tencent.com/npm/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "http://mirrors.tencent.com/npm/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "http://mirrors.tencent.com/npm/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/body-parser": { + "version": "1.20.5", + "resolved": "http://mirrors.tencent.com/npm/body-parser/-/body-parser-1.20.5.tgz", + "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "~1.2.0", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "on-finished": "~2.4.1", + "qs": "~6.15.1", + "raw-body": "~2.5.3", + "type-is": "~1.6.18", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.3", + "resolved": "http://mirrors.tencent.com/npm/raw-body/-/raw-body-2.5.3.tgz", + "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.4.24", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "http://mirrors.tencent.com/npm/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "http://mirrors.tencent.com/npm/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "http://mirrors.tencent.com/npm/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "http://mirrors.tencent.com/npm/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "http://mirrors.tencent.com/npm/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "http://mirrors.tencent.com/npm/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.7", + "resolved": "http://mirrors.tencent.com/npm/cookie-signature/-/cookie-signature-1.0.7.tgz", + "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.6", + "resolved": "http://mirrors.tencent.com/npm/cors/-/cors-2.8.6.tgz", + "integrity": "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "http://mirrors.tencent.com/npm/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "http://mirrors.tencent.com/npm/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "http://mirrors.tencent.com/npm/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "http://mirrors.tencent.com/npm/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "http://mirrors.tencent.com/npm/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "http://mirrors.tencent.com/npm/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "http://mirrors.tencent.com/npm/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "http://mirrors.tencent.com/npm/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "http://mirrors.tencent.com/npm/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.8", + "resolved": "http://mirrors.tencent.com/npm/eventsource-parser/-/eventsource-parser-3.0.8.tgz", + "integrity": "sha512-70QWGkr4snxr0OXLRWsFLeRBIRPuQOvt4s8QYjmUlmlkyTZkRqS7EDVRZtzU3TiyDbXSzaOeF0XUKy8PchzukQ==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/express": { + "version": "4.22.2", + "resolved": "http://mirrors.tencent.com/npm/express/-/express-4.22.2.tgz", + "integrity": "sha512-IuL+Elrou2ZvCFHs18/CIzy2Nzvo25nZ1/D2eIZlz7c+QUayAcYoiM2BthCjs+EBHVpjYjcuLDAiCWgeIX3X1Q==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "~1.20.5", + "content-disposition": "~0.5.4", + "content-type": "~1.0.4", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "~0.1.12", + "proxy-addr": "~2.0.7", + "qs": "~6.15.1", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "~0.19.0", + "serve-static": "~1.16.2", + "setprototypeof": "1.2.0", + "statuses": "~2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "8.5.1", + "resolved": "http://mirrors.tencent.com/npm/express-rate-limit/-/express-rate-limit-8.5.1.tgz", + "integrity": "sha512-5O6KYmyJEpuPJV5hNTXKbAHWRqrzyu+OI3vUnSd2kXFubIVpG7ezpgxQy76Zo5GQZtrQBg86hF+CM/NX+cioiQ==", + "license": "MIT", + "dependencies": { + "ip-address": "^10.2.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "http://mirrors.tencent.com/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "http://mirrors.tencent.com/npm/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/finalhandler": { + "version": "1.3.2", + "resolved": "http://mirrors.tencent.com/npm/finalhandler/-/finalhandler-1.3.2.tgz", + "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "~2.4.1", + "parseurl": "~1.3.3", + "statuses": "~2.0.2", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "http://mirrors.tencent.com/npm/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "http://mirrors.tencent.com/npm/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "http://mirrors.tencent.com/npm/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "http://mirrors.tencent.com/npm/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "http://mirrors.tencent.com/npm/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "http://mirrors.tencent.com/npm/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "http://mirrors.tencent.com/npm/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hono": { + "version": "4.12.18", + "resolved": "http://mirrors.tencent.com/npm/hono/-/hono-4.12.18.tgz", + "integrity": "sha512-RWzP96k/yv0PQfyXnWjs6zot20TqfpfsNXhOnev8d1InAxubW93L11/oNUc3tQqn2G0bSdAOBpX+2uDFHV7kdQ==", + "license": "MIT", + "engines": { + "node": ">=16.9.0" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "http://mirrors.tencent.com/npm/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "license": "MIT", + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "http://mirrors.tencent.com/npm/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "http://mirrors.tencent.com/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ip-address": { + "version": "10.2.0", + "resolved": "http://mirrors.tencent.com/npm/ip-address/-/ip-address-10.2.0.tgz", + "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "http://mirrors.tencent.com/npm/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "http://mirrors.tencent.com/npm/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jose": { + "version": "6.2.3", + "resolved": "http://mirrors.tencent.com/npm/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "http://mirrors.tencent.com/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "8.0.2", + "resolved": "http://mirrors.tencent.com/npm/json-schema-typed/-/json-schema-typed-8.0.2.tgz", + "integrity": "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA==", + "license": "BSD-2-Clause" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "http://mirrors.tencent.com/npm/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "http://mirrors.tencent.com/npm/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "http://mirrors.tencent.com/npm/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "http://mirrors.tencent.com/npm/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "http://mirrors.tencent.com/npm/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "http://mirrors.tencent.com/npm/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "http://mirrors.tencent.com/npm/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "http://mirrors.tencent.com/npm/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "http://mirrors.tencent.com/npm/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "http://mirrors.tencent.com/npm/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "http://mirrors.tencent.com/npm/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "http://mirrors.tencent.com/npm/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "http://mirrors.tencent.com/npm/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "http://mirrors.tencent.com/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.13", + "resolved": "http://mirrors.tencent.com/npm/path-to-regexp/-/path-to-regexp-0.1.13.tgz", + "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==", + "license": "MIT" + }, + "node_modules/pkce-challenge": { + "version": "5.0.1", + "resolved": "http://mirrors.tencent.com/npm/pkce-challenge/-/pkce-challenge-5.0.1.tgz", + "integrity": "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "http://mirrors.tencent.com/npm/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/qs": { + "version": "6.15.1", + "resolved": "http://mirrors.tencent.com/npm/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "http://mirrors.tencent.com/npm/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "http://mirrors.tencent.com/npm/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "license": "MIT", + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.2", + "resolved": "http://mirrors.tencent.com/npm/iconv-lite/-/iconv-lite-0.7.2.tgz", + "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "http://mirrors.tencent.com/npm/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "http://mirrors.tencent.com/npm/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/debug": { + "version": "4.4.3", + "resolved": "http://mirrors.tencent.com/npm/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/router/node_modules/ms": { + "version": "2.1.3", + "resolved": "http://mirrors.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.4.2", + "resolved": "http://mirrors.tencent.com/npm/path-to-regexp/-/path-to-regexp-8.4.2.tgz", + "integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "http://mirrors.tencent.com/npm/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "http://mirrors.tencent.com/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "0.19.2", + "resolved": "http://mirrors.tencent.com/npm/send/-/send-0.19.2.tgz", + "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.1", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "~2.4.1", + "range-parser": "~1.2.1", + "statuses": "~2.0.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "http://mirrors.tencent.com/npm/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/serve-static": { + "version": "1.16.3", + "resolved": "http://mirrors.tencent.com/npm/serve-static/-/serve-static-1.16.3.tgz", + "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "~0.19.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "http://mirrors.tencent.com/npm/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "http://mirrors.tencent.com/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "http://mirrors.tencent.com/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "http://mirrors.tencent.com/npm/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "http://mirrors.tencent.com/npm/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "http://mirrors.tencent.com/npm/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "http://mirrors.tencent.com/npm/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "http://mirrors.tencent.com/npm/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "http://mirrors.tencent.com/npm/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "http://mirrors.tencent.com/npm/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "http://mirrors.tencent.com/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "http://mirrors.tencent.com/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "http://mirrors.tencent.com/npm/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.2", + "resolved": "http://mirrors.tencent.com/npm/zod-to-json-schema/-/zod-to-json-schema-3.25.2.tgz", + "integrity": "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25.28 || ^4" + } + } + } +} diff --git a/server/mcp-server/package.json b/server/mcp-server/package.json new file mode 100644 index 0000000..adf52fe --- /dev/null +++ b/server/mcp-server/package.json @@ -0,0 +1,18 @@ +{ + "name": "guanghulab-mcp-server", + "version": "1.0.0", + "description": "铸渊 MCP Server — 光湖代码仓库远程操作接口 · WorkBuddy/CodeBuddy 一键连接", + "main": "index.js", + "scripts": { + "start": "node index.js", + "dev": "node --watch index.js" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0", + "express": "^4.21.0", + "cors": "^2.8.5" + }, + "author": "铸渊 · ICE-GL-ZY001", + "license": "UNLICENSED", + "private": true +} diff --git a/server/nginx/guanghulab-cvm.conf b/server/nginx/guanghulab-cvm.conf index 4c46110..63acb21 100644 --- a/server/nginx/guanghulab-cvm.conf +++ b/server/nginx/guanghulab-cvm.conf @@ -8,6 +8,7 @@ # # 路由: # /git/ → Forgejo (127.0.0.1:3001) +# /mcp → MCP Server (127.0.0.1:8083) # /wake/ → Wake Gate 唤醒门 (127.0.0.1:8081) # /sync/ → Git Sync 同步服务 (127.0.0.1:8082) # / → 仓库首页 (Forgejo 处理) @@ -80,6 +81,30 @@ server { # deny all; } + # ─── 铸渊 MCP Server (/mcp) ─── + # WorkBuddy / CodeBuddy 通过 MCP 协议连接 + location /mcp { + proxy_pass http://127.0.0.1:8083; + 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; + + # SSE / 长连接支持 + proxy_set_header Connection ''; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + } + + # ─── MCP 健康检查 (/mcp-health) ─── + location = /mcp-health { + proxy_pass http://127.0.0.1:8083/health; + access_log off; + } + # ─── 健康探针 ─── location = /health { access_log off;