内容
# mcp-snapshot-filter
MCP 代理,位于 [Claude Code](https://claude.com/claude-code) 和 [`chrome-devtools-mcp`](https://github.com/nichochar/chrome-devtools-mcp) 之间,拦截内容密集的响应并应用智能过滤,以减少 **40-60%** 的令牌使用量。
```
Claude Code <--stdio--> mcp-snapshot-filter <--stdio--> chrome-devtools-mcp
```
## 为什么?
浏览器 MCP 工具(尤其是 `take_snapshot`)返回庞大的可访问性树,这些树会迅速填充上下文窗口。单个数据密集型页面的快照可以是 30-40KB 的文本。此代理在不破坏任何工具交互的情况下透明地过滤掉这些内容。
**实际结果:**
| 页面 | 原始大小 | 过滤后大小 | 减少百分比 |
|---|---|---|---|
| GitHub 仓库页面 | 29.5KB | 22.8KB | 23% |
| 包含 36 行数据表的门户 | 38.5KB | 17.3KB | 55% |
## 设置
```bash
# 克隆并构建
git clone https://github.com/Akarda/mcp-snapshot-filter.git
cd mcp-snapshot-filter
npm install
npm run build
```
添加到 `~/.claude.json`(替换现有的 `chrome-devtools` 条目):
```json
{
"mcpServers": {
"chrome-devtools": {
"type": "stdio",
"command": "node",
"args": [
"/path/to/mcp-snapshot-filter/dist/index.js",
"--filter-level=moderate",
"--",
"npx", "-y", "chrome-devtools-mcp@latest"
]
}
}
}
```
重启 Claude Code 以获取新的配置。
## 过滤级别
| 设置 | 轻度 | 中度(默认) | 激进 |
|---|---|---|---|
| 最大节点数 | 1000 | 500 | 300 |
| 最大深度 | 20 | 15 | 10 |
| 最大相似兄弟节点数 | 5 | 3 | 2 |
| 剥离装饰节点 | 是 | 是 | 是 |
| 折叠导航 | 否 | 是 | 是 |
| 仅关注主要内容 | 否 | 否 | 是 |
| 估计减少百分比 | 20-30% | 40-60% | 60-80% |
使用 `--filter-level=off` 禁用所有过滤并直接传递原始响应。
## 过滤内容
### 快照过滤(影响最大)
- **移除装饰节点** — `role=none/presentation/separator`,空文本节点,无名通用包装器被剥离(子节点提升)
- **折叠相似兄弟节点** — 在 N 个具有相同角色的连续兄弟节点之后(例如,表格中的 50 个 `StaticText` 节点),保留前 N 个并显示 `... [47 more StaticText elements collapsed]`
- **折叠导航** — `navigation/banner/contentinfo/menu` 子树减少为单个摘要: `[navigation: 21 items, 9 links]`
- **主要内容聚焦**(仅激进)— 当存在 `role=main` 时,兄弟子树被总结
- **深度/节点限制** — 超出 maxDepth 时修剪,限制总节点数
### 网络请求过滤
从 `list_network_requests` 输出中剥离 `image`、`font`、`stylesheet`(以及激进模式下的 `media`)条目。所有 `xhr`、`fetch`、`document` 请求保持可见。`get_network_request` **从不被过滤** — 单个请求详细信息始终完全传递。
### 控制台消息过滤
从 `list_console_messages` 中剥离 `debug`、`verbose`(以及较高级别的 `dir`、`trace`)。错误和警告消息始终被保留。
### 评估脚本和内存快照过滤
`evaluate_script` 和 `take_memory_snapshot` 的大型响应被截断:
- **JSON 数组** — 保留前 N 个项目(根据级别为 100/30/10)
- **HTML 转储** — 在最大文本长度处截断
- **纯文本** — 在最大文本长度处截断(根据级别为 100KB/50KB/20KB)
## 未被过滤的内容
- **错误响应** — 始终直接传递
- **图像内容块** — 截图等从不触及
- **未知/新工具** — 只有明确列出的工具被过滤,其他工具直接传递
- **单个请求/消息详细信息** — `get_network_request`、`get_console_message` 未被过滤
- **非交互工具** — `emulate`、`performance_*`、`screencast_*` 等直接传递
## UID 完整性
过滤输出中保留所有可见节点的 UID。在获取过滤快照后,可以在输出中单击、填充或悬停任何显示的 UID — 代理将这些调用不变地转发到上游服务器。
## 会话统计
每个过滤响应都包含一行统计信息:
```
[cdp-filter-proxy: 20.7KB saved (55%) | session: 22.4KB saved across 2 calls (52%)]
```
## 工作原理
代理使用 MCP SDK 的低级 `Server` 类(而非 `McpServer`),以避免在代理工具定义时出现 JSON Schema 到 Zod 的转换问题。启动时,它:
1. 通过 `StdioClientTransport` 将上游的 `chrome-devtools-mcp` 进程作为子进程启动
2. 通过 `listTools()` 发现所有上游工具
3. 通过 `setRequestHandler(ListToolsRequestSchema)` 和 `setRequestHandler(CallToolRequestSchema)` 重新公开它们
4. 对于内容密集型工具的调用,解析响应文本为 markdown 部分(`## Latest page snapshot` 等),对每个部分应用适当的过滤器,并返回过滤结果
## 与 `--slim` 模式的兼容性
chrome-devtools-mcp 支持 `--slim` 标志,该标志将服务器减少到仅 3 个工具(`navigate`、`evaluate`、`screenshot`),以实现最大令牌节省(约 368 个令牌)。如果代理在上游参数中检测到 `--slim`,它将警告过滤无效 — 精简模式响应已经最小化。代理设计用于完整模式,在此模式下,它在减少 40-60% 的响应大小的同时保留所有工具。
## 开发
```bash
npm run build # 将 TypeScript 编译到 dist/
```
重建后,重启 Claude Code 以获取更改(MCP 服务器是长期运行的进程)。