feat: install latest main commit snapshots

This commit is contained in:
nac
2026-08-18 17:32:56 +00:00
parent 4c53f90947
commit c7e62d1d6d
7 changed files with 128 additions and 50 deletions
+54 -18
View File
@@ -6,7 +6,7 @@
## 完成标准
- 下载本文件所在的同一固定 Release,不使用默认分支;
- 从 Gitea `main` 解析安装开始时的最新完整 Commit SHA,并将本次安装的文档、源码和构建全部固定到该 Commit;
- 只连接固定的 NocoBase API `https://justconn.top/api`;
- MCP 在用户本机以 stdio 运行,默认只读;
- 通过 NocoBase 原生 OAuth 2.1 认证当前用户,权限仍跟随本人的业务角色;
@@ -20,28 +20,39 @@
- OAuth Token 不得进入聊天、命令参数、环境变量、CRM 配置、剪贴板日志或 MCP 客户端配置。
- 不使用 `sudo`,不执行 `curl | sh` 或 `wget | sh`。
- 不静默安装 Git、Node.js、包管理器或其他系统工具。
- 解析 `main` 后只使用带完整 Commit SHA 的不可变 URL;一次安装中不得再次读取移动中的 `main` 文件。
- 最新 Commit 无法下载、检查、测试或构建时必须停止,不得静默退回旧 Release、旧 Commit 或其他来源。
- 修改 MCP 客户端配置前展示目标文件与新增项,创建备份,并结构化合并;不得覆盖其他 server。
- 默认不启用写入、原始数据、后台服务或网络监听。
- 不询问或接受其他 NocoBase URL,也不允许通过参数、配置或凭证文件覆盖固定 API 地址。
## 安装流程
### 1. 确认本机位置与 Release 权限
### 1. 解析并固定最新 Commit
确定当前 Agent/MCP 客户端及其配置路径,以及普通用户应用数据目录。NocoBase API 已固定为 `https://justconn.top/api`,不需要向用户询问地址。
从本文件 URL 解析固定 Release Tag。读取同一 Release 的资产列表,只接受:
安装源固定为:
- `donaldttt-nocobase-crm-mcp-<version>.tgz`;
- `SHA256SUMS`。
- 仓库:`https://git.justconn.top/gitea-admin/nocobase-mcp`
- 分支:`main`
- 分支 API:`https://git.justconn.top/api/v1/repos/gitea-admin/nocobase-mcp/branches/main`
仓库访问受限时,必须使用当前用户已经授权的代码托管平台连接读取 Release;无权访问时停止,不得退回默认分支、源码 clone 或索取用户的访问令牌到聊天。
通过当前用户已经授权的 Gitea API/连接读取分支 API,只解析一次 `commit.id`,并验证它是 40 位十六进制完整 SHA。记录为 `<commit-sha>` 后,本次安装即使发现 `main` 又有新提交,也继续完成这个已固定快照;下一次安装才重新解析最新提交。
立即从以下不可变地址重新读取安装协议,后续不再依赖最初的 `main` 页面内容:
```text
https://git.justconn.top/gitea-admin/nocobase-mcp/raw/commit/<commit-sha>/INSTALL.md
```
仓库访问受限时必须使用当前用户已有的授权连接;无权访问时停止,不得索取或接收用户在聊天中发送的 Gitea 访问令牌。
### 2. 一次性说明本机变更
检查 `node --version` 和 `npm --version`。要求 Node.js `>=20.11`。
如果 Node.js 缺失或版本过低,向用户说明需要安装或升级 Node.js、官方来源、目标位置和影响,取得明确同意后再使用操作系统的正规安装方式。不能因为 npm 不存在就直接尝试全局安装。
如果 Node.js 缺失或版本过低,向用户说明需要安装或升级 Node.js、官方来源、目标位置和影响,取得明确同意后再使用操作系统的正规安装方式。不能因为 npm 不存在就直接尝试全局安装。还需确认 npm 能读取锁定依赖;不得改用未锁定的依赖版本。
正常安装只会留下:
@@ -50,25 +61,46 @@
- 权限受限的本机凭证文件;
- MCP 客户端配置及其备份。
不会安装 Git、Python、uv、`nb CLI`、后台服务或本机监听端口。
源码快照、构建期 `node_modules` 和本地 tarball 只放在新建的临时目录,安装完成后不作为持久文件保留。不会安装 Git、Python、uv、`nb CLI`、后台服务或本机监听端口。
### 3. 下载并验证固定发布物
### 3. 下载、验证并构建固定 Commit
通过当前 Gitea 实例或经批准分发渠道的已授权 API/连接,将两个 Release 资产下载到新建的临时目录。验证 tarball 的 SHA-256 与 `SHA256SUMS` 完全一致;不一致立即停止并删除未使用的下载文件。
在新建的临时目录中下载 `<commit-sha>` 的源码归档,不下载 Release 资产,也不从移动的 `main` URL 下载源码。Windows 使用 `.zip`,macOS/Linux 使用 `.tar.gz`;两种归档都必须包含同一个已解析的完整 Commit SHA:
```text
Windows: https://git.justconn.top/gitea-admin/nocobase-mcp/archive/<commit-sha>.zip
macOS/Linux: https://git.justconn.top/gitea-admin/nocobase-mcp/archive/<commit-sha>.tar.gz
```
不要让用户选择版本,也不要因为操作系统不同而改用 Release。每次新的安装任务都重新解析当时 `main` 的最新 Commit,随后只下载并使用该 SHA。
下载后记录归档 SHA-256。解包前拒绝绝对路径、`..` 路径穿越或逃出临时目录的链接;源码根目录必须包含 `package.json`、`package-lock.json`、`install-manifest.json`、`INSTALL.md` 和 `src/`。
确认归档中的 `install-manifest.json` 声明 `distribution.branch` 为 `main`、`distribution.strategy` 为 `resolve-latest-commit-then-pin`。随后只在这个临时源码目录运行:
```bash
npm ci
npm run check
npm test
npm run build
npm pack --pack-destination <temporary-output-directory>
```
任何一步失败都停止并报告 `<commit-sha>` 与失败步骤,不得改装旧 Release。记录本地生成 npm tarball 的 SHA-256;安装结束时只报告哈希,不发送或上传 tarball。
选择用户级安装前缀,例如:
- Windows:`%LOCALAPPDATA%\NocoBaseMCP\app`
- macOS:`~/Library/Application Support/NocoBaseMCP/app`
- Windows:`%LOCALAPPDATA%\nocobase-crm-mcp\app`
- macOS:`~/Library/Application Support/nocobase-crm-mcp/app`
- Linux:`${XDG_DATA_HOME:-~/.local/share}/nocobase-crm-mcp/app`
执行隔离安装,不使用全局目录:
```bash
npm install --prefix <install-prefix> --omit=dev <verified-release.tgz>
npm install --prefix <install-prefix> --omit=dev <locally-built-commit.tgz>
```
定位安装后的命令:POSIX 为 `<install-prefix>/node_modules/.bin/nocobase-crm-mcp`,Windows 为相同目录下的 `nocobase-crm-mcp.cmd`。
定位安装后的命令:POSIX 为 `<install-prefix>/node_modules/.bin/nocobase-crm-mcp`,Windows 为相同目录下的 `nocobase-crm-mcp.cmd`。运行 `--version` 和 `--help`,确认版本等于源码 `package.json`,并且帮助中包含本 Commit 安装协议使用的 `setup --no-browser` 选项;不一致时停止,不得继续注册旧二进制。
### 4. 浏览器登录 NocoBase
@@ -88,6 +120,8 @@ npm install --prefix <install-prefix> --omit=dev <verified-release.tgz>
然后由用户手动打开链接。设备授权约十分钟后失效;密码和浏览器会话始终留在 NocoBase,安装程序不会读取浏览器 Cookie。访问令牌临近过期时会自动使用刷新令牌续期,不影响日常 MCP 调用。
在 Hermes Agent、OpenClaw 或其他远程无界面环境中,Agent 应在可持续读取输出的后台会话运行 `setup --no-browser --json`,取得授权链接和确认码后立即通过当前消息通道发给用户,同时让进程继续轮询。只能转发 HTTPS 授权链接、用户确认码和有效期,绝不能转发 OAuth Token、设备码或凭据文件内容。一个 MCP 进程只能服务一个受信任的用户身份;多用户必须使用相互隔离的 Agent/MCP 实例和凭据路径。
POSIX 凭证目录使用 `0700`,凭证文件使用 `0600`。Windows 使用当前用户应用数据目录。凭证文件不保存或接受 API 地址,Token 不会出现在返回 JSON、命令参数、MCP 配置或日志中。不要复制其他用户的凭证文件;每个操作系统用户都必须单独登录。
只有在 OAuth 暂时不可用、管理员明确要求且用户拥有个人 Authorize Key 时,才使用:
@@ -108,7 +142,7 @@ POSIX 凭证目录使用 `0700`,凭证文件使用 `0600`。Windows 使用当
4. 重载或重启 MCP 客户端;
5. 调用 `crm_health`,要求 `ok=true`。
最终只报告 Release、安装目录、配置备份位置、认证方式和只读/写入模式,不显示任何 Token 或 Key。
最终只报告完整 Commit SHA、源码版本、本地构建 tarball 的 SHA-256、安装目录、配置备份位置、认证方式和只读/写入模式,不显示任何 Token 或 Key。
## 可选写入
@@ -121,11 +155,13 @@ POSIX 凭证目录使用 `0700`,凭证文件使用 `0600`。Windows 使用当
- `nocobase_auth_failed`:重新运行 `setup` 完成浏览器登录;不要换用共享高权限 Token 或 Key。
- `nocobase_request_failed` / `NO_PERMISSIONS`:检查用户角色、字段权限、行级权限与 `config.json` 映射,不得换用共享高权限身份。
- Node.js 缺失:报告前置条件并请求用户授权正规安装,不退回 Python/uv/nb CLI 方案。
- 受限 Release 无权访问:报告 Gitea 或分发渠道的权限问题,不退回 clone 默认分支。
- `main` 或 Commit 归档无权访问:报告 Gitea 权限问题,不索取聊天中的访问令牌,也不退回旧 Release。
- 最新 Commit 的依赖安装、检查、测试或构建失败:报告 SHA 和原始失败步骤后停止;不得以“先装可用版本”为由降级。
- 安装过程中 `main` 更新:不影响当前任务,继续完成开始时固定的 SHA;下次安装再取得新 SHA。
## 用户可发送给 Agent 的最短指令
```text
请按这个固定 Release 的协议帮我完成本机安装。默认只读;请运行 setup,让我只在 NocoBase 官方网页登录并确认授权。不要向我索要密码、Token 或 Authorize Key,也不要静默安装系统工具。完成前必须验证 crm_health:
<固定 Release 的 INSTALL.md 链接>
请按这个 INSTALL.md 帮我完成安装。每次先解析当前 Gitea 仓库 main 分支的最新完整 Commit SHA,并把本次安装固定在该 Commit;不要退回旧 Release。默认只读;请运行 setup,让我只在 NocoBase 官方网页登录并确认授权。不要向我索要密码、Token 或 Authorize Key,也不要静默安装系统工具。完成前必须验证 crm_health:
https://git.justconn.top/gitea-admin/nocobase-mcp/raw/branch/main/INSTALL.md
```
+20 -13
View File
@@ -11,28 +11,33 @@
- Node.js 20.11 或更高版本;
- 能访问 `https://justconn.top`;
- 你自己的 NocoBase 账号;
- 能读取当前 Gitea 仓库对应 Release 的权限。
- 能读取当前 Gitea 仓库 `main` 分支,并能访问 npm 软件源。
如果 Node.js 尚未安装,安装 Agent 会先说明需要进行的系统变更,并在获得你确认后再继续。
支持 Windows、macOS 和 Linux。三个平台都会安装 `main` 在任务开始时的最新 Commit;Windows 下载该 Commit 的 `.zip`,macOS/Linux 下载同一 Commit 的 `.tar.gz`。
不需要提前创建或复制 Authorize Key。安装程序会打开 NocoBase 官方网页;你在网页中登录并确认授权后,本机安装会自动继续。
### 最快安装方式
1. 打开当前 Gitea 仓库的 **Releases(版本发布)** 页面,选择要安装的固定版本。
2. 确认该版本包含 npm 安装包和 `SHA256SUMS`,然后打开同一版本下的 `INSTALL.md`。不要使用默认分支中的安装说明代替固定版本。
3. 把这个固定版本的 `INSTALL.md` 链接和下面的文字一起发给安装 Agent:
把下面整段直接复制给安装 Agent:
```text
请按这个固定版本的安装协议帮我完成 NocoBase CRM MCP 本机安装。
请按这个 INSTALL.md 帮我完成 NocoBase CRM MCP 安装。
每次先解析当前 Gitea 仓库 main 分支的最新完整 Commit SHA,并把本次安装固定在该 Commit;不要退回旧 Release。
默认只读;请运行 setup,让我只在 NocoBase 官方网页完成登录和授权。
不要向我索要密码、Token 或 Authorize Key,也不要静默安装系统工具。完成前请验证 crm_health 返回 ok=true。
安装协议:
https://git.justconn.top/gitea-admin/nocobase-mcp/raw/branch/main/INSTALL.md
```
4. 浏览器打开后,在 `justconn.top` 登录并核对页面与终端显示的确认码,然后点击授权。浏览器没有自动打开时,复制终端显示的授权链接手动打开。
5. 安装完成后,确认 Agent 报告 `crm_health` 返回 `ok=true`。
1. Agent 会读取 Gitea `main` 的最新 Commit,把源码快照、安装协议和构建过程固定到同一个 SHA,再在临时目录完成检查和打包。
2. 浏览器打开后,在 `justconn.top` 登录并核对页面与终端显示的确认码,然后点击授权。远程或无界面 Agent 会把授权链接和确认码发到当前对话。
3. 安装完成后,确认 Agent 报告完整 Commit SHA,并且 `crm_health` 返回 `ok=true`。
完整的安装和验收规则见 [INSTALL.md](INSTALL.md)。实际安装时应使用所选 Release Tag 中的同一文件。
完整的安装和验收规则见 [INSTALL.md](INSTALL.md)。该 `main` 链接是安装入口;Agent 必须先解析一次最新 Commit,然后重新读取该 Commit 中不可变的同一文件,不能在一次安装中混用不同提交。
## 重要注意事项
@@ -40,8 +45,9 @@
- **默认只读:** 安装后默认只能查询 CRM,不会创建、更新或删除业务数据。
- **权限跟随本人:** MCP 不会绕过 NocoBase 的角色、字段权限和行级权限,也不会使用共享管理员账号。
- **只连接公司环境:** 程序固定连接 `https://justconn.top/api`,不会要求你填写其他 NocoBase 地址。
- **安装在用户目录:** 不使用 `sudo`,不会全局安装本项目,也不需要 Git、Python、uv 或 `nb CLI`。
- **受限仓库需要授权:** 如果 Agent 无法读取 Gitea Release,请联系仓库管理员开通权限,不要把访问令牌发到聊天中。
- **始终安装最新提交:** 每次安装只解析一次 `main` 的最新 Commit SHA,随后固定该快照完成构建;不会因为旧 Release 可用而安装旧代码。
- **安装在用户目录:** 不使用 `sudo`,不会全局安装本项目,也不需要 Git、Python、uv 或 `nb CLI`。源码和构建依赖只存在于临时目录,安装后仅保留打包运行文件。
- **受限仓库需要授权:** 如果 Agent 无法读取 Gitea `main` 或对应 Commit 快照,请联系仓库管理员开通权限,不要把访问令牌发到聊天中。
## 安装后可以做什么
@@ -75,13 +81,14 @@
- 仅在 OAuth 暂时不可用且管理员明确要求时,才使用 `setup --manual-key` 的隐藏输入备用模式;不要把 Key 发到聊天中。
- 返回 `NO_PERMISSIONS`:请检查本人 NocoBase 角色和数据权限。
- 请求超时:确认可以访问 `https://justconn.top`,或缩小查询范围。
- Release 无法下载:确认当前账号或 Agent 已获得 Gitea 仓库和 Release 的读取权限。
- 最新 Commit 无法解析或构建失败:停止安装并报告 Commit SHA 和失败步骤,不要退回旧 Release。
- 源码快照无法下载:确认当前账号或 Agent 已获得 Gitea 仓库的读取权限。
更多故障处理和更新、回滚说明见 [本机交付与权限验收](docs/LOCAL_DELIVERY.md)。
## 更多文档
- [完整安装协议](INSTALL.md):供安装 Agent 执行的固定版本安装与验收流程。
- [完整安装协议](INSTALL.md):供安装 Agent 解析并固定最新 Commit、构建、安装和验收。
- [命令与工具参考](docs/REFERENCE.md):CLI 命令、MCP 工具和可选运行开关。
- [内部架构](docs/ARCHITECTURE.md):模块边界、身份与网络安全设计。
- [本机交付与权限验收](docs/LOCAL_DELIVERY.md):运维、权限验收、更新和回滚。
@@ -98,4 +105,4 @@ npm run build
node dist/index.js --help
```
本项目要求 Node.js 20.11 或更高版本。正式 Release 已将运行代码和依赖打包,最终用户不需要源码开发环境。
本项目要求 Node.js 20.11 或更高版本。安装 Agent 会在临时目录从锁定依赖构建最新 Commit;最终运行包不含额外 npm 运行时依赖,用户不需要长期保留源码开发环境。
+3 -2
View File
@@ -15,7 +15,7 @@ MCP client → TypeScript tool boundary → CRM domain service → NocoBaseClien
- `src/nocobase-client.ts` 是唯一远程适配器,直接实现 NocoBase resource action 协议、data-modeling 读取、项目附件关系和 ACL 检查。
- `src/crm-service.ts` 负责 CRM 查询、解析、分页、聚合和可读输出;`src/crm-helpers.ts` 与 `src/filters.ts` 保存纯函数。
- `src/project-service.ts` 只允许固定项目字段的 create/update;`src/tools.ts` 是稳定 MCP 契约和错误/原始数据策略边界。
- `scripts/build.mjs` 用 esbuild 将 MCP SDK、Zod 和所有运行代码打成一个 ESM 文件。Release tarball 没有运行时 npm 依赖。
- `scripts/build.mjs` 用 esbuild 将 MCP SDK、Zod 和所有运行代码打成一个 ESM 文件。按 Commit 构建的安装 tarball 和正式 Release tarball 都没有运行时 npm 依赖。
## 身份与网络安全
@@ -33,4 +33,5 @@ MCP client → TypeScript tool boundary → CRM domain service → NocoBaseClien
- 写模式只增加 `create_project`、`update_project`,不提供 delete/destroy。
- `include_raw` 默认在 MCP 边界拒绝。
- 配置继续接受 camelCase 与 snake_case 字段别名。
- Release Tag、`package.json` 和 `install-manifest.json` 的版本必须一致。
- 默认安装先解析 Gitea `main` 的最新完整 Commit SHA,再在同一快照中读取协议、检查、测试、构建和打包;失败时不回退旧 Release。
- 正式 Release 仍要求 Tag、`package.json` 和 `install-manifest.json` 的版本一致,但 Release 不再是默认安装前提。
+13 -8
View File
@@ -10,14 +10,19 @@
项目不保存共享业务账号,也不需要多人共用的远程 MCP 服务。个人 Authorize Key 仅作为显式备用认证方式。
## Release 发布物
## 最新 Commit 交付
Release workflow 会在带版本 Tag 时执行锁定安装、类型/格式检查、测试、bundle、npm pack 和生产依赖审计,并上传:
默认安装不等待 Release。Agent 在每次安装开始时读取 Gitea `main` 的最新完整 Commit SHA,然后把这次任务固定在该 SHA:
- npm tarball;
- `SHA256SUMS`。
- 从带 SHA 的不可变 URL 重新读取 `INSTALL.md`;
- 下载同一 SHA 的源码归档;
- 在临时目录执行锁定依赖安装、检查、测试、bundle 和 npm pack;
- 将本地生成的运行 tarball 安装到用户级隔离前缀;
- 报告完整 Commit SHA 和本地 tarball SHA-256。
Gitea 仓库访问受限时,外部用户必须具有 Release 下载权限,或通过另一个经过身份认证的分发渠道取得相同资产。受限仓库链接本身不能成为任意用户可访问的一键安装链接。
解析 SHA 后,即使 `main` 在安装期间更新,也不混入新文件;下一次安装才采用更新后的提交。任何检查或构建失败都停止,不回退旧 Release。正式 Release 可以继续用于归档和人工回滚,但不是默认安装来源。
Gitea 仓库访问受限时,用户或 Agent 必须具有源码和 Commit 归档读取权限。受限仓库链接本身不能成为任意用户可访问的一键安装链接,也不得通过聊天传递访问令牌。
## 用户电脑上的内容
@@ -27,7 +32,7 @@ Gitea 仓库访问受限时,外部用户必须具有 Release 下载权限,
- 当前 OS 用户的私有凭证文件;
- MCP 客户端配置和备份。
不需要 Git、Python、uv、`nb CLI` 或项目源码 checkout。npm 只在隔离前缀安装一个已经 bundle 的包,运行时没有额外 npm 依赖。
不需要 Git、Python、uv、`nb CLI` 或持久源码 checkout。npm 在临时目录安装锁定的构建依赖并生成 bundle,随后只在隔离前缀安装本地 tarball;运行时没有额外 npm 依赖。临时源码和构建依赖不属于持久安装内容。
## 权限验收
@@ -43,9 +48,9 @@ Gitea 仓库访问受限时,外部用户必须具有 Release 下载权限,
## 更新与回滚
Agent 下载新的固定 Release tarball并验证 SHA-256,再对同一隔离前缀运行 `npm install --prefix ... --omit=dev <tarball>`。安装前备份 MCP 客户端配置和非秘密 CRM 配置。
更新时,Agent 重新解析 `main` 的最新 Commit,在新临时目录完成全部检查和构建,再对同一隔离前缀运行 `npm install --prefix ... --omit=dev <locally-built-tarball>`。安装前备份 MCP 客户端配置和非秘密 CRM 配置,并记录更新前后的完整 Commit SHA。
回滚时重新安装上一固定 Release 的已验证 tarball。凭证文件与 CRM 配置位于包目录之外,更新和回滚不应复制、覆盖或删除个人 OAuth 凭据。
回滚是唯一允许选择旧提交的安装操作:使用上次记录的完整 Commit SHA 重建并安装该快照,不通过移动分支名猜测版本。凭证文件与 CRM 配置位于包目录之外,更新和回滚不应复制、覆盖或删除个人 OAuth 凭据。
## 常见故障
+1 -1
View File
@@ -1,6 +1,6 @@
# 命令与工具参考
本文面向集成者和维护者。普通用户请从仓库根目录的 [README](../README.md) 开始,安装 Agent 请使用固定 Release Tag 中的 [INSTALL.md](../INSTALL.md)。
本文面向集成者和维护者。普通用户请从仓库根目录的 [README](../README.md) 开始;安装 Agent 应从 `main` 的 [INSTALL.md](../INSTALL.md) 进入,先解析最新完整 Commit SHA,再固定该快照完成安装。
## CLI 命令
+12 -7
View File
@@ -1,20 +1,23 @@
{
"schemaVersion": 2,
"schemaVersion": 3,
"id": "com.nocobase.crm-mcp",
"name": "NocoBase CRM MCP",
"version": "0.4.0",
"distribution": {
"repository": "https://git.justconn.top/admin/nocobase-mcp",
"releaseRef": "must-match-v<version>",
"guide": "INSTALL.md from the exact Release tag",
"assets": ["donaldttt-nocobase-crm-mcp-<version>.tgz", "SHA256SUMS"],
"accessRequirement": "Private Release download requires an authenticated user or Agent with explicit repository access."
"repository": "https://git.justconn.top/gitea-admin/nocobase-mcp",
"branch": "main",
"strategy": "resolve-latest-commit-then-pin",
"releaseRequired": false,
"guide": "INSTALL.md from the resolved full commit SHA",
"sourceArchive": "Gitea source archive for the resolved full commit SHA",
"build": ["npm ci", "npm run check", "npm test", "npm run build", "npm pack"],
"accessRequirement": "Source download requires an authenticated user or Agent with explicit Gitea repository access."
},
"runtime": {
"location": "user-device",
"defaultTransport": "stdio",
"node": ">=20.11",
"packageFormat": "bundled-npm-tarball",
"packageFormat": "commit-pinned locally bundled npm tarball",
"runtimeNpmDependencies": 0,
"nocobaseCli": false,
"python": false
@@ -28,6 +31,8 @@
"installation": {
"requiredTools": ["node", "npm"],
"sourceCheckout": false,
"temporarySourceArchiveBuild": true,
"fallbackToRelease": false,
"globalPackageInstall": false,
"persistentArtifacts": [
"isolated user-data npm prefix",
+25 -1
View File
@@ -6,16 +6,40 @@ import test from "node:test";
import { clientConfig, runCli } from "../src/cli.js";
import { VERSION } from "../src/version.js";
test("package, manifest, and runtime versions agree with no runtime npm dependencies", () => {
test("package, manifest, and runtime versions agree with commit-pinned installation", () => {
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
const manifest = JSON.parse(readFileSync(new URL("../install-manifest.json", import.meta.url), "utf8"));
assert.equal(VERSION, "0.4.0");
assert.equal(packageJson.version, VERSION);
assert.equal(manifest.version, VERSION);
assert.equal(manifest.schemaVersion, 3);
assert.equal(manifest.distribution.branch, "main");
assert.equal(manifest.distribution.strategy, "resolve-latest-commit-then-pin");
assert.equal(manifest.distribution.releaseRequired, false);
assert.equal(manifest.distribution.releaseRef, undefined);
assert.equal(manifest.installation.temporarySourceArchiveBuild, true);
assert.equal(manifest.installation.fallbackToRelease, false);
assert.deepEqual(packageJson.dependencies, undefined);
assert.equal(manifest.runtime.runtimeNpmDependencies, 0);
});
test("installation protocol resolves main once and never falls back to an old Release", () => {
const guide = readFileSync(new URL("../INSTALL.md", import.meta.url), "utf8");
const readme = readFileSync(new URL("../README.md", import.meta.url), "utf8");
const installUrl = "https://git.justconn.top/gitea-admin/nocobase-mcp/raw/branch/main/INSTALL.md";
assert.match(guide, /branches\/main/);
assert.match(guide, /40 位十六进制完整 SHA/);
assert.match(guide, /resolve-latest-commit-then-pin/);
assert.match(guide, /archive\/<commit-sha>\.zip/);
assert.match(guide, /archive\/<commit-sha>\.tar\.gz/);
assert.match(guide, /Windows 使用 `.zip`/);
assert.match(guide, /不得.*退回旧 Release/);
assert.ok(guide.includes(installUrl));
assert.ok(readme.includes(installUrl));
assert.doesNotMatch(guide, /下载本文件所在的同一固定 Release/);
assert.doesNotMatch(readme, /<main 分支的 INSTALL\.md 链接>/);
});
test("generated MCP config contains no Key, token, or environment secret", () => {
const config = clientConfig("/private/config.json", false);
const serialized = JSON.stringify(config);