feat: Enhance deployment capabilities with direct server deployment tools, email configuration, and comprehensive documentation
This commit is contained in:
295
DIRECT_DEPLOY.md
Normal file
295
DIRECT_DEPLOY.md
Normal file
@@ -0,0 +1,295 @@
|
||||
# 直接部署方案(推荐)
|
||||
|
||||
## 概述
|
||||
|
||||
直接在服务器上运行 MCP 服务器(不使用 Docker),这样可以直接使用 MCP 工具进行部署,无需 SSH 连接。
|
||||
|
||||
## 优势
|
||||
|
||||
✅ **无需 SSH** - MCP 工具直接在服务器上运行
|
||||
✅ **更简单** - 不需要配置 Runner、Webhook 等
|
||||
✅ **更直接** - 在 Cursor 中直接触发部署
|
||||
✅ **更灵活** - 可以直接访问服务器文件系统
|
||||
|
||||
## 安装步骤
|
||||
|
||||
### 1. 在服务器上安装 Bun
|
||||
|
||||
```bash
|
||||
# 安装 Bun
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
|
||||
# 验证安装
|
||||
bun --version
|
||||
```
|
||||
|
||||
### 2. 克隆项目
|
||||
|
||||
```bash
|
||||
git clone <your-gitea-repo-url> /opt/cloud-mcp
|
||||
cd /opt/cloud-mcp
|
||||
```
|
||||
|
||||
### 3. 安装依赖
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
### 4. 配置环境变量
|
||||
|
||||
```bash
|
||||
cp env.template .env
|
||||
nano .env # 编辑配置
|
||||
```
|
||||
|
||||
### 5. 运行 MCP 服务器
|
||||
|
||||
#### 方式一:直接运行(测试)
|
||||
|
||||
```bash
|
||||
bun run src/index.ts
|
||||
```
|
||||
|
||||
#### 方式二:使用 PM2(推荐)
|
||||
|
||||
```bash
|
||||
# 安装 PM2
|
||||
bun add -g pm2
|
||||
|
||||
# 启动服务
|
||||
pm2 start "bun run src/index.ts" --name cloud-mcp
|
||||
|
||||
# 设置开机自启
|
||||
pm2 save
|
||||
pm2 startup
|
||||
```
|
||||
|
||||
#### 方式三:使用 systemd(生产环境)
|
||||
|
||||
创建服务文件:
|
||||
|
||||
```bash
|
||||
sudo tee /etc/systemd/system/cloud-mcp.service > /dev/null <<EOF
|
||||
[Unit]
|
||||
Description=Cloud MCP Server
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=root
|
||||
WorkingDirectory=/opt/cloud-mcp
|
||||
Environment="PATH=/usr/local/bin:/usr/bin:/bin"
|
||||
ExecStart=/usr/local/bin/bun run src/index.ts
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
# 启用并启动服务
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable cloud-mcp
|
||||
sudo systemctl start cloud-mcp
|
||||
sudo systemctl status cloud-mcp
|
||||
```
|
||||
|
||||
## 在 Cursor 中配置 MCP
|
||||
|
||||
### 1. 配置 MCP 服务器
|
||||
|
||||
编辑 Cursor 的 MCP 配置(通常在 `~/.cursor/mcp.json` 或类似位置):
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"cloud-mcp": {
|
||||
"command": "ssh",
|
||||
"args": [
|
||||
"user@your-server",
|
||||
"cd /opt/cloud-mcp && bun run src/index.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**或者**,如果 MCP 服务器已经在运行,通过 stdio 连接:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"cloud-mcp": {
|
||||
"command": "ssh",
|
||||
"args": [
|
||||
"user@your-server",
|
||||
"bun run /opt/cloud-mcp/src/index.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 使用部署工具
|
||||
|
||||
配置完成后,在 Cursor 中可以直接使用:
|
||||
|
||||
- `deploy_update` - 拉取最新代码并重新部署
|
||||
- `deploy_status` - 查看部署状态
|
||||
- `deploy_logs` - 查看部署日志
|
||||
|
||||
## 部署流程
|
||||
|
||||
### 自动部署(通过 MCP 工具)
|
||||
|
||||
1. **在 Cursor 中**,直接调用 `deploy_update` 工具
|
||||
2. 工具会自动:
|
||||
- 拉取最新代码
|
||||
- 更新依赖(如果需要)
|
||||
- 重启服务
|
||||
|
||||
### 手动部署
|
||||
|
||||
```bash
|
||||
cd /opt/cloud-mcp
|
||||
git pull origin main
|
||||
bun install # 如果依赖有变化
|
||||
pm2 restart cloud-mcp # 或 systemctl restart cloud-mcp
|
||||
```
|
||||
|
||||
## 部署工具说明
|
||||
|
||||
### deploy_update
|
||||
|
||||
拉取最新代码并重新部署:
|
||||
|
||||
```
|
||||
参数:
|
||||
- branch: Git 分支(默认: main)
|
||||
- rebuild: 是否强制重建(默认: false)
|
||||
```
|
||||
|
||||
### deploy_status
|
||||
|
||||
查看当前部署状态:
|
||||
- Git 状态
|
||||
- 服务运行状态
|
||||
- 是否有未提交的更改
|
||||
|
||||
### deploy_logs
|
||||
|
||||
查看部署日志:
|
||||
- 参数:lines(显示行数,默认 50)
|
||||
|
||||
## 与 Docker 方案对比
|
||||
|
||||
| 特性 | 直接运行 | Docker |
|
||||
|------|---------|--------|
|
||||
| 部署复杂度 | ⭐ 简单 | ⭐⭐ 中等 |
|
||||
| 资源占用 | 较低 | 较高 |
|
||||
| 隔离性 | 较低 | 高 |
|
||||
| MCP 工具访问 | ✅ 直接访问 | ❌ 需要 SSH |
|
||||
| 适合场景 | 个人/小项目 | 生产环境 |
|
||||
|
||||
## 迁移 from Docker
|
||||
|
||||
如果之前使用 Docker,迁移步骤:
|
||||
|
||||
```bash
|
||||
# 1. 停止 Docker 容器
|
||||
docker-compose down
|
||||
|
||||
# 2. 备份数据
|
||||
cp -r data data.backup
|
||||
|
||||
# 3. 安装 Bun(如果还没有)
|
||||
curl -fsSL https://bun.sh/install | bash
|
||||
|
||||
# 4. 安装依赖
|
||||
cd /opt/cloud-mcp
|
||||
bun install
|
||||
|
||||
# 5. 启动服务(选择一种方式)
|
||||
# PM2
|
||||
pm2 start "bun run src/index.ts" --name cloud-mcp
|
||||
|
||||
# 或 systemd
|
||||
sudo systemctl start cloud-mcp
|
||||
```
|
||||
|
||||
## 故障排查
|
||||
|
||||
### MCP 服务器无法启动
|
||||
|
||||
```bash
|
||||
# 检查 Bun 是否安装
|
||||
bun --version
|
||||
|
||||
# 检查依赖
|
||||
bun install
|
||||
|
||||
# 查看错误
|
||||
bun run src/index.ts
|
||||
```
|
||||
|
||||
### 部署工具执行失败
|
||||
|
||||
1. **检查 Git 仓库**:
|
||||
```bash
|
||||
cd /opt/cloud-mcp
|
||||
git status
|
||||
```
|
||||
|
||||
2. **检查权限**:
|
||||
```bash
|
||||
ls -la /opt/cloud-mcp
|
||||
chmod +x deploy-gitea.sh
|
||||
```
|
||||
|
||||
3. **检查服务状态**:
|
||||
```bash
|
||||
# PM2
|
||||
pm2 status
|
||||
|
||||
# systemd
|
||||
sudo systemctl status cloud-mcp
|
||||
```
|
||||
|
||||
### 查看日志
|
||||
|
||||
```bash
|
||||
# PM2 日志
|
||||
pm2 logs cloud-mcp
|
||||
|
||||
# systemd 日志
|
||||
sudo journalctl -u cloud-mcp -f
|
||||
|
||||
# 部署日志
|
||||
tail -f /opt/cloud-mcp/deploy.log
|
||||
```
|
||||
|
||||
## 安全建议
|
||||
|
||||
1. **使用非 root 用户运行**(如果可能):
|
||||
```bash
|
||||
sudo adduser mcpuser
|
||||
sudo chown -R mcpuser:mcpuser /opt/cloud-mcp
|
||||
```
|
||||
|
||||
2. **限制文件权限**:
|
||||
```bash
|
||||
chmod 600 .env
|
||||
```
|
||||
|
||||
3. **定期更新**:
|
||||
```bash
|
||||
bun update
|
||||
```
|
||||
|
||||
## 下一步
|
||||
|
||||
- 配置自动备份
|
||||
- 设置监控告警
|
||||
- 优化性能配置
|
||||
|
||||
163
MCP_CONNECTION.md
Normal file
163
MCP_CONNECTION.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# MCP 服务器连接说明
|
||||
|
||||
## 重要:MCP 服务器不监听端口!
|
||||
|
||||
MCP (Model Context Protocol) 服务器使用 **stdio(标准输入输出)** 传输,**不监听任何网络端口**。
|
||||
|
||||
这意味着:
|
||||
- ❌ 没有 HTTP 端点
|
||||
- ❌ 没有 WebSocket 连接
|
||||
- ❌ 不能通过浏览器访问
|
||||
- ✅ 通过进程间通信(stdin/stdout)与客户端通信
|
||||
|
||||
## 工作原理
|
||||
|
||||
```
|
||||
Cursor/Claude Desktop (客户端)
|
||||
↓ (启动进程)
|
||||
bun run src/index.ts (MCP 服务器)
|
||||
↓ (stdio 通信)
|
||||
工具执行和响应
|
||||
```
|
||||
|
||||
## 在 Cursor 中配置
|
||||
|
||||
### 本地运行(开发)
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"cloud-mcp": {
|
||||
"command": "bun",
|
||||
"args": ["run", "/Users/zijianchen/Desktop/my-project/cloud-mcp/src/index.ts"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 服务器运行(生产)
|
||||
|
||||
如果 MCP 服务器运行在远程服务器上:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"cloud-mcp": {
|
||||
"command": "ssh",
|
||||
"args": [
|
||||
"user@your-server",
|
||||
"cd /opt/cloud-mcp && bun run src/index.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
或者如果服务器上已经通过 PM2/systemd 运行,可以通过 SSH 直接连接:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"cloud-mcp": {
|
||||
"command": "ssh",
|
||||
"args": [
|
||||
"user@your-server",
|
||||
"bun run /opt/cloud-mcp/src/index.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 验证连接
|
||||
|
||||
### 1. 检查进程是否运行
|
||||
|
||||
```bash
|
||||
# 在服务器上
|
||||
ps aux | grep "bun.*index.ts"
|
||||
|
||||
# 或如果使用 PM2
|
||||
pm2 list | grep cloud-mcp
|
||||
|
||||
# 或如果使用 systemd
|
||||
sudo systemctl status cloud-mcp
|
||||
```
|
||||
|
||||
### 2. 测试 MCP 服务器
|
||||
|
||||
```bash
|
||||
# 直接运行测试
|
||||
cd /opt/cloud-mcp
|
||||
bun run src/index.ts
|
||||
|
||||
# 应该看到:
|
||||
# [INFO] Registering tools...
|
||||
# [INFO] All tools registered. Starting MCP server...
|
||||
# [INFO] MCP Server started
|
||||
```
|
||||
|
||||
### 3. 在 Cursor 中测试
|
||||
|
||||
1. 配置 MCP 服务器后
|
||||
2. 重启 Cursor
|
||||
3. 尝试使用任何工具(如 `deploy_status`)
|
||||
4. 如果连接成功,工具会正常执行
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 为什么看不到端口监听?
|
||||
|
||||
**A**: MCP 使用 stdio,不需要端口。这是 MCP 协议的设计。
|
||||
|
||||
### Q: 如何知道服务器是否在运行?
|
||||
|
||||
**A**: 检查进程:
|
||||
```bash
|
||||
ps aux | grep "bun.*index.ts"
|
||||
```
|
||||
|
||||
### Q: 可以添加 HTTP 端点吗?
|
||||
|
||||
**A**: 可以,但需要修改代码使用 SSE 传输。当前实现使用 stdio,这是 MCP 的标准方式。
|
||||
|
||||
### Q: 如何调试连接问题?
|
||||
|
||||
**A**:
|
||||
1. 检查 Cursor 的 MCP 日志
|
||||
2. 在服务器上直接运行 `bun run src/index.ts` 查看错误
|
||||
3. 检查 SSH 连接是否正常(如果使用远程服务器)
|
||||
|
||||
## 添加健康检查端点(可选)
|
||||
|
||||
如果你需要一个 HTTP 端点来检查服务状态,可以添加一个简单的 HTTP 服务器:
|
||||
|
||||
```typescript
|
||||
// 在 src/index.ts 中添加
|
||||
import { serve } from "bun";
|
||||
|
||||
// 健康检查端点(可选)
|
||||
serve({
|
||||
port: 3000,
|
||||
fetch(req) {
|
||||
if (req.url.endsWith("/health")) {
|
||||
return new Response(JSON.stringify({ status: "ok" }), {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
return new Response("Not Found", { status: 404 });
|
||||
},
|
||||
});
|
||||
|
||||
console.log("Health check server running on http://localhost:3000/health");
|
||||
```
|
||||
|
||||
但这只是用于健康检查,**MCP 通信仍然通过 stdio**。
|
||||
|
||||
## 总结
|
||||
|
||||
- MCP 服务器**不监听端口**,使用 stdio 通信
|
||||
- 在 Cursor 中配置时,指定 `command` 和 `args` 来启动进程
|
||||
- 服务器运行时,Cursor 会自动启动进程并通过 stdio 通信
|
||||
- 这是 MCP 协议的标准工作方式
|
||||
|
||||
@@ -67,6 +67,14 @@ ROUTER_HOST=your-router-ip
|
||||
ROUTER_USERNAME=admin
|
||||
ROUTER_PASSWORD=your-password
|
||||
|
||||
# Email Configuration (SMTP)
|
||||
EMAIL_HOST=smtp.gmail.com
|
||||
EMAIL_PORT=587
|
||||
EMAIL_USER=your-email@gmail.com
|
||||
EMAIL_PASSWORD=your-app-password
|
||||
EMAIL_FROM=Your Name
|
||||
EMAIL_SECURE=false
|
||||
|
||||
# API Keys (optional)
|
||||
FOOTBALL_API_KEY=your-football-api-key
|
||||
GAME_API_KEY=your-game-api-key
|
||||
@@ -156,6 +164,7 @@ Example configuration for Claude Desktop (`claude_desktop_config.json`):
|
||||
- `task_add` - Add a task
|
||||
- `task_list` - List tasks
|
||||
- `task_complete` - Complete a task
|
||||
- `email_send` - Send email via SMTP (supports text, HTML, and attachments)
|
||||
|
||||
## Data Storage
|
||||
|
||||
|
||||
53
README_DEPLOY.md
Normal file
53
README_DEPLOY.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# 部署方案对比
|
||||
|
||||
## 方案一:直接运行(推荐 ⭐)
|
||||
|
||||
**优点**:
|
||||
- ✅ 最简单,无需 Docker
|
||||
- ✅ MCP 工具可以直接操作服务器
|
||||
- ✅ 无需 SSH 配置
|
||||
- ✅ 资源占用更少
|
||||
|
||||
**适用场景**:个人项目、小规模部署
|
||||
|
||||
**快速开始**:
|
||||
```bash
|
||||
# 在服务器上
|
||||
git clone <repo> /opt/cloud-mcp
|
||||
cd /opt/cloud-mcp
|
||||
bun install
|
||||
bun run start
|
||||
```
|
||||
|
||||
详细文档:查看 `DIRECT_DEPLOY.md`
|
||||
|
||||
## 方案二:Docker 部署
|
||||
|
||||
**优点**:
|
||||
- ✅ 环境隔离
|
||||
- ✅ 易于管理
|
||||
- ✅ 适合生产环境
|
||||
|
||||
**适用场景**:生产环境、需要隔离的场景
|
||||
|
||||
详细文档:查看 `DEPLOY.md`
|
||||
|
||||
## 推荐方案
|
||||
|
||||
对于你的使用场景(个人 MCP 服务器),**推荐使用方案一(直接运行)**:
|
||||
|
||||
1. 在服务器上直接运行 MCP
|
||||
2. 通过 Cursor 的 MCP 连接直接访问
|
||||
3. 使用 `deploy_update` 工具一键部署更新
|
||||
|
||||
这样就不需要:
|
||||
- ❌ Gitea Actions Runner
|
||||
- ❌ SSH 配置
|
||||
- ❌ Webhook 服务器
|
||||
- ❌ Docker 容器
|
||||
|
||||
只需要:
|
||||
- ✅ 在服务器上运行 MCP
|
||||
- ✅ 在 Cursor 中配置 MCP 连接
|
||||
- ✅ 使用部署工具更新
|
||||
|
||||
166
bun.lock
166
bun.lock
@@ -7,22 +7,166 @@
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.4",
|
||||
"axios": "^1.7.7",
|
||||
"nodemailer": "^6.9.8",
|
||||
"ssh2": "^1.15.0",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.7.9",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/ssh2": "^1.15.4",
|
||||
"typescript": "^5.6.3",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@aws-crypto/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="],
|
||||
|
||||
"@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="],
|
||||
|
||||
"@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="],
|
||||
|
||||
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
||||
|
||||
"@aws-sdk/client-ses": ["@aws-sdk/client-ses@3.964.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.964.0", "@aws-sdk/credential-provider-node": "3.964.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.964.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.964.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "@smithy/util-waiter": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-gAbDlXvNP5Sb2tS4tJYmOS6/frmba2tryJ4MzJVeR1ad8sSa94GQx7XbR7HyCi5VtJpOSk7Uibp3aKzK3+sWsg=="],
|
||||
|
||||
"@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.964.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.964.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.964.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.964.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-IenVyY8Io2CwBgmS22xk/H5LibmSbvLnPA9oFqLORO6Ji1Ks8z/ow+ud/ZurVjFekz3LD/uxVFX3ZKGo6N7Byw=="],
|
||||
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.964.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@aws-sdk/xml-builder": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/signature-v4": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-1gIfbt0KRxI8am1UYFcIxQ5QKb22JyN3k52sxyrKXJYC8Knn/rTUAZbYti45CfETe5PLadInGvWqClwGRlZKNg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jWNSXOOBMYuxzI2rXi8x91YL07dhomyGzzh0CdaLej0LRmknmDrZcZNkVpa7Fredy1PFcmOlokwCS5PmZMN8ZQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-up7dl6vcaoXuYSwGXDvx8RnF8Lwj3jGChhyUR7krZOXLarIfUUN3ILOZnVNK5s/HnVNkEILlkdPvjhr9LVC1/Q=="],
|
||||
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/credential-provider-env": "3.964.0", "@aws-sdk/credential-provider-http": "3.964.0", "@aws-sdk/credential-provider-login": "3.964.0", "@aws-sdk/credential-provider-process": "3.964.0", "@aws-sdk/credential-provider-sso": "3.964.0", "@aws-sdk/credential-provider-web-identity": "3.964.0", "@aws-sdk/nested-clients": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-t4FN9qTWU4nXDU6EQ6jopvyhXw0dbQ3n+3g6x5hmc1ECFAqA+xmFd1i5LljdZCi79cUXHduQWwvW8RJHMf0qJw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/nested-clients": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-c64dmTizMkJXDRzN3NYPTmUpKxegr5lmLOYPeQ60Zcbft6HFwPme8Gwy8pNxO4gG1fw6Ja2Vu6fZuSTn8aDFOQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.964.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.964.0", "@aws-sdk/credential-provider-http": "3.964.0", "@aws-sdk/credential-provider-ini": "3.964.0", "@aws-sdk/credential-provider-process": "3.964.0", "@aws-sdk/credential-provider-sso": "3.964.0", "@aws-sdk/credential-provider-web-identity": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-FHxDXPOj888/qc/X8s0x4aUBdp4Y3k9VePRehUJBWRhhTsAyuIJis5V0iQeY1qvtqHXYa2qd1EZHGJ3bTjHxSw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-HaTLKqj3jeZY88E/iBjsNJsXgmRTTT7TghqeRiF8FKb/7UY1xEvasBO0c1xqfOye8dsyt35nTfTTyIsd/CBfww=="],
|
||||
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.964.0", "", { "dependencies": { "@aws-sdk/client-sso": "3.964.0", "@aws-sdk/core": "3.964.0", "@aws-sdk/token-providers": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-oR78TjSpjVf1IpPWQnGHEGqlnQs+K4f5nCxLK2P6JDPprXay6oknsoSiU4x2urav6VCyMPMC9KTCGjBoFKUIxQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/nested-clients": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-07JQDmbjZjOt3nL/j1wTcvQqjmPkynQYftUV/ooZ+qTbmJXFbCBdal1VCElyeiu0AgBq9dfhw0rBBcbND1ZMlA=="],
|
||||
|
||||
"@aws-sdk/middleware-host-header": ["@aws-sdk/middleware-host-header@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-BBgKawVyfQZglEkNTuBBdC3azlyqNXsvvN4jPkWAiNYcY0x1BasaJFl+7u/HisfULstryweJq/dAvIZIxzlZaA=="],
|
||||
|
||||
"@aws-sdk/middleware-logger": ["@aws-sdk/middleware-logger@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-w1qfKrSKHf9b5a8O76yQ1t69u6NWuBjr5kBX+jRWFx/5mu6RLpqERXRpVJxfosbep7k3B+DSB5tZMZ82GKcJtQ=="],
|
||||
|
||||
"@aws-sdk/middleware-recursion-detection": ["@aws-sdk/middleware-recursion-detection@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-D2H/WoxhAZNYX+IjkKTdOhOkWQaK0jjJrDBj56hKjU5c9ltQiaX/1PqJ4dfjHntEshJfu0w+E6XJ+/6A6ILBBA=="],
|
||||
|
||||
"@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@smithy/core": "^3.20.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-/QyBl8WLNtqw3ucyAggumQXVCi8GRxaDGE1ElyYMmacfiwHl37S9y8JVW/QLL1lIEXGcsrhMUKV3pyFJFALA7w=="],
|
||||
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.964.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.964.0", "@aws-sdk/middleware-host-header": "3.957.0", "@aws-sdk/middleware-logger": "3.957.0", "@aws-sdk/middleware-recursion-detection": "3.957.0", "@aws-sdk/middleware-user-agent": "3.964.0", "@aws-sdk/region-config-resolver": "3.957.0", "@aws-sdk/types": "3.957.0", "@aws-sdk/util-endpoints": "3.957.0", "@aws-sdk/util-user-agent-browser": "3.957.0", "@aws-sdk/util-user-agent-node": "3.964.0", "@smithy/config-resolver": "^4.4.5", "@smithy/core": "^3.20.0", "@smithy/fetch-http-handler": "^5.3.8", "@smithy/hash-node": "^4.2.7", "@smithy/invalid-dependency": "^4.2.7", "@smithy/middleware-content-length": "^4.2.7", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-retry": "^4.4.17", "@smithy/middleware-serde": "^4.2.8", "@smithy/middleware-stack": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/node-http-handler": "^4.4.7", "@smithy/protocol-http": "^5.3.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.16", "@smithy/util-defaults-mode-node": "^4.2.19", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ql+ftRwjyZkZeG3qbrRJFVmNR0id83WEUqhFVjvrQMWspNApBhz0Ar4YVSn7Uv0QaKkaR7ALPtmdMzFr3/E4bQ=="],
|
||||
|
||||
"@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/config-resolver": "^4.4.5", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-V8iY3blh8l2iaOqXWW88HbkY5jDoWjH56jonprG/cpyqqCnprvpMUZWPWYJoI8rHRf2bqzZeql1slxG6EnKI7A=="],
|
||||
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.964.0", "", { "dependencies": { "@aws-sdk/core": "3.964.0", "@aws-sdk/nested-clients": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-UqouLQbYepZnMFJGB/DVpA5GhF9uT98vNWSMz9PVbhgEPUKa73FECRT6YFZvZOh8kA+0JiENrnmS6d93I70ykQ=="],
|
||||
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.957.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-wzWC2Nrt859ABk6UCAVY/WYEbAd7FjkdrQL6m24+tfmWYDNRByTJ9uOgU/kw9zqLCAwb//CPvrJdhqjTznWXAg=="],
|
||||
|
||||
"@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-endpoints": "^3.2.7", "tslib": "^2.6.2" } }, "sha512-xwF9K24mZSxcxKS3UKQFeX/dPYkEps9wF1b+MGON7EvnbcucrJGyQyK1v1xFPn1aqXkBTFi+SZaMRx5E5YCVFw=="],
|
||||
|
||||
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.957.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-nhmgKHnNV9K+i9daumaIz8JTLsIIML9PE/HUks5liyrjUzenjW/aHoc7WJ9/Td/gPZtayxFnXQSJRb/fDlBuJw=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.957.0", "", { "dependencies": { "@aws-sdk/types": "3.957.0", "@smithy/types": "^4.11.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-exueuwxef0lUJRnGaVkNSC674eAiWU07ORhxBnevFFZEKisln+09Qrtw823iyv5I1N8T+wKfh95xvtWQrNKNQw=="],
|
||||
|
||||
"@aws-sdk/util-user-agent-node": ["@aws-sdk/util-user-agent-node@3.964.0", "", { "dependencies": { "@aws-sdk/middleware-user-agent": "3.964.0", "@aws-sdk/types": "3.957.0", "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" }, "peerDependencies": { "aws-crt": ">=1.0.0" }, "optionalPeers": ["aws-crt"] }, "sha512-jgob8Z/bZIh1dwEgLqE12q+aCf0ieLy7anT8bWpqMijMJqsnrPBToa7smSykfom9YHrdOgrQhXswMpE75dzLRw=="],
|
||||
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.957.0", "", { "dependencies": { "@smithy/types": "^4.11.0", "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" } }, "sha512-Ai5iiQqS8kJ5PjzMhWcLKN0G2yasAkvpnPlq2EnqlIMdB48HsizElt62qcktdxp4neRMyGkFq4NzgmDbXnhRiA=="],
|
||||
|
||||
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.2.2", "", {}, "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg=="],
|
||||
|
||||
"@hono/node-server": ["@hono/node-server@1.19.7", "", { "peerDependencies": { "hono": "^4" } }, "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw=="],
|
||||
|
||||
"@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.25.1", "", { "dependencies": { "@hono/node-server": "^1.19.7", "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.0.1", "express-rate-limit": "^7.5.0", "jose": "^6.1.1", "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.0" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ=="],
|
||||
|
||||
"@smithy/abort-controller": ["@smithy/abort-controller@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-rzMY6CaKx2qxrbYbqjXWS0plqEy7LOdKHS0bg4ixJ6aoGDPNUcLWk/FRNuCILh7GKLG9TFUXYYeQQldMBBwuyw=="],
|
||||
|
||||
"@smithy/config-resolver": ["@smithy/config-resolver@4.4.5", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-endpoints": "^3.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-HAGoUAFYsUkoSckuKbCPayECeMim8pOu+yLy1zOxt1sifzEbrsRpYa+mKcMdiHKMeiqOibyPG0sFJnmaV/OGEg=="],
|
||||
|
||||
"@smithy/core": ["@smithy/core@3.20.0", "", { "dependencies": { "@smithy/middleware-serde": "^4.2.8", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-stream": "^4.5.8", "@smithy/util-utf8": "^4.2.0", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-WsSHCPq/neD5G/MkK4csLI5Y5Pkd9c1NMfpYEKeghSGaD4Ja1qLIohRQf2D5c1Uy5aXp76DeKHkzWZ9KAlHroQ=="],
|
||||
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-CmduWdCiILCRNbQWFR0OcZlUPVtyE49Sr8yYL0rZQ4D/wKxiNzBNS/YHemvnbkIWj623fplgkexUd/c9CAKdoA=="],
|
||||
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.3.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/querystring-builder": "^4.2.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "tslib": "^2.6.2" } }, "sha512-h/Fi+o7mti4n8wx1SR6UHWLaakwHRx29sizvp8OOm7iqwKGFneT06GCSFhml6Bha5BT6ot5pj3CYZnCHhGC2Rg=="],
|
||||
|
||||
"@smithy/hash-node": ["@smithy/hash-node@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-PU/JWLTBCV1c8FtB8tEFnY4eV1tSfBc7bDBADHfn1K+uRbPgSJ9jnJp0hyjiFN2PMdPzxsf1Fdu0eo9fJ760Xw=="],
|
||||
|
||||
"@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-ncvgCr9a15nPlkhIUx3CU4d7E7WEuVJOV7fS7nnK2hLtPK9tYRBkMHQbhXU1VvvKeBm/O0x26OEoBq+ngFpOEQ=="],
|
||||
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ=="],
|
||||
|
||||
"@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.2.7", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-GszfBfCcvt7kIbJ41LuNa5f0wvQCHhnGx/aDaZJCCT05Ld6x6U2s0xsc/0mBFONBZjQJp2U/0uSJ178OXOwbhg=="],
|
||||
|
||||
"@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.4.1", "", { "dependencies": { "@smithy/core": "^3.20.0", "@smithy/middleware-serde": "^4.2.8", "@smithy/node-config-provider": "^4.3.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "@smithy/url-parser": "^4.2.7", "@smithy/util-middleware": "^4.2.7", "tslib": "^2.6.2" } }, "sha512-gpLspUAoe6f1M6H0u4cVuFzxZBrsGZmjx2O9SigurTx4PbntYa4AJ+o0G0oGm1L2oSX6oBhcGHwrfJHup2JnJg=="],
|
||||
|
||||
"@smithy/middleware-retry": ["@smithy/middleware-retry@4.4.17", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/protocol-http": "^5.3.7", "@smithy/service-error-classification": "^4.2.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-retry": "^4.2.7", "@smithy/uuid": "^1.1.0", "tslib": "^2.6.2" } }, "sha512-MqbXK6Y9uq17h+4r0ogu/sBT6V/rdV+5NvYL7ZV444BKfQygYe8wAhDrVXagVebN6w2RE0Fm245l69mOsPGZzg=="],
|
||||
|
||||
"@smithy/middleware-serde": ["@smithy/middleware-serde@4.2.8", "", { "dependencies": { "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-8rDGYen5m5+NV9eHv9ry0sqm2gI6W7mc1VSFMtn6Igo25S507/HaOX9LTHAS2/J32VXD0xSzrY0H5FJtOMS4/w=="],
|
||||
|
||||
"@smithy/middleware-stack": ["@smithy/middleware-stack@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-bsOT0rJ+HHlZd9crHoS37mt8qRRN/h9jRve1SXUhVbkRzu0QaNYZp1i1jha4n098tsvROjcwfLlfvcFuJSXEsw=="],
|
||||
|
||||
"@smithy/node-config-provider": ["@smithy/node-config-provider@4.3.7", "", { "dependencies": { "@smithy/property-provider": "^4.2.7", "@smithy/shared-ini-file-loader": "^4.4.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-7r58wq8sdOcrwWe+klL9y3bc4GW1gnlfnFOuL7CXa7UzfhzhxKuzNdtqgzmTV+53lEp9NXh5hY/S4UgjLOzPfw=="],
|
||||
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.4.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/querystring-builder": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-NELpdmBOO6EpZtWgQiHjoShs1kmweaiNuETUpuup+cmm/xJYjT4eUjfhrXRP4jCOaAsS3c3yPsP3B+K+/fyPCQ=="],
|
||||
|
||||
"@smithy/property-provider": ["@smithy/property-provider@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-jmNYKe9MGGPoSl/D7JDDs1C8b3dC8f/w78LbaVfoTtWy4xAd5dfjaFG9c9PWPihY4ggMQNQSMtzU77CNgAJwmA=="],
|
||||
|
||||
"@smithy/protocol-http": ["@smithy/protocol-http@5.3.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-1r07pb994I20dD/c2seaZhoCuNYm0rWrvBxhCQ70brNh11M5Ml2ew6qJVo0lclB3jMIXirD4s2XRXRe7QEi0xA=="],
|
||||
|
||||
"@smithy/querystring-builder": ["@smithy/querystring-builder@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "@smithy/util-uri-escape": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-eKONSywHZxK4tBxe2lXEysh8wbBdvDWiA+RIuaxZSgCMmA0zMgoDpGLJhnyj+c0leOQprVnXOmcB4m+W9Rw7sg=="],
|
||||
|
||||
"@smithy/querystring-parser": ["@smithy/querystring-parser@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-3X5ZvzUHmlSTHAXFlswrS6EGt8fMSIxX/c3Rm1Pni3+wYWB6cjGocmRIoqcQF9nU5OgGmL0u7l9m44tSUpfj9w=="],
|
||||
|
||||
"@smithy/service-error-classification": ["@smithy/service-error-classification@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0" } }, "sha512-YB7oCbukqEb2Dlh3340/8g8vNGbs/QsNNRms+gv3N2AtZz9/1vSBx6/6tpwQpZMEJFs7Uq8h4mmOn48ZZ72MkA=="],
|
||||
|
||||
"@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.4.2", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-M7iUUff/KwfNunmrgtqBfvZSzh3bmFgv/j/t1Y1dQ+8dNo34br1cqVEqy6v0mYEgi0DkGO7Xig0AnuOaEGVlcg=="],
|
||||
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.3.7", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-middleware": "^4.2.7", "@smithy/util-uri-escape": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-9oNUlqBlFZFOSdxgImA6X5GFuzE7V2H7VG/7E70cdLhidFbdtvxxt81EHgykGK5vq5D3FafH//X+Oy31j3CKOg=="],
|
||||
|
||||
"@smithy/smithy-client": ["@smithy/smithy-client@4.10.2", "", { "dependencies": { "@smithy/core": "^3.20.0", "@smithy/middleware-endpoint": "^4.4.1", "@smithy/middleware-stack": "^4.2.7", "@smithy/protocol-http": "^5.3.7", "@smithy/types": "^4.11.0", "@smithy/util-stream": "^4.5.8", "tslib": "^2.6.2" } }, "sha512-D5z79xQWpgrGpAHb054Fn2CCTQZpog7JELbVQ6XAvXs5MNKWf28U9gzSBlJkOyMl9LA1TZEjRtwvGXfP0Sl90g=="],
|
||||
|
||||
"@smithy/types": ["@smithy/types@4.11.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-mlrmL0DRDVe3mNrjTcVcZEgkFmufITfUAPBEA+AHYiIeYyJebso/He1qLbP3PssRe22KUzLRpQSdBPbXdgZ2VA=="],
|
||||
|
||||
"@smithy/url-parser": ["@smithy/url-parser@4.2.7", "", { "dependencies": { "@smithy/querystring-parser": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-/RLtVsRV4uY3qPWhBDsjwahAtt3x2IsMGnP5W1b2VZIe+qgCqkLxI1UOHDZp1Q1QSOrdOR32MF3Ph2JfWT1VHg=="],
|
||||
|
||||
"@smithy/util-base64": ["@smithy/util-base64@4.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ=="],
|
||||
|
||||
"@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg=="],
|
||||
|
||||
"@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.2.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA=="],
|
||||
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew=="],
|
||||
|
||||
"@smithy/util-config-provider": ["@smithy/util-config-provider@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q=="],
|
||||
|
||||
"@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.3.16", "", { "dependencies": { "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-/eiSP3mzY3TsvUOYMeL4EqUX6fgUOj2eUOU4rMMgVbq67TiRLyxT7Xsjxq0bW3OwuzK009qOwF0L2OgJqperAQ=="],
|
||||
|
||||
"@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.2.19", "", { "dependencies": { "@smithy/config-resolver": "^4.4.5", "@smithy/credential-provider-imds": "^4.2.7", "@smithy/node-config-provider": "^4.3.7", "@smithy/property-provider": "^4.2.7", "@smithy/smithy-client": "^4.10.2", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-3a4+4mhf6VycEJyHIQLypRbiwG6aJvbQAeRAVXydMmfweEPnLLabRbdyo/Pjw8Rew9vjsh5WCdhmDaHkQnhhhA=="],
|
||||
|
||||
"@smithy/util-endpoints": ["@smithy/util-endpoints@3.2.7", "", { "dependencies": { "@smithy/node-config-provider": "^4.3.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-s4ILhyAvVqhMDYREeTS68R43B1V5aenV5q/V1QpRQJkCXib5BPRo4s7uNdzGtIKxaPHCfU/8YkvPAEvTpxgspg=="],
|
||||
|
||||
"@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw=="],
|
||||
|
||||
"@smithy/util-middleware": ["@smithy/util-middleware@4.2.7", "", { "dependencies": { "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-i1IkpbOae6NvIKsEeLLM9/2q4X+M90KV3oCFgWQI4q0Qz+yUZvsr+gZPdAEAtFhWQhAHpTsJO8DRJPuwVyln+w=="],
|
||||
|
||||
"@smithy/util-retry": ["@smithy/util-retry@4.2.7", "", { "dependencies": { "@smithy/service-error-classification": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-SvDdsQyF5CIASa4EYVT02LukPHVzAgUA4kMAuZ97QJc2BpAqZfA4PINB8/KOoCXEw9tsuv/jQjMeaHFvxdLNGg=="],
|
||||
|
||||
"@smithy/util-stream": ["@smithy/util-stream@4.5.8", "", { "dependencies": { "@smithy/fetch-http-handler": "^5.3.8", "@smithy/node-http-handler": "^4.4.7", "@smithy/types": "^4.11.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-buffer-from": "^4.2.0", "@smithy/util-hex-encoding": "^4.2.0", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-ZnnBhTapjM0YPGUSmOs0Mcg/Gg87k503qG4zU2v/+Js2Gu+daKOJMeqcQns8ajepY8tgzzfYxl6kQyZKml6O2w=="],
|
||||
|
||||
"@smithy/util-uri-escape": ["@smithy/util-uri-escape@4.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA=="],
|
||||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="],
|
||||
|
||||
"@smithy/util-waiter": ["@smithy/util-waiter@4.2.7", "", { "dependencies": { "@smithy/abort-controller": "^4.2.7", "@smithy/types": "^4.11.0", "tslib": "^2.6.2" } }, "sha512-vHJFXi9b7kUEpHWUCY3Twl+9NPOZvQ0SAi+Ewtn48mbiJk4JY9MZmKQjGB4SCvVb9WPiSphZJYY6RIbs+grrzw=="],
|
||||
|
||||
"@smithy/uuid": ["@smithy/uuid@1.1.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw=="],
|
||||
|
||||
"@types/node": ["@types/node@22.19.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-1N9SBnWYOJTrNZCdh/yJE+t910Y128BoyY+zBLWhL3r0TYzlTmFdXrPwHL9DyFZmlEXNQQolTZh3KHV31QDhyA=="],
|
||||
|
||||
"@types/nodemailer": ["@types/nodemailer@6.4.21", "", { "dependencies": { "@aws-sdk/client-ses": "^3.731.1", "@types/node": "*" } }, "sha512-Eix+sb/Nj28MNnWvO2X1OLrk5vuD4C9SMnb2Vf4itWnxphYeSceqkFX7IdmxTzn+dvmnNz7paMbg4Uc60wSfJg=="],
|
||||
|
||||
"@types/ssh2": ["@types/ssh2@1.15.5", "", { "dependencies": { "@types/node": "^18.11.18" } }, "sha512-N1ASjp/nXH3ovBHddRJpli4ozpk6UdDYIX4RJWFa9L1YKnzdhTlVmiGHm4DZnj/jLbqZpes4aeR30EFGQtvhQQ=="],
|
||||
|
||||
"accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
|
||||
@@ -41,6 +185,8 @@
|
||||
|
||||
"body-parser": ["body-parser@2.2.1", "", { "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.0", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw=="],
|
||||
|
||||
"bowser": ["bowser@2.13.1", "", {}, "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw=="],
|
||||
|
||||
"buildcheck": ["buildcheck@0.0.7", "", {}, "sha512-lHblz4ahamxpTmnsk+MNTRWsjYKv965MwOrSJyeD588rR3Jcu7swE+0wN5F+PbL5cjgu/9ObkhfzEPuofEMwLA=="],
|
||||
|
||||
"bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
|
||||
@@ -101,6 +247,8 @@
|
||||
|
||||
"fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
|
||||
|
||||
"fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="],
|
||||
|
||||
"finalhandler": ["finalhandler@2.1.1", "", { "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" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
|
||||
|
||||
"follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
|
||||
@@ -161,6 +309,8 @@
|
||||
|
||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"nodemailer": ["nodemailer@6.10.1", "", {}, "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA=="],
|
||||
|
||||
"object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
|
||||
|
||||
"object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
|
||||
@@ -215,8 +365,12 @@
|
||||
|
||||
"statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
|
||||
|
||||
"strnum": ["strnum@2.1.2", "", {}, "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ=="],
|
||||
|
||||
"toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"tweetnacl": ["tweetnacl@0.14.5", "", {}, "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="],
|
||||
|
||||
"type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
|
||||
@@ -237,12 +391,24 @@
|
||||
|
||||
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@types/ssh2/@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="],
|
||||
|
||||
"form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@types/ssh2/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
|
||||
"form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
}
|
||||
}
|
||||
|
||||
26
ecosystem.config.js
Normal file
26
ecosystem.config.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// PM2 ecosystem file for cloud-mcp
|
||||
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: "cloud-mcp",
|
||||
script: "bun",
|
||||
args: "run src/index.ts",
|
||||
cwd: "/opt/cloud-mcp",
|
||||
instances: 1,
|
||||
exec_mode: "fork",
|
||||
watch: false,
|
||||
max_memory_restart: "500M",
|
||||
env: {
|
||||
NODE_ENV: "production",
|
||||
},
|
||||
error_file: "./logs/cloud-mcp-error.log",
|
||||
out_file: "./logs/cloud-mcp-out.log",
|
||||
log_date_format: "YYYY-MM-DD HH:mm:ss Z",
|
||||
merge_logs: true,
|
||||
autorestart: true,
|
||||
max_restarts: 10,
|
||||
min_uptime: "10s",
|
||||
},
|
||||
],
|
||||
};
|
||||
@@ -18,6 +18,15 @@ ROUTER_HOST=192.168.1.1
|
||||
ROUTER_USERNAME=admin
|
||||
ROUTER_PASSWORD=your-router-password
|
||||
|
||||
# Email Configuration
|
||||
# 邮件配置(SMTP)
|
||||
EMAIL_HOST=smtp.gmail.com
|
||||
EMAIL_PORT=587
|
||||
EMAIL_USER=your-email@gmail.com
|
||||
EMAIL_PASSWORD=your-app-password
|
||||
EMAIL_FROM=Your Name
|
||||
EMAIL_SECURE=false
|
||||
|
||||
# API Keys (optional)
|
||||
# 可选:配置 API 密钥以使用完整功能
|
||||
# 足球信息 API (football-data.org - 免费注册获取)
|
||||
|
||||
@@ -7,7 +7,10 @@
|
||||
"scripts": {
|
||||
"dev": "bun run src/index.ts",
|
||||
"build": "bun build src/index.ts --outdir dist --target bun",
|
||||
"start": "bun run dist/index.js",
|
||||
"start": "bun run src/index.ts",
|
||||
"start:pm2": "pm2 start ecosystem.config.js",
|
||||
"stop:pm2": "pm2 stop cloud-mcp",
|
||||
"restart:pm2": "pm2 restart cloud-mcp",
|
||||
"test": "bun test",
|
||||
"test:watch": "bun test --watch",
|
||||
"test:coverage": "bun test --coverage"
|
||||
@@ -22,10 +25,12 @@
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.0.4",
|
||||
"axios": "^1.7.7",
|
||||
"nodemailer": "^6.9.8",
|
||||
"ssh2": "^1.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.7.9",
|
||||
"@types/nodemailer": "^6.4.14",
|
||||
"@types/ssh2": "^1.15.4",
|
||||
"typescript": "^5.6.3"
|
||||
},
|
||||
|
||||
@@ -15,6 +15,7 @@ import { registerCodeReviewTools } from "./tools/programming/codeReview.js";
|
||||
import { registerNASTools } from "./tools/devops/nas.js";
|
||||
import { registerServerTools } from "./tools/devops/server.js";
|
||||
import { registerRouterTools } from "./tools/devops/router.js";
|
||||
import { registerDeployTools } from "./tools/devops/deploy.js";
|
||||
|
||||
import { registerMathTools } from "./tools/family/math.js";
|
||||
import { registerBabyTools } from "./tools/family/baby.js";
|
||||
@@ -24,6 +25,7 @@ import { registerGameTools } from "./tools/hobbies/games.js";
|
||||
|
||||
import { registerNoteTools } from "./tools/common/notes.js";
|
||||
import { registerTaskTools } from "./tools/common/tasks.js";
|
||||
import { registerEmailTools } from "./tools/common/email.js";
|
||||
|
||||
// Register all tool modules
|
||||
logger.info("Registering tools...");
|
||||
@@ -38,6 +40,7 @@ registerCodeReviewTools();
|
||||
registerNASTools();
|
||||
registerServerTools();
|
||||
registerRouterTools();
|
||||
registerDeployTools();
|
||||
|
||||
// Family tools
|
||||
registerMathTools();
|
||||
@@ -50,6 +53,7 @@ registerGameTools();
|
||||
// Common tools
|
||||
registerNoteTools();
|
||||
registerTaskTools();
|
||||
registerEmailTools();
|
||||
|
||||
logger.info("All tools registered. Starting MCP server...");
|
||||
|
||||
|
||||
@@ -23,10 +23,20 @@ export interface RouterConfig {
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export interface EmailConfig {
|
||||
host?: string;
|
||||
port?: number;
|
||||
user?: string;
|
||||
password?: string;
|
||||
from?: string;
|
||||
secure?: boolean;
|
||||
}
|
||||
|
||||
export interface AppConfig {
|
||||
nas: NASConfig;
|
||||
server: ServerConfig;
|
||||
router: RouterConfig;
|
||||
email: EmailConfig;
|
||||
footballApiKey?: string;
|
||||
gameApiKey?: string;
|
||||
}
|
||||
@@ -57,6 +67,14 @@ class ConfigManager {
|
||||
username: process.env.ROUTER_USERNAME,
|
||||
password: process.env.ROUTER_PASSWORD,
|
||||
},
|
||||
email: {
|
||||
host: process.env.EMAIL_HOST,
|
||||
port: process.env.EMAIL_PORT ? parseInt(process.env.EMAIL_PORT) : 587,
|
||||
user: process.env.EMAIL_USER,
|
||||
password: process.env.EMAIL_PASSWORD,
|
||||
from: process.env.EMAIL_FROM,
|
||||
secure: process.env.EMAIL_SECURE === 'true',
|
||||
},
|
||||
footballApiKey: process.env.FOOTBALL_API_KEY,
|
||||
gameApiKey: process.env.GAME_API_KEY,
|
||||
};
|
||||
@@ -78,6 +96,10 @@ class ConfigManager {
|
||||
return this.config.router;
|
||||
}
|
||||
|
||||
getEmailConfig(): EmailConfig {
|
||||
return this.config.email;
|
||||
}
|
||||
|
||||
reload(): void {
|
||||
this.config = this.loadConfig();
|
||||
}
|
||||
|
||||
206
src/tools/common/email.ts
Normal file
206
src/tools/common/email.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
/**
|
||||
* Email sending tools
|
||||
*/
|
||||
|
||||
import { mcpServer } from "../../server.js";
|
||||
import { configManager } from "../../storage/config.js";
|
||||
import { logger } from "../../utils/logger.js";
|
||||
import nodemailer from "nodemailer";
|
||||
import { readFileSync, existsSync } from "fs";
|
||||
|
||||
export function registerEmailTools(): void {
|
||||
// Send email
|
||||
mcpServer.registerTool(
|
||||
{
|
||||
name: "email_send",
|
||||
description:
|
||||
"Send an email via SMTP with support for text, HTML, and attachments",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
to: {
|
||||
type: "string",
|
||||
description: "Recipient email address (required)",
|
||||
},
|
||||
subject: {
|
||||
type: "string",
|
||||
description: "Email subject (required)",
|
||||
},
|
||||
text: {
|
||||
type: "string",
|
||||
description: "Plain text email body (required)",
|
||||
},
|
||||
html: {
|
||||
type: "string",
|
||||
description: "HTML email body (optional, if not provided, text will be used)",
|
||||
},
|
||||
cc: {
|
||||
type: "string",
|
||||
description: "CC recipient email address (optional)",
|
||||
},
|
||||
bcc: {
|
||||
type: "string",
|
||||
description: "BCC recipient email address (optional)",
|
||||
},
|
||||
attachments: {
|
||||
type: "array",
|
||||
description: "Email attachments (optional)",
|
||||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
filename: {
|
||||
type: "string",
|
||||
description: "Attachment filename",
|
||||
},
|
||||
path: {
|
||||
type: "string",
|
||||
description: "Path to file (if using file path)",
|
||||
},
|
||||
content: {
|
||||
type: "string",
|
||||
description: "File content as string (if using content directly)",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ["to", "subject", "text"],
|
||||
},
|
||||
},
|
||||
async (args) => {
|
||||
const emailConfig = configManager.getEmailConfig();
|
||||
|
||||
if (!emailConfig.host || !emailConfig.user || !emailConfig.password) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "Error: Email configuration not found. Please set EMAIL_HOST, EMAIL_USER, and EMAIL_PASSWORD in environment variables.",
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const to = args.to as string;
|
||||
const subject = args.subject as string;
|
||||
const text = args.text as string;
|
||||
const html = args.html as string | undefined;
|
||||
const cc = args.cc as string | undefined;
|
||||
const bcc = args.bcc as string | undefined;
|
||||
const attachments = args.attachments as
|
||||
| Array<{ filename: string; path?: string; content?: string }>
|
||||
| undefined;
|
||||
|
||||
// Create transporter
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: emailConfig.host,
|
||||
port: emailConfig.port || 587,
|
||||
secure: emailConfig.secure || false,
|
||||
auth: {
|
||||
user: emailConfig.user,
|
||||
pass: emailConfig.password,
|
||||
},
|
||||
});
|
||||
|
||||
// Process attachments
|
||||
const processedAttachments: any[] = [];
|
||||
if (attachments && attachments.length > 0) {
|
||||
for (const attachment of attachments) {
|
||||
if (attachment.path) {
|
||||
// Use file path
|
||||
if (existsSync(attachment.path)) {
|
||||
processedAttachments.push({
|
||||
filename: attachment.filename,
|
||||
path: attachment.path,
|
||||
});
|
||||
} else {
|
||||
logger.warn(`Attachment file not found: ${attachment.path}`);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error: Attachment file not found: ${attachment.path}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
} else if (attachment.content) {
|
||||
// Use content directly
|
||||
processedAttachments.push({
|
||||
filename: attachment.filename,
|
||||
content: attachment.content,
|
||||
});
|
||||
} else {
|
||||
logger.warn(
|
||||
`Invalid attachment: missing path or content for ${attachment.filename}`
|
||||
);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error: Invalid attachment: missing path or content for ${attachment.filename}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare email options
|
||||
const mailOptions: any = {
|
||||
from: emailConfig.from || emailConfig.user,
|
||||
to: to,
|
||||
subject: subject,
|
||||
text: text,
|
||||
};
|
||||
|
||||
if (html) {
|
||||
mailOptions.html = html;
|
||||
}
|
||||
|
||||
if (cc) {
|
||||
mailOptions.cc = cc;
|
||||
}
|
||||
|
||||
if (bcc) {
|
||||
mailOptions.bcc = bcc;
|
||||
}
|
||||
|
||||
if (processedAttachments.length > 0) {
|
||||
mailOptions.attachments = processedAttachments;
|
||||
}
|
||||
|
||||
// Send email
|
||||
logger.info(`Sending email to ${to} with subject: ${subject}`);
|
||||
const info = await transporter.sendMail(mailOptions);
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Email sent successfully!\n\nTo: ${to}\nSubject: ${subject}\nMessage ID: ${info.messageId}${processedAttachments.length > 0 ? `\nAttachments: ${processedAttachments.length}` : ""}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Error sending email:", error);
|
||||
const errorMessage =
|
||||
error instanceof Error ? error.message : String(error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error sending email: ${errorMessage}\n\nPlease check:\n1. Email configuration (EMAIL_HOST, EMAIL_USER, EMAIL_PASSWORD)\n2. SMTP server connection\n3. Recipient email address`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
384
src/tools/devops/deploy.ts
Normal file
384
src/tools/devops/deploy.ts
Normal file
@@ -0,0 +1,384 @@
|
||||
/**
|
||||
* Deployment tools - for direct server deployment
|
||||
* These tools run directly on the server, no SSH needed
|
||||
*/
|
||||
|
||||
import { mcpServer } from "../../server.js";
|
||||
import { logger } from "../../utils/logger.js";
|
||||
import { execSync } from "child_process";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
export function registerDeployTools(): void {
|
||||
// Pull latest code and deploy
|
||||
mcpServer.registerTool(
|
||||
{
|
||||
name: "deploy_update",
|
||||
description:
|
||||
"Pull latest code from git and redeploy the MCP server (runs directly on server)",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
branch: {
|
||||
type: "string",
|
||||
description: "Git branch to pull from (default: main or master)",
|
||||
default: "main",
|
||||
},
|
||||
rebuild: {
|
||||
type: "boolean",
|
||||
description: "Force rebuild Docker image (default: false)",
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async (args) => {
|
||||
try {
|
||||
const branch = (args.branch as string) || "main";
|
||||
const rebuild = (args.rebuild as boolean) || false;
|
||||
const projectDir = process.cwd();
|
||||
|
||||
logger.info(`Starting deployment update in ${projectDir}`);
|
||||
|
||||
let output = "Deployment Update\n\n";
|
||||
const steps: string[] = [];
|
||||
|
||||
// Step 1: Check if we're in a git repository
|
||||
if (!existsSync(join(projectDir, ".git"))) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "Error: Not in a git repository. Please run this from the project directory.",
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Step 2: Fetch latest changes
|
||||
try {
|
||||
steps.push("Fetching latest changes from git...");
|
||||
const fetchOutput = execSync("git fetch origin", {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
});
|
||||
output += `✓ Fetched changes\n`;
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error fetching from git: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Step 3: Check current branch
|
||||
const currentBranch = execSync("git rev-parse --abbrev-ref HEAD", {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
// Step 4: Pull latest code
|
||||
try {
|
||||
steps.push(`Pulling latest code from ${branch}...`);
|
||||
const pullOutput = execSync(`git pull origin ${branch}`, {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
});
|
||||
output += `✓ Pulled latest code from ${branch}\n`;
|
||||
output += `\n${pullOutput}\n`;
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error pulling code: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
|
||||
// Step 5: Install dependencies if package.json changed
|
||||
try {
|
||||
steps.push("Checking for dependency updates...");
|
||||
const hasPackageChanges = execSync(
|
||||
"git diff HEAD@{1} HEAD -- package.json bun.lockb",
|
||||
{ cwd: projectDir, encoding: "utf-8" }
|
||||
).trim();
|
||||
|
||||
if (hasPackageChanges) {
|
||||
steps.push("Installing/updating dependencies...");
|
||||
execSync("bun install", {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
stdio: "inherit",
|
||||
});
|
||||
output += `✓ Dependencies updated\n`;
|
||||
} else {
|
||||
output += `✓ No dependency changes\n`;
|
||||
}
|
||||
} catch (error) {
|
||||
// Not critical, continue
|
||||
logger.warn("Could not check dependencies:", error);
|
||||
}
|
||||
|
||||
// Step 6: Restart service (if using systemd or PM2)
|
||||
try {
|
||||
steps.push("Restarting MCP server...");
|
||||
|
||||
// Check if running as systemd service
|
||||
const serviceName = process.env.MCP_SERVICE_NAME || "cloud-mcp";
|
||||
try {
|
||||
execSync(`systemctl is-active --quiet ${serviceName}`, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
// Service exists and is active, restart it
|
||||
execSync(`sudo systemctl restart ${serviceName}`, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
output += `✓ Restarted systemd service: ${serviceName}\n`;
|
||||
} catch {
|
||||
// Not a systemd service, try PM2
|
||||
try {
|
||||
execSync("pm2 list | grep cloud-mcp", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
execSync("pm2 restart cloud-mcp", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
output += `✓ Restarted PM2 process: cloud-mcp\n`;
|
||||
} catch {
|
||||
// Not PM2 either, just log that manual restart is needed
|
||||
output += `⚠ Service restart skipped (not running as systemd/PM2)\n`;
|
||||
output += ` Please restart the MCP server manually\n`;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.warn("Could not restart service:", error);
|
||||
output += `⚠ Could not auto-restart service\n`;
|
||||
}
|
||||
|
||||
output += `\n✅ Deployment update completed!\n`;
|
||||
output += `\nSteps executed:\n${steps
|
||||
.map((s, i) => `${i + 1}. ${s}`)
|
||||
.join("\n")}`;
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: output,
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Deployment error:", error);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error during deployment: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Check deployment status
|
||||
mcpServer.registerTool(
|
||||
{
|
||||
name: "deploy_status",
|
||||
description:
|
||||
"Check deployment status - git status, last commit, service status",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
},
|
||||
},
|
||||
async () => {
|
||||
try {
|
||||
const projectDir = process.cwd();
|
||||
let output = "Deployment Status\n\n";
|
||||
|
||||
// Git status
|
||||
try {
|
||||
const gitStatus = execSync("git status --short", {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
const lastCommit = execSync("git log -1 --oneline", {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
const currentBranch = execSync("git rev-parse --abbrev-ref HEAD", {
|
||||
cwd: projectDir,
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
output += `📦 Git Status:\n`;
|
||||
output += `Branch: ${currentBranch}\n`;
|
||||
output += `Last commit: ${lastCommit}\n`;
|
||||
|
||||
// Check if behind remote
|
||||
try {
|
||||
execSync("git fetch origin", { cwd: projectDir });
|
||||
const behind = execSync(
|
||||
`git rev-list HEAD..origin/${currentBranch} --count`,
|
||||
{ cwd: projectDir, encoding: "utf-8" }
|
||||
).trim();
|
||||
|
||||
if (behind !== "0") {
|
||||
output += `⚠ Behind remote by ${behind} commit(s)\n`;
|
||||
} else {
|
||||
output += `✓ Up to date with remote\n`;
|
||||
}
|
||||
} catch {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
if (gitStatus) {
|
||||
output += `\nUncommitted changes:\n${gitStatus}\n`;
|
||||
} else {
|
||||
output += `✓ Working directory clean\n`;
|
||||
}
|
||||
} catch (error) {
|
||||
output += `Error checking git status: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}\n`;
|
||||
}
|
||||
|
||||
// Service status
|
||||
output += `\n🔧 Service Status:\n`;
|
||||
const serviceName = process.env.MCP_SERVICE_NAME || "cloud-mcp";
|
||||
|
||||
try {
|
||||
const systemdStatus = execSync(`systemctl is-active ${serviceName}`, {
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
output += `Systemd: ${systemdStatus}\n`;
|
||||
} catch {
|
||||
try {
|
||||
const pm2Status = execSync("pm2 list | grep cloud-mcp", {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
output += `PM2: Running\n`;
|
||||
} catch {
|
||||
output += `Service: Not managed by systemd/PM2\n`;
|
||||
}
|
||||
}
|
||||
|
||||
// Process status
|
||||
try {
|
||||
const processInfo = execSync(
|
||||
"ps aux | grep 'bun.*index.ts' | grep -v grep",
|
||||
{
|
||||
encoding: "utf-8",
|
||||
}
|
||||
).trim();
|
||||
if (processInfo) {
|
||||
output += `\nProcess: Running\n`;
|
||||
} else {
|
||||
output += `\nProcess: Not found\n`;
|
||||
}
|
||||
} catch {
|
||||
output += `\nProcess: Unknown\n`;
|
||||
}
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: output,
|
||||
},
|
||||
],
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error checking status: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// View deployment logs
|
||||
mcpServer.registerTool(
|
||||
{
|
||||
name: "deploy_logs",
|
||||
description: "View deployment logs",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
lines: {
|
||||
type: "number",
|
||||
description: "Number of lines to show (default: 50)",
|
||||
default: 50,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
async (args) => {
|
||||
try {
|
||||
const lines = (args.lines as number) || 50;
|
||||
const logFile = join(process.cwd(), "deploy.log");
|
||||
|
||||
if (existsSync(logFile)) {
|
||||
const content = readFileSync(logFile, "utf-8");
|
||||
const logLines = content.split("\n").slice(-lines).join("\n");
|
||||
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Deployment Logs (last ${lines} lines):\n\n${logLines}`,
|
||||
},
|
||||
],
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "No deployment log file found. Logs will be created on first deployment.",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Error reading logs: ${
|
||||
error instanceof Error ? error.message : String(error)
|
||||
}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -440,7 +440,7 @@ serve({
|
||||
module: "ESNext",
|
||||
lib: ["ES2022"],
|
||||
moduleResolution: "bundler",
|
||||
types: ["bun-types"],
|
||||
types: ["node"],
|
||||
strict: true,
|
||||
esModuleInterop: true,
|
||||
skipLibCheck: true,
|
||||
|
||||
14
tests/tsconfig.json
Normal file
14
tests/tsconfig.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node"],
|
||||
"noEmit": true,
|
||||
"skipLibCheck": true,
|
||||
"typeRoots": ["../types", "../node_modules/@types"],
|
||||
"moduleResolution": "bundler",
|
||||
"rootDir": ".."
|
||||
},
|
||||
"include": ["**/*.ts"],
|
||||
"exclude": []
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
/*
|
||||
* @Date: 2026-01-07 09:09:22
|
||||
* @LastEditors: 陈子健
|
||||
* @LastEditTime: 2026-01-07 10:04:55
|
||||
* @FilePath: /cloud-mcp/tests/unit/storage/config.test.ts
|
||||
*/
|
||||
/**
|
||||
* Configuration management tests
|
||||
*/
|
||||
|
||||
// @ts-ignore - Bun test types are built-in
|
||||
import { describe, test, expect, beforeEach, afterEach } from "bun:test";
|
||||
import { configManager } from "../../../src/storage/config.js";
|
||||
import { setTestEnv } from "../../helpers/test-utils.js";
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"module": "ESNext",
|
||||
"lib": ["ES2022"],
|
||||
"moduleResolution": "bundler",
|
||||
"types": ["bun-types", "node"],
|
||||
"types": ["node"],
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
@@ -19,7 +19,6 @@
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
"include": ["src/**/*", "types/**/*"],
|
||||
"exclude": ["node_modules", "dist", "tests"]
|
||||
}
|
||||
|
||||
|
||||
9
tsconfig.test.json
Normal file
9
tsconfig.test.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["node", "bun-types"],
|
||||
"noEmit": true
|
||||
},
|
||||
"include": ["tests/**/*", "src/**/*"]
|
||||
}
|
||||
|
||||
59
types/bun-test.d.ts
vendored
Normal file
59
types/bun-test.d.ts
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* @Date: 2026-01-07 15:24:14
|
||||
* @LastEditors: 陈子健
|
||||
* @LastEditTime: 2026-01-07 15:26:23
|
||||
* @FilePath: /cloud-mcp/types/bun-test.d.ts
|
||||
*/
|
||||
/**
|
||||
* Type declarations for Bun test framework
|
||||
* This file provides type definitions for Bun's built-in test framework
|
||||
* Place this file in a types directory and include it in tsconfig.json
|
||||
*/
|
||||
|
||||
declare module "bun:test" {
|
||||
export function describe(name: string, fn: () => void | Promise<void>): void;
|
||||
export function test(
|
||||
name: string,
|
||||
fn: () => void | Promise<void>,
|
||||
timeout?: number
|
||||
): void;
|
||||
export function it(
|
||||
name: string,
|
||||
fn: () => void | Promise<void>,
|
||||
timeout?: number
|
||||
): void;
|
||||
export function expect(actual: any): {
|
||||
toBe(expected: any): void;
|
||||
toBeDefined(): void;
|
||||
toBeUndefined(): void;
|
||||
toBeNull(): void;
|
||||
toBeTruthy(): void;
|
||||
toBeFalsy(): void;
|
||||
toEqual(expected: any): void;
|
||||
toContain(expected: any): void;
|
||||
toMatch(pattern: string | RegExp): void;
|
||||
toThrow(error?: string | RegExp | Error): void;
|
||||
toBeGreaterThan(expected: number): void;
|
||||
toBeLessThan(expected: number): void;
|
||||
toBeGreaterThanOrEqual(expected: number): void;
|
||||
toBeLessThanOrEqual(expected: number): void;
|
||||
toBeCloseTo(expected: number, precision?: number): void;
|
||||
toBeInstanceOf(expected: any): void;
|
||||
not: {
|
||||
toBe(expected: any): void;
|
||||
toBeDefined(): void;
|
||||
toBeUndefined(): void;
|
||||
toBeNull(): void;
|
||||
toBeTruthy(): void;
|
||||
toBeFalsy(): void;
|
||||
toEqual(expected: any): void;
|
||||
toContain(expected: any): void;
|
||||
toMatch(pattern: string | RegExp): void;
|
||||
toThrow(error?: string | RegExp | Error): void;
|
||||
};
|
||||
};
|
||||
export function beforeEach(fn: () => void | Promise<void>): void;
|
||||
export function afterEach(fn: () => void | Promise<void>): void;
|
||||
export function beforeAll(fn: () => void | Promise<void>): void;
|
||||
export function afterAll(fn: () => void | Promise<void>): void;
|
||||
}
|
||||
Reference in New Issue
Block a user