413 lines
9.3 KiB
Markdown
413 lines
9.3 KiB
Markdown
# mcp-proxy npm 包依赖更新机制分析
|
||
|
||
## 问题
|
||
**用户关注**: mcp-proxy 打包到 npm 时,内部依赖的平台二进制文件是否是最新的(下载的)?
|
||
|
||
## 快速回答
|
||
❌ **当前机制**: cargo-dist 生成的 npm 包中的二进制文件**不是**从 npm registry 下载的最新版本,而是**构建时打包进去的**。
|
||
|
||
✅ **这实际上是正确的行为**: 这确保了版本一致性和可靠性。
|
||
|
||
---
|
||
|
||
## cargo-dist npm 安装器工作机制
|
||
|
||
### 1. 构建阶段(GitHub Actions)
|
||
|
||
```yaml
|
||
# .github/workflows/release.yml
|
||
targets = [
|
||
"aarch64-apple-darwin",
|
||
"aarch64-unknown-linux-gnu",
|
||
"x86_64-apple-darwin",
|
||
"x86_64-unknown-linux-gnu",
|
||
"x86_64-pc-windows-msvc"
|
||
]
|
||
```
|
||
|
||
**流程**:
|
||
```
|
||
Tag 推送 (v0.1.39)
|
||
↓
|
||
GitHub Actions 触发
|
||
↓
|
||
为每个平台构建二进制文件
|
||
├─ Linux x86_64: mcp-proxy (ELF)
|
||
├─ Linux ARM64: mcp-proxy (ELF)
|
||
├─ macOS x86_64: mcp-proxy (Mach-O)
|
||
├─ macOS ARM64: mcp-proxy (Mach-O)
|
||
└─ Windows: mcp-proxy.exe (PE)
|
||
↓
|
||
cargo-dist 打包成 tarball
|
||
├─ mcp-stdio-proxy-aarch64-apple-darwin.tar.xz
|
||
├─ mcp-stdio-proxy-x86_64-unknown-linux-gnu.tar.xz
|
||
└─ mcp-stdio-proxy-x86_64-pc-windows-msvc.zip
|
||
↓
|
||
生成 npm 安装器包
|
||
└─ mcp-stdio-proxy-0.1.39-npm-package.tar.gz
|
||
```
|
||
|
||
### 2. npm 包结构
|
||
|
||
cargo-dist 生成的 npm 包包含:
|
||
|
||
```
|
||
mcp-stdio-proxy-0.1.39-npm-package.tar.gz
|
||
└── package/
|
||
├── package.json
|
||
│ ├── "version": "0.1.39"
|
||
│ ├── "name": "mcp-stdio-proxy"
|
||
│ ├── "bin": { "mcp-proxy": "./install.js" }
|
||
│ └── "artifactDownloadUrl": "https://github.com/.../v0.1.39"
|
||
├── install.js # 安装脚本
|
||
└── (可能的其他元数据)
|
||
```
|
||
|
||
**package.json 关键字段**:
|
||
```json
|
||
{
|
||
"name": "mcp-stdio-proxy",
|
||
"version": "0.1.39",
|
||
"bin": {
|
||
"mcp-proxy": "./install.js"
|
||
},
|
||
"artifactDownloadUrl": "https://github.com/nuwax-ai/mcp-proxy/releases/download/v0.1.39"
|
||
}
|
||
```
|
||
|
||
### 3. 用户安装流程
|
||
|
||
```bash
|
||
npm install -g mcp-stdio-proxy@0.1.39
|
||
```
|
||
|
||
**实际发生的事情**:
|
||
|
||
1. **下载 npm 包**:
|
||
```
|
||
npm registry → mcp-stdio-proxy-0.1.39-npm-package.tar.gz
|
||
```
|
||
|
||
2. **运行 install.js**:
|
||
```javascript
|
||
// install.js (由 cargo-dist 生成)
|
||
const version = "0.1.39";
|
||
const platform = detectPlatform(); // e.g., "x86_64-pc-windows-msvc"
|
||
const artifactUrl = `${baseUrl}/mcp-stdio-proxy-${platform}.tar.xz`;
|
||
|
||
// 下载平台特定的二进制包
|
||
download(artifactUrl);
|
||
extract(artifact);
|
||
symlinkBinary("mcp-proxy");
|
||
```
|
||
|
||
3. **下载的二进制文件来源**:
|
||
```
|
||
https://github.com/nuwax-ai/mcp-proxy/releases/download/v0.1.39/mcp-stdio-proxy-x86_64-pc-windows-msvc.zip
|
||
```
|
||
或者(如果 OSS 同步成功):
|
||
```
|
||
https://nuwa-packages.oss-rg-china-mainland.aliyuncs.com/mcp-stdio-proxy/v0.1.39/mcp-stdio-proxy-x86_64-pc-windows-msvc.zip
|
||
```
|
||
|
||
---
|
||
|
||
## 关键点:版本锁定机制
|
||
|
||
### ✅ 版本是锁定的(这是正确的)
|
||
|
||
| 组件 | 版本来源 | 更新时机 |
|
||
|------|---------|---------|
|
||
| **npm 包版本** | Cargo.toml `version = "0.1.39"` | 手动更新 + Git Tag |
|
||
| **二进制文件** | 该版本构建时编译的二进制 | 构建时生成 |
|
||
| **依赖的 crate** | Cargo.lock 锁定 | 更新 Cargo.lock |
|
||
| **下载 URL** | package.json `artifactDownloadUrl` | 自动生成(包含版本号) |
|
||
|
||
**示例**:
|
||
```
|
||
用户安装: npm install -g mcp-stdio-proxy@0.1.39
|
||
↓
|
||
下载 npm 包(包含版本信息)
|
||
↓
|
||
install.js 读取 artifactDownloadUrl
|
||
↓
|
||
下载: https://.../v0.1.39/mcp-stdio-proxy-x86_64-pc-windows-msvc.zip
|
||
↓
|
||
解压得到的二进制文件就是 v0.1.39 构建时的版本
|
||
```
|
||
|
||
---
|
||
|
||
## 依赖更新策略
|
||
|
||
### 场景 A: Rust 依赖更新(如 rmcp, tokio 等)
|
||
|
||
**问题**: 如果 `rmcp` 发布了新版本,用户安装 `mcp-stdio-proxy@0.1.39` 会用到新版本吗?
|
||
|
||
**答案**: ❌ 不会,因为二进制文件已经编译好了
|
||
|
||
**更新方法**:
|
||
```bash
|
||
# 1. 在项目中更新依赖
|
||
cd mcp-proxy
|
||
cargo update -p rmcp
|
||
|
||
# 2. 测试
|
||
cargo test
|
||
|
||
# 3. 更新版本号
|
||
# 编辑 mcp-proxy/Cargo.toml
|
||
version = "0.1.40"
|
||
|
||
# 4. 提交并打标签
|
||
git commit -am "chore: bump version to 0.1.40 with updated rmcp"
|
||
git tag v0.1.40
|
||
git push origin v0.1.40
|
||
|
||
# 5. GitHub Actions 自动构建并发布
|
||
# 新的 npm 包 mcp-stdio-proxy@0.1.40 将包含更新后的 rmcp
|
||
```
|
||
|
||
### 场景 B: 系统依赖(如 OpenSSL、glibc)
|
||
|
||
**问题**: 构建的二进制依赖的系统库版本是什么?
|
||
|
||
**答案**: 取决于 GitHub Actions runner 的环境
|
||
|
||
**当前配置** (`.github/workflows/release.yml`):
|
||
```yaml
|
||
matrix:
|
||
runner: "ubuntu-22.04" # Ubuntu 22.04 的 glibc 版本
|
||
```
|
||
|
||
**潜在问题**:
|
||
- 如果在 Ubuntu 22.04 上构建,二进制可能依赖较新的 glibc
|
||
- 在旧系统(如 CentOS 7)上可能无法运行
|
||
|
||
**解决方案**:
|
||
```yaml
|
||
# 使用容器构建以控制依赖版本
|
||
matrix:
|
||
container:
|
||
image: "quay.io/pypa/manylinux2014_x86_64" # 兼容性更好
|
||
```
|
||
|
||
---
|
||
|
||
## 当前流程的优缺点
|
||
|
||
### ✅ 优点
|
||
|
||
1. **版本一致性**:
|
||
- `mcp-stdio-proxy@0.1.39` 永远下载的是 v0.1.39 构建时的二进制
|
||
- 不会因为依赖更新导致意外行为
|
||
|
||
2. **确定性构建**:
|
||
- Cargo.lock 锁定所有依赖版本
|
||
- 可复现的构建结果
|
||
|
||
3. **无运行时编译**:
|
||
- 用户安装时不需要 Rust 工具链
|
||
- 安装速度快(直接下载预编译二进制)
|
||
|
||
4. **平台特定优化**:
|
||
- 为每个平台单独编译优化
|
||
- 无跨平台兼容性损失
|
||
|
||
### ❌ 潜在问题
|
||
|
||
1. **依赖无法自动更新**:
|
||
- 用户不能通过 `npm update` 获取新的 Rust 依赖
|
||
- 必须发布新版本
|
||
|
||
2. **二进制体积大**:
|
||
- 每个平台的二进制都需要打包
|
||
- npm 包本身较小(只是安装器),但下载的二进制较大
|
||
|
||
3. **系统兼容性**:
|
||
- 需要确保目标系统有合适的运行时库
|
||
- 可能在旧系统上无法运行
|
||
|
||
---
|
||
|
||
## 对比其他方案
|
||
|
||
### 方案 A: 当前方案(cargo-dist)
|
||
|
||
```
|
||
npm install -g mcp-stdio-proxy
|
||
↓
|
||
下载安装器 npm 包(~1KB)
|
||
↓
|
||
install.js 下载平台二进制(~10MB)
|
||
↓
|
||
解压到 ~/.npm/bin/
|
||
```
|
||
|
||
**特点**: 预编译二进制,版本锁定
|
||
|
||
---
|
||
|
||
### 方案 B: 纯 npm 包(不适用)
|
||
|
||
```
|
||
npm install -g mcp-stdio-proxy
|
||
↓
|
||
下载 JavaScript 代码
|
||
↓
|
||
运行时执行
|
||
```
|
||
|
||
**特点**: 不适用,因为 mcp-proxy 是 Rust 项目
|
||
|
||
---
|
||
|
||
### 方案 C: npm 包 + 源码编译(不推荐)
|
||
|
||
```
|
||
npm install -g mcp-stdio-proxy
|
||
↓
|
||
下载源码 + package.json
|
||
↓
|
||
postinstall: cargo build --release
|
||
↓
|
||
编译二进制
|
||
```
|
||
|
||
**特点**:
|
||
- ❌ 需要用户有 Rust 工具链
|
||
- ❌ 安装时间长(编译需要几分钟)
|
||
- ✅ 可以获取最新依赖
|
||
- ✅ 针对用户系统优化
|
||
|
||
---
|
||
|
||
## 建议
|
||
|
||
### ✅ 保持当前方案
|
||
|
||
**理由**:
|
||
1. cargo-dist 是 Rust 社区标准方案
|
||
2. 版本锁定是**优点**而非缺点(确保稳定性)
|
||
3. 用户体验好(无需 Rust 工具链,安装快)
|
||
|
||
### 🔧 优化建议
|
||
|
||
#### 1. 明确依赖更新流程
|
||
|
||
创建文档说明如何更新依赖并发布新版本:
|
||
|
||
```markdown
|
||
# 依赖更新指南
|
||
|
||
## 更新 Rust 依赖
|
||
1. `cargo update -p <crate_name>`
|
||
2. `cargo test` 确保无破坏性更改
|
||
3. 更新 `Cargo.toml` 版本号
|
||
4. `git tag v<new_version>` 触发发布
|
||
|
||
## 发布检查清单
|
||
- [ ] 所有测试通过
|
||
- [ ] CHANGELOG.md 已更新
|
||
- [ ] 版本号已同步(Cargo.toml)
|
||
- [ ] Git tag 格式正确(v0.1.40)
|
||
```
|
||
|
||
#### 2. 添加版本信息到二进制
|
||
|
||
```rust
|
||
// mcp-proxy/src/main.rs
|
||
#[derive(Parser)]
|
||
#[command(version = env!("CARGO_PKG_VERSION"))]
|
||
struct Cli {
|
||
// ...
|
||
}
|
||
|
||
// 运行时显示依赖版本
|
||
fn print_version_info() {
|
||
println!("mcp-proxy {}", env!("CARGO_PKG_VERSION"));
|
||
println!(" rmcp: {}", env!("CARGO_PKG_VERSION_rmcp"));
|
||
println!(" tokio: {}", env!("CARGO_PKG_VERSION_tokio"));
|
||
}
|
||
```
|
||
|
||
#### 3. 自动化依赖检查
|
||
|
||
```yaml
|
||
# .github/workflows/dependency-check.yml
|
||
name: Dependency Check
|
||
on:
|
||
schedule:
|
||
- cron: '0 0 * * 1' # 每周一检查
|
||
workflow_dispatch:
|
||
|
||
jobs:
|
||
check-outdated:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- run: cargo outdated --exit-code 1
|
||
```
|
||
|
||
#### 4. 添加系统兼容性说明
|
||
|
||
在 README.md 中明确说明:
|
||
|
||
```markdown
|
||
## 系统要求
|
||
|
||
### Linux
|
||
- glibc >= 2.31 (Ubuntu 20.04+, Debian 11+, RHEL 8+)
|
||
- 或使用 musl 构建版本(待支持)
|
||
|
||
### macOS
|
||
- macOS 10.15+ (Catalina or later)
|
||
|
||
### Windows
|
||
- Windows 10 / Windows Server 2019 或更高版本
|
||
- 需要 Visual C++ Redistributable 2015-2022
|
||
```
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
### 问题回答
|
||
|
||
**Q: mcp-proxy 打包的内部平台依赖是否是最新的(下载的)?**
|
||
|
||
**A**:
|
||
- ❌ **不是"下载的最新"**: 二进制文件在构建时编译,版本锁定
|
||
- ✅ **这是正确的行为**: 确保版本一致性和可靠性
|
||
- 🔄 **更新方式**: 通过发布新版本(如 v0.1.40)获取更新的依赖
|
||
|
||
### 版本管理流程
|
||
|
||
```
|
||
Rust 依赖更新
|
||
↓
|
||
cargo update
|
||
↓
|
||
测试验证
|
||
↓
|
||
版本号递增 (0.1.39 → 0.1.40)
|
||
↓
|
||
Git Tag (v0.1.40)
|
||
↓
|
||
GitHub Actions 构建
|
||
↓
|
||
发布到 npm (mcp-stdio-proxy@0.1.40)
|
||
↓
|
||
用户 npm install -g mcp-stdio-proxy@latest
|
||
↓
|
||
获取包含最新依赖的二进制
|
||
```
|
||
|
||
### 最佳实践
|
||
|
||
1. ✅ **保持当前 cargo-dist 方案**
|
||
2. ✅ **定期检查和更新依赖**
|
||
3. ✅ **清晰的版本发布流程**
|
||
4. ✅ **文档化系统要求**
|
||
5. ✅ **自动化依赖检查(GitHub Actions)**
|