Skip to content

## Implement: biblio zotero push-tags — write enrichments back to Zotero Phase

Implement: biblio zotero push-tags — write enrichments back to Zotero

Phase 3 of the pool ecosystem spec (docs/specs/biblio/pool-ecosystem.md).

What

Add biblio zotero push-tags command and MCP tool that writes biblio enrichments (tags, notes, resolved metadata) back to Zotero items via the API.

Dependencies

  • pyzotero (same as zotero pull)
  • Zotero API write permissions (API key must have write access)
  • Items must have been pulled from Zotero originally (need item key mapping)

Behavior

# Push all enriched tags back to Zotero
biblio zotero push-tags

# Push tags for specific papers
biblio zotero push-tags --citekeys smith2024,doe2023

# Push from a specific project's library.yml
biblio zotero push-tags --source pixecog

# Push new papers (ingested via OpenAlex) to Zotero
biblio zotero push --new

What gets pushed back

biblio enrichment Zotero target Example
autotag tags Zotero tags method:place-cells, domain:hippocampus
concept categories Zotero tags (prefixed) concept:sharp-wave-ripple
reading status Zotero tag status:reading, status:cited
LLM summary Zotero note (child item) Structured summary as HTML note
Resolved DOI Zotero Extra field If DOI was missing in Zotero
OpenAlex ID Zotero Extra field OpenAlex: W1234567890

Implementation

  1. Push logicpackages/biblio/src/biblio/zotero_sync.py (extend)
  2. push_tags(citekeys, zotero_client) — read library.yml, map to Zotero tags, update items
  3. push_notes(citekeys, zotero_client) — create/update child note items with summaries
  4. push_new_items(citekeys, zotero_client) — create new Zotero items from biblio BibTeX

  5. Citekey ↔ Zotero item key mapping

  6. Maintained in .projio/biblio/zotero-sync.yml
  7. Built during zotero pull, updated during zotero push
  8. Falls back to DOI matching if citekey mapping missing

  9. Conflict detection

  10. Check item version before writing (Zotero uses version numbers)
  11. If item was modified in Zotero since last sync, warn and skip (or force with --force)

  12. MCP tool:

    def biblio_zotero_push(
        citekeys: list[str] | None = None,
        push_tags: bool = True,
        push_notes: bool = False,
        push_new: bool = False,
        force: bool = False,
    ) -> dict  # {"updated": N, "created": N, "conflicts": [...], "errors": [...]}
    

Key files

  • packages/biblio/src/biblio/zotero_sync.py — extend from pull implementation
  • packages/biblio/src/biblio/library.py — read tags/status
  • packages/biblio/src/biblio/autotag.py — read autotag results
  • packages/biblio/src/biblio/concepts.py — read concept results
  • packages/biblio/src/biblio/summarize.py — read summaries