内容
# MCP 缓存代理
MCP(模型上下文协议)工具调用的缓存代理服务器。通过在 SQLite 中缓存只读工具结果,减少 API 配额使用。适用于任何符合 MCP 协议的客户端(Claude Code、Cursor、Copilot 等)。
## 功能
- 透明缓存 MCP 工具调用
- 可配置的 TTL(每秒生存时间)每个服务器
- 基于 SQLite 的缓存,具有 LRU(最近最少使用)大小驱逐
- **缓存失效同时重新验证** — 立即提供缓存数据,在后台刷新
- **WAL 模式** — 多进程访问的并发读取性能
- **成本节省计数器** — 在统计信息中跟踪避免的 API 调用
- **自适应 TTL 调整** — 根据驱逐模式自动调整 TTL(每个服务器可选)
- **代理统计信息** — 跟踪每个服务器的请求指标(总请求、成功、失败、活动请求、失败分类)
- **按需服务器网关** — 延迟加载 MCP 服务器以减少上下文窗口和启动开销
- 支持 stdio 和基于 HTTP 的 MCP 服务器
- **错误缓存**,具有可配置的 TTL
- **每个条目的大小限制**,以防止缓存膨胀
- **缓存导出/导入**,用于备份和转移
- 用于缓存管理的 CLI(`--stats`、`--flush`、`--new`、`--warm`、`--export`、`--import`、`--tune-ttl`)
- 每个工具的缓存统计信息,用于监控和优化
- 项目特定的配置覆盖,具有全局继承
## 安装
### 选项 1:通过 npm 安装(推荐)
```bash
# 全局安装
npm install -g mcp-cache-proxy
# 或直接使用而无需安装(通过 npx)
npx mcp-cache-proxy --stats
```
安装后,`mcp-cache-proxy` 命令可在全局范围内使用:
```bash
mcp-cache-proxy --help
mcp-cache-proxy --stats
```
### 选项 2:从源代码构建
```bash
# 克隆仓库
git clone https://github.com/username/mcp-cache-proxy.git
cd mcp-cache-proxy
# 安装依赖并构建
npm install
npm run build
# 直接运行
node dist/index.js --help
```
### 要求
- Node.js >= 20.0.0
- npm(随 Node.js 捆绑)
## 配置
创建 `~/.mcp-cache-proxy/config.json`:
```json
{
"servers": {
"search-prime": {
"command": "npx",
"args": ["-y", "@zai-mcp/web-search-prime"],
"cacheTtlSeconds": 86400,
"negativeCacheTtlSeconds": 300
},
"web-reader-http": {
"url": "https://api.example.com/mcp/web-reader",
"env": {
"API_KEY": ""
},
"cacheTtlSeconds": 21600,
"negativeCacheTtlSeconds": 600
}
},
"cache": {
"path": "~/.mcp-cache-proxy/cache.db",
"maxSizeBytes": 104857600,
"maxEntrySizeBytes": 10485760,
"defaultTtlSeconds": 43200,
"negativeCacheTtlSeconds": 300
},
"mode": "whitelist"
}
```
**服务器类型:**
- **stdio 服务器:** 使用 `command` 和 `args` 启动子进程
- **HTTP 服务器:** 使用 `url` 进行基于 POST 的 MCP 端点
**环境变量:** 空字符串值(`"API_KEY": ""`)告诉代理使用 `process.env[KEY]` 代替。适用于将机密保留在配置文件之外。
**服务器配置选项:**
- `cacheTtlSeconds`:成功响应的生存时间(默认:43200 = 12 小时)
- `negativeCacheTtlSeconds`:错误响应的生存时间(默认:300 = 5 分钟)
- `adaptiveTtl`:启用基于驱逐模式的自动 TTL 调整(默认:false)
- `cacheTtlRange`:自适应 TTL 调整的最小/最大边界,例如 `{ "min": 3600, "max": 86400 }`
**缓存配置选项:**
- `maxSizeBytes`:超过驱逐前的最大缓存大小(默认:104857600 = 100MB)
- `maxEntrySizeBytes`:单个缓存条目的最大大小(默认:10485760 = 10MB)
- `defaultTtlSeconds`:未显式配置的服务器的默认 TTL(默认:43200)
- `negativeCacheTtlSeconds`:错误的默认负缓存 TTL(默认:300)
- `staleWhileRevalidateSeconds`:TTL 过期后提供缓存数据的宽限期,同时在后台刷新(默认:0 = 禁用)
### 按需服务器(网关模式)
通过延迟加载 MCP 服务器来减少启动开销和上下文窗口使用。配置在 `onDemandServers` 下的服务器在首次使用时不会加载,并在一段时间内不活动后自动卸载。
```json
{
"onDemandServers": {
"n8n-mcp": {
"command": "npx",
"args": ["-y", "n8n-mcp"],
"env": {
"N8N_API_URL": "https://n8n.example.com",
"N8N_API_KEY": ""
},
"idleTimeoutSeconds": 1800
},
"chrome-devtools-mcp": {
"command": "npx",
"args": ["-y", "@executeautomation/chrome-devtools-mcp"],
"idleTimeoutSeconds": 3600
}
}
}
```
**按需服务器选项:**
- `command`:启动服务器进程的命令
- `args`:传递给命令的参数
- `env`:环境变量(空字符串使用 `process.env[KEY]`)
- `idleTimeoutSeconds`:空闲超时秒数,在自动卸载前(默认:1800 = 30 分钟)
**工作原理:**
1. 按需服务器公开一个元工具:`<server_name>_call`(例如,`n8n_mcp_call`)
2. 对元工具的首次调用加载服务器并发现可用工具
3. 随后的调用使用缓存的工具模式并直接路由
4. 服务器在 `idleTimeoutSeconds` 秒内无活动后自动卸载
5. 使用 `gateway_status()` 工具检查哪些服务器当前已加载
**好处:**
- 更小的上下文窗口:仅在需要时加载工具
- 更快的启动:不常用的服务器不会减慢初始连接
- 资源效率:空闲服务器自动断开连接
参见 `config.example.json` 获取所有选项。
### 项目特定配置
在项目目录中创建 `.mcp-cache-proxy.json`:
```json
{
"extendGlobal": true,
"servers": {
"search-prime": {
"cacheTtlSeconds": 3600
}
}
}
```
当 `extendGlobal` 为 `true`(默认)时,项目配置与全局配置合并。设置为 `false` 以使用独立配置。
## 用法
代理作为 MCP 服务器运行,并公开所有上游工具和缓存管理工具。
### 缓存管理工具
代理为任何 MCP 客户端添加了这些工具:
- `cache_stats()` — 获取缓存和代理统计信息,包括每个工具的细分和上游服务器指标
- **缓存指标:** cached, hits, hitRate, misses, sizeBytes, staleHits, savedCalls, byTool
- **代理指标:** totalRequests, successful, failed, successfulByServer, failedByServer, byServer(详细的每个服务器细分,包括 failedByTool, failedByErrorType, activeRequests)
- **网关指标:** 网关状态,显示按需服务器的加载/卸载状态(当配置了 `onDemandServers` 时)
- `cache_flush(tool?)` — 清除缓存条目(全部或特定工具)
- `cache_new()` — 重新创建缓存数据库
- `gateway_status()` — 获取所有按需服务器的状态(加载/卸载,空闲时间,工具数量)— 仅在配置了 `onDemandServers` 时可用
### 客户端配置
在通过 npm 安装后,配置您的 MCP 客户端以使用 `mcp-cache-proxy` 命令:
**Claude Code** (`~/.claude/settings.json`):
```json
{
"mcpServers": {
"cached-tools": {
"command": "mcp-cache-proxy"
}
}
}
```
**Cursor**(设置 → MCP):
```json
{
"mcpServers": {
"cached-tools": {
"command": "mcp-cache-proxy"
}
}
}
```
**Copilot CLI** (`~/.config/github-copilot-cli/mcp.json` 或类似):
```json
{
"mcpServers": {
"cached-tools": {
"command": "mcp-cache-proxy"
}
}
}
```
**从源代码构建?** 使用完整路径:
```json
{
"mcpServers": {
"cached-tools": {
"command": "node",
"args": ["/absolute/path/to/mcp-cache-proxy/dist/index.js"]
}
}
}
```
**通用 MCP 客户端:** 任何符合 MCP 协议的客户端都可以通过 stdio 连接到此代理。参阅客户端文档获取 MCP 服务器配置信息。
### CLI 命令
```bash
# 显示缓存和代理统计信息(包括上游服务器指标)
mcp-cache-proxy --stats
# 清除所有缓存
mcp-cache-proxy --flush
# 清除特定工具的缓存
mcp-cache-proxy --flush search-prime
# 重新创建缓存数据库(处理损坏)
mcp-cache-proxy --new
# 使用预定义查询预热缓存
mcp-cache-proxy --warm --queries queries.txt
# 将缓存导出到 JSON 文件
mcp-cache-proxy --export cache-backup.json
# 从 JSON 文件导入缓存
mcp-cache-proxy --import cache-backup.json
# 显示自适应 TTL 调试状态
mcp-cache-proxy --tune-ttl
# 使用自定义配置路径
mcp-cache-proxy --config /path/to/config.json
# 显示帮助
mcp-cache-proxy --help
```
### 环境变量
使用 `MCP_CACHE_CONFIG` 指定自定义配置路径:
```bash
export MCP_CACHE_CONFIG=/path/to/config.json
node dist/index.js
```
环境变量优先于默认查找,但被 `--config` 标志覆盖。
### 缓存预热
使用预先确定的查询预加载缓存:
```bash
node dist/index.js --warm --queries queries.txt
```
**queries.txt 格式**(每行一个 JSON 查询,`#` 表示注释):
```json
{"tool": "web_search_prime", "args": {"search_query": "typescript best practices"}}
{"tool": "web-reader", "args": {"url": "https://example.com"}}
# 这是一个注释
{"tool": "mcp__mcp-cache-proxy__analyze_image", "args": {"imageSource": "https://example.com/image.jpg", "prompt": "Describe this image"}}
```
参见 `queries.example.txt` 获取完整示例。
### 缓存导出/导入
导出和导入缓存内容以进行备份或在机器之间传输:
```bash
# 将缓存导出到 JSON 文件
mcp-cache-proxy --export cache-backup.json
# 从 JSON 文件导入缓存
mcp-cache-proxy --import cache-backup.json
```
**导出格式:** 具有版本信息、时间戳和条目数组的 JSON 文件。每个条目包括键、工具、参数、结果、时间戳和错误状态。
**导入行为:**
- 跳过已存在的条目(基于键)
- 跳过已过期的条目(TTL 已过)
- 跳过超过 `maxEntrySizeBytes` 的条目
- 调整 TTL 以保留原始过期时间
- 更新每个工具的统计信息
**用例:**
- 在清除或升级前备份缓存
- 在机器之间共享缓存
- 用已知的良好结果预先加载缓存
- 调试和分析
## 缓存策略
- **密钥生成:** 工具名称 + 规范参数(排序键、修剪、大小写不敏感)的 SHA-256 哈希
- **默认 TTL:**
- search-prime:24 小时
- web-reader:6 小时
- zread:1 小时
- 其他:12 小时(defaultTtlSeconds)
- **缓存失效同时重新验证:** 启用时(`staleWhileRevalidateSeconds > 0`),在后台刷新时立即提供缓存数据。用户无需等待缓存刷新。
- **驱逐:** 当超过 `maxSizeBytes` 时使用 LRU(默认:100MB)
- 条目按 `(hits ASC, created_at ASC)` 驱逐 — 最少使用/最旧的优先
- 驱逐目标为最大大小的 90%,以避免频繁重新驱逐
- **模式:** 默认情况下为白名单 — 仅缓存显式配置的工具
- **WAL 模式:** SQLite 使用写入前日志记录进行并发读取性能。`busy_timeout = 5000ms` 优雅地处理锁定争用。
- **自适应 TTL 调整:** 在每个服务器上启用 `adaptiveTtl: true`。后台适配器每 10 分钟分析一次驱逐统计信息 — 在访问之前过期的条目(过早驱逐)表明 TTL 太长。适配器在过早驱逐率高(>60%)时自动降低 TTL,在大多数驱逐的条目被访问时增加 TTL(<20%)。使用 `--tune-ttl` 查看诊断状态。
## 开发
```bash
npm run build # 编译 TypeScript
npm run dev # 构建并运行代理
npm test # 运行测试
npm run lint # ESLint
```
## 更新
```bash
# 更新到最新版本
npm update -g mcp-cache-proxy
# 或重新安装特定版本
npm install -g mcp-cache-proxy@latest
# 检查已安装的版本
mcp-cache-proxy --version # (如果实现)或
npm list -g mcp-cache-proxy
```
## 架构
```
MCP 客户端(Claude Code、Cursor、Copilot 等)
↕ stdio
MCP 缓存代理
↕ stdio/HTTP(每个上游服务器)
真实 MCP 服务器(search-prime、web-reader、zread 等)
↕
SQLite 缓存 (~/.mcp-cache-proxy/cache.db)
网关(可选,当配置了 onDemandServers 时):
元工具(<server>_call)→ 首次使用时延迟加载 → 空闲时自动卸载
```
代理:
1. 从 Claude Code 接受工具调用,基于 stdio
2. 从工具名称 + 参数生成缓存密钥
3. 在 SQLite 中检查缓存结果
4. 丢失时:调用上游服务器,缓存结果并设置 TTL
5. 命中时:返回缓存结果,增加命中计数器
6. 当缓存大小超过 maxSizeBytes 时自动驱逐(LRU)
7. 网关:根据元工具调用加载按需服务器,在空闲超时后卸载
## 贡献
在发布之前,请更新 `package.json` 中的存储库 URL:
- `repository.url`
- `bugs.url`
- `homepage`
用您的实际 GitHub 用户名替换 `username`。
## 许可证
MIT