Skip to content

## Implement: biblio zotero pull — read items + PDFs from Zotero via API

Phase

Goal

(promoted from note)

Context

(see source note)

Prompt

Fix the issue described in /storage2/arash/projects/projio/docs/log/issue/issue-arash-20260403-210002-675833.md. Read it first, then implement the proposed fix.

Acceptance Criteria

  • [ ]

Result

Completed in 432.4s (1 steps, model: opus)

Session: e7558a52-7468-42cd-9b68-bd33dd727fcf Result note: /storage2/arash/worklog/workflow/captures/20260403-211239-6ebcdb/note.md

Output

Everything is in place. Here's what was implemented:

## Summary

Implemented **Phase 1: `biblio zotero pull`** — read-only pull with incremental sync from Zotero.

### Files created
- **`packages/biblio/src/biblio/zotero.py`** — Core module with:
  - `ZoteroConfig` / `load_zotero_config()` — config from `zotero:` section in biblio.yml
  - `SyncState` — load/save `.projio/biblio/zotero_sync.yml` for version-based incremental sync
  - `ZoteroClient` — thin pyzotero wrapper (item_versions, fetch_items, fetch_attachment, deleted_since)
  - `item_to_bibtex()` — Zotero JSON → BibTeX conversion with type mapping
  - `pull()` — orchestrator: fetch changed items → write `bib/srcbib/zotero.bib` → download PDFs → handle deletions → update state → log
  - `status()` — return sync state for display

### Files modified
- **`packages/biblio/pyproject.toml`** — Added `zotero = ["pyzotero>=1.6"]` optional dep
- **`packages/biblio/src/biblio/cli.py`** — Added `biblio zotero pull` and `biblio zotero status` subcommands
- **`packages/biblio/src/biblio/mcp.py`** — Added `zotero_pull()` and `zotero_status()` MCP wrappers
- **`src/projio/mcp/biblio.py`** — Added `biblio_zotero_pull()` and `biblio_zotero_status()` tool functions
- **`src/projio/mcp/server.py`** — Registered `biblio_zotero_pull` and `biblio_zotero_status` tools

## Next Steps

1. Run `biblio zotero pull --dry-run` against a real Zotero library to validate the end-to-end flow (requires `zotero:` section in biblio.yml and `pip install pyzotero`).
2. Update CLAUDE.md's MCP tool table and biblio.py docstring to document the new `biblio_zotero_pull` and `biblio_zotero_status` tools.
3. Implement Phase 2 (`biblio zotero push`) for writing tags, notes, and DOI/OpenAlex IDs back to Zotero.