Skip to main content
Glama
HCLEMINI
by HCLEMINI
README.md
# zotero-claude-bridge

让 [Claude Code](https://claude.com/claude-code) 通过 MCP 控制 Zotero 浏览器连接器,把网页里的论文自动抓取到本地 Zotero 库。

```
Claude Code CLI
   │  MCP 工具调用(stdio)
   ▼
zotero-claude-bridge(本仓库,Python MCP server,内嵌 WebSocket server)
   │  WebSocket  ws://127.0.0.1:24731/bridge
   ▼
改造后的 Zotero Connector(claude-bridge.js,service worker 长连接)
   │  复用原有 translator + itemSaver
   ▼
本地 Zotero 桌面客户端(POST http://127.0.0.1:23119/connector/saveItems)
```

本仓库**只是桥**。它必须和改造后的 Zotero Connector 扩展(fork 仓库 `zotero-connectors-claude-code`)配合使用。

## 它解决什么

- 原生 Zotero Connector 只能"手动逐篇点图标保存",无法被程序驱动。
- `zotero-mcp` 只能操作 Zotero 库内的增删改查,**不能从网页提取元数据**。
- 本桥让 Claude Code 编程驱动 Connector 的几百个 translator:抓当前页 / 给 URL 列表批量入库,全部走原生存储路径进本地 Zotero。

## 前置条件

1. **改造后的 Connector 扩展**已构建并以"加载已解压扩展程序"方式装进 Chrome —— 见 connector 仓库的 `src/browserExt/claude-bridge.js` 与构建说明(`build/manifestv3/`)。
2. **Zotero 桌面客户端**正在运行(`http://127.0.0.1:23119/connector/ping` 可达)。本机未开云同步也能用,因为全程走本地客户端。

## 安装

```bash
cd zotero-claude-bridge
pip install -e .          # 或 pip install -r requirements.txt
```

`pip install -e .` 后 `python -m zotero_claude_bridge` 与 `zotero-claude-bridge` 命令都可用。

## 注册到 Claude Code

任选其一:

**A. 命令行(推荐)**
```bash
claude mcp add zotero-claude-bridge \
  --env ZCB_HOST=127.0.0.1 --env ZCB_PORT=24731 \
  -- python -m zotero_claude_bridge
```

**B. 配置文件**(项目级 `.mcp.json` 或用户级 `~/.claude.json`):复制 `.mcp.json.example`。

注册后在 Claude Code 里即可用这些工具:
| 工具 | 作用 |
|---|---|
| `zotero_status` | 检查扩展连接 + Zotero 在线(先调它确认健康) |
| `zotero_capture_active_tab` | 抓浏览器当前活动 tab |
| `zotero_capture_url` | 后台开 tab 抓单个 URL,完成后关闭 |
| `zotero_capture_urls` | 批量抓(并发上限 5,单次上限 50) |
| `zotero_ping` | 调试往返 |

## 用法

在 Claude Code 里直接说:
- "把当前打开的这篇论文抓到 Zotero" → 调 `zotero_capture_active_tab`
- "把这 10 个 URL 的论文都抓到 Zotero:<url 列表>" → 调 `zotero_capture_urls`

返回结构化结果:
```json
{"success": true, "items": [{"title": "...", "itemType": "journalArticle",
  "creators": [...], "DOI": "...", "url": "...", "key": "ABCD1234"}],
 "durationMs": 3210}
```

## 先测桥(不装扩展)

```bash
# 终端1:起 MCP server(前台 stdio,等 Claude Code 调用)
python -m zotero_claude_bridge

# 终端2:起假扩展(模拟 Connector)
python scripts/fake_extension.py
```

在 Claude Code 调 `zotero_status` 应返回 `extension_connected: true`;调 `zotero_capture_active_tab` 返回一个 `FAKE PAPER` 条目。

## WebSocket 协议

仅 127.0.0.1,JSON 文本帧:
```
{v:1, id?, type, action?, data?, ts}
```
- `type`:`auth | auth_ok | request | response | notification | error | heartbeat`
- `action`:`ping | get_status | capture_active_tab | capture_url | capture_urls`
- 鉴权(MVP):loopback 信任 + 扩展首帧 `auth` → server 回 `auth_ok`。
- 心跳:双向 30s,60s 无帧则断;扩展指数退避重连。

CaptureResult `errorType`:`no_translator | translator_failure | zotero_offline | timeout | extension_disconnected | cancelled | unknown`。

## 故障排查

| 现象 | 原因 / 处理 |
|---|---|
| `extension_disconnected` | Connector 扩展未加载,或 SW 未激活——在 Chrome 打开任意网页(about:blank 不算)触发 SW |
| `zotero_offline` | Zotero 桌面端没开,或 23119 端口不通——启动 Zotero 客户端 |
| `no_translator` | 该 URL 没有匹配的 translator(非学术页或需登录态已失效) |
| `translator_failure` | 站点需登录(如知网),在浏览器里重新登录后再抓 |
| WS 连不上 | 确认端口 24731 未被占用;扩展 service worker 页面无报错;查 `%LOCALAPPDATA%\zotero-claude-bridge\bridge.log` |

## 配置

环境变量:`ZCB_HOST`(默认 127.0.0.1)、`ZCB_PORT`(默认 24731)、`ZCB_LOG_LEVEL`(默认 INFO)。

扩展端开关:在 Chrome 扩展 storage 里设 `claudeBridge.enabled=false` 可禁用桥,`claudeBridge.port` 改端口(需与 server 一致)。

## 相关仓库

- 改造的 Connector 扩展:`HCLEMINI/zotero-connectors-claude-code`(基于 `zotero/zotero-connectors`)。
- 本桥与扩展通过 WS 协议契约(见 `src/zotero_claude_bridge/schemas.py` 与扩展 `src/browserExt/claude-bridge.js`)保持一致。

License: AGPL-3.0-or-later(与上游 Zotero Connectors 一致)。