name: zotero-import description: "Teaches the two-step zotero_add -> zotero_confirm pipeline for importing papers into Zotero, including collection selection, file attachment, dedup handling, and non-HEP DOI support.\n"
Zotero Import Workflow
This skill teaches the correct tool-calling sequence for importing papers into Zotero via the zotero_* MCP tools.
All Zotero tools are local-only and require Zotero to be running with the Local API enabled (Settings → Advanced → "Allow other applications on this computer to communicate with Zotero").
Writes need the zotero-inspire plugin. Zotero's native Local API is read-only — every
POST/DELETEreturns400 "Endpoint does not support method". File attachment (zotero_add+file_path) and deletion (zotero_delete) are performed through the zotero-inspire plugin (≥ 3.0.3), which registers an authenticatedPOST /connector/zinspireWriteendpoint. The MCP reads the endpoint token from the Zotero profileprefs.jsautomatically; override with theZOTERO_WRITE_TOKENenv var. Item/note creation still works without the plugin (via the Connector). If the plugin is missing, item writes succeed and the attachment is reported asfile_attached:falsewith anattach_error(never silently dropped).
Core Pattern: Two-Step Add/Confirm
Every Zotero write operation follows a preview-then-confirm pattern:
zotero_add { source: {...}, ... } # Step 1: Preview — returns confirm_token
|
zotero_confirm { confirm_token: "..." } # Step 2: Execute — creates/updates the item
The zotero_add call resolves metadata, checks for duplicates, and returns a confirm_token (valid for 10 minutes). The agent should present the preview to the user, then call zotero_confirm to execute.
Source Types
INSPIRE (HEP papers)
{ "source": { "type": "inspire", "recid": "1234567" } }
DOI (HEP and non-HEP)
{ "source": { "type": "doi", "doi": "10.1103/PhysRevD.110.030001" } }
- HEP DOIs are resolved via INSPIRE first (richer metadata with arXiv IDs, collaborations).
- Non-HEP DOIs automatically fall back to CrossRef (e.g.,
10.1063/1.864977).
arXiv
{ "source": { "type": "arxiv", "arxiv_id": "2301.12345" } }
Manual item
{
"source": {
"type": "item",
"item": {
"itemType": "journalArticle",
"title": "...",
"creators": [{ "creatorType": "author", "lastName": "...", "firstName": "..." }],
"DOI": "10.xxx/yyy",
"date": "2024"
}
}
}
Collection Selection
Option A: Use Zotero UI selection (default)
If collection_keys is omitted, the tool writes to whichever collection is currently selected in Zotero's left sidebar. To check:
zotero_get_selected_collection {}
Option B: Explicit collection key
{ "source": {...}, "collection_keys": ["ABCD1234"] }
Library root
By default, writing to the library root (no collection) is rejected. Override with:
{ "source": {...}, "allow_library_root": true }
File Attachment
To attach a local file (e.g., a downloaded PDF) to the created item:
{
"source": { "type": "doi", "doi": "10.xxx/yyy" },
"file_path": "/absolute/path/to/paper.pdf",
"attach_mode": "import"
}
- The path must be absolute and the file must exist.
- Attachment is performed via the zotero-inspire write endpoint (see the note at the top); the native Local API cannot attach files.
attach_mode(defaultimport):import— copies the file into Zotero storage. Never mutates the source file and is robust to file-management plugins. Recommended default.link— references the file in place (Zotero stores a path, not a copy). ⚠️ File-management plugins (e.g. Attanger, ZotFile) auto-rename/move linked source files based on the parent item's metadata — usinglinkmay rename your original file on disk. Preferimportunless you specifically manage linked files yourself.
- On success the confirm result reports
file_attached: true,attach_mode, andattachment_key. On failure it reportsfile_attached: falseand a structuredattach_error(the item write still succeeds). - Supported formats: PDF, EPUB, HTML, DJVU, DOC/DOCX, and others.
Deduplication
The dedupe parameter controls behavior when the item already exists in Zotero:
| Value | Behavior |
|---|---|
return_existing (default) |
Return the existing item without changes |
update_existing |
Add new collections/tags/notes to the existing item |
error_on_existing |
Throw an error if the item exists |
Dedup matches on DOI, arXiv ID, and INSPIRE recid.
Tags and Notes
{
"source": { "type": "doi", "doi": "10.xxx/yyy" },
"tags": ["hep-ph", "review"],
"note": "Key reference for section 3"
}
Complete Example: Import a non-HEP paper with PDF
# 1. Check which collection is selected
zotero_get_selected_collection {}
# 2. Preview the import
zotero_add {
"source": { "type": "doi", "doi": "10.1063/1.864977" },
"tags": ["plasma-physics"],
"file_path": "/path/to/Downloads/hasegawa1983.pdf"
}
# -> Returns confirm_token + preview
# 3. Confirm
zotero_confirm { "confirm_token": "<token from step 2>" }
# -> Item created with PDF attached
Integration with sci-hub
When a paper has been downloaded via sci-hub, the manifest contains the DOI and file path. Use these directly:
zotero_add {
"source": { "type": "doi", "doi": "<DOI from manifest>" },
"file_path": "<downloaded PDF path>"
}
Common Pitfalls
- Token expiry: Confirm tokens expire after 10 minutes. If expired, re-run
zotero_add. - Collection not selected: If Zotero has no collection selected and no
collection_keysgiven, the call fails. Check withzotero_get_selected_collectionfirst. - Native Local API is read-only: The native Local API cannot create attachments or delete items (
400 "Endpoint does not support method"). File attachment andzotero_deleteroute through the zotero-inspire plugin endpoint (see the note at the top). If it is unavailable, item/note creation still works; attachment is reported asfile_attached:false+attach_errorrather than silently dropped. linkattach mutates source files: Withattach_mode:"link", file-management plugins (Attanger/ZotFile) may rename or move your source file. Use the defaultattach_mode:"import".- Large metadata: The
itemsource type has a 200KB JSON limit.
Deleting Items
Delete follows the same preview → confirm pattern (destructive, so it is gated):
# 1. Preview — resolves each key's title/type; returns confirm_token
zotero_delete { "item_keys": ["ABCD1234", "EFGH5678"], "mode": "trash" }
# 2. Execute
zotero_confirm { "confirm_token": "<token from step 1>" }
mode: "trash"(default) moves items to the Zotero trash — recoverable.mode: "erase"permanently deletes them — not recoverable; the preview warns accordingly.- Missing keys are flagged in the preview and skipped on execute; per-item results are returned (
succeeded/skipped/failed). - Deleting a top-level item removes its child attachments/notes too.
Tool Reference
| Tool | Purpose |
|---|---|
zotero_get_selected_collection |
Check which collection is selected in Zotero UI |
zotero_add |
Preview a Zotero add/update with optional file_path (attach_mode import/link); returns confirm_token |
zotero_delete |
Preview a trash/erase of items by key; returns confirm_token |
zotero_confirm |
Execute a previewed write operation (add or delete) |
zotero_local |
Query Zotero Local API directly (read operations) |
zotero_find_items |
Search existing Zotero items |
zotero_search_items |
Full-text search in Zotero library |
zotero_export_items |
Export items as BibTeX/CSL-JSON/RIS/etc. |