Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

Zotero Native MCP

NPM · ZOTERO-NATIVE-MCP · SCANNED SEP 21

Read and write your local Zotero 10 library. No plugin, no zotero.org API key, no cloud.

Available components

+4 this week 88 Trust /100
Trust breakdown (7 categories)

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →

Supply Chain Security98
  • No malware found by supply-chain analysis.Pass
  • No known CVEs affecting this package version or its production dependencies.Pass
  • No install/post-install scripts declared.Pass
  • 31 of 96 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency97
  • Source repository is publicly reachable at the declared URL. View diagnostics → Pass
  • Cryptographically verified build provenance (signed, bound to dvdsosa/zotero-native-mcp). View diagnostics → Pass
  • Clear OSI-approved license (MIT).Pass
  • Actively maintained (last published 17 days ago).Pass
  • Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability71
  • AI-judged instruction clarity (excellent).Pass
  • Context-footprint check failed: tool/resource definitions use about 5122 tokens (~182/item across 28 items; 28 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
  • Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management60
  • Stability observed for 18 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage100
  • 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
  • 100% of tool parameters carry a description.Pass
  • Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety94
  • No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
  • 3 of 4 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation; "zotero_run_saved_search" implies "execute" and declares readOnlyHint instead, contradicting what its own name says it does. See how to fix → Partial
  • An AI judge read all 29 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
  • Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Install

How do I install the Zotero Native MCP server?

Zotero Native MCP runs locally as an npm package, launched with npx -y zotero-native-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

npm · zotero-native-mcp

# add to Claude Code
claude mcp add dvdsosa-zotero-native-mcp -- npx -y zotero-native-mcp
// .cursor/mcp.json
{
  "mcpServers": {
    "dvdsosa-zotero-native-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "zotero-native-mcp"
      ]
    }
  }
}
// .vscode/mcp.json
{
  "servers": {
    "dvdsosa-zotero-native-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "zotero-native-mcp"
      ]
    }
  }
}
# add to Codex CLI
codex mcp add dvdsosa-zotero-native-mcp -- npx -y zotero-native-mcp
// opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "dvdsosa-zotero-native-mcp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "zotero-native-mcp"
      ],
      "enabled": true
    }
  }
}
# add to OpenClaw
openclaw mcp add dvdsosa-zotero-native-mcp --command npx --arg -y --arg zotero-native-mcp
# ~/.hermes/config.yaml
mcp_servers:
  dvdsosa-zotero-native-mcp:
    command: "npx"
    args: ["-y", "zotero-native-mcp"]
// ~/.netclaw/config/netclaw.json
{
  "McpServers": {
    "dvdsosa-zotero-native-mcp": {
      "Transport": "stdio",
      "Command": "npx",
      "Arguments": [
        "-y",
        "zotero-native-mcp"
      ]
    }
  }
}
# add to Vellum
assistant mcp add dvdsosa-zotero-native-mcp -t stdio -c npx -a -y zotero-native-mcp
// mcp.json
{
  "mcpServers": {
    "dvdsosa-zotero-native-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "zotero-native-mcp"
      ]
    }
  }
}
Changelog

Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.

  • 21 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 57 to 60. That category is still filling its 30-day observation window: 17 days of observed history at the previous scan, 18 at this one. The score rises as the window fills, whether or not the server changes.

  • 19 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 50 to 53. That category is still filling its 30-day observation window: 15 days of observed history at the previous scan, 16 at this one. The score rises as the window fills, whether or not the server changes.

  • 17 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 43 to 47. That category is still filling its 30-day observation window: 13 days of observed history at the previous scan, 14 at this one. The score rises as the window fills, whether or not the server changes.

  • 15 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 37 to 40. That category is still filling its 30-day observation window: 11 days of observed history at the previous scan, 12 at this one. The score rises as the window fills, whether or not the server changes.

  • 13 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 30 to 33. That category is still filling its 30-day observation window: 9 days of observed history at the previous scan, 10 at this one. The score rises as the window fills, whether or not the server changes.

  • 11 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

  • 8 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

  • 6 Sept 26 +1

    No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

Diagnostics

Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.

Captured 21 Sept 2026 · Analysed npm/zotero-native-mcp@1.0.1

Provenance Verified

A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.

Result Verified
Ecosystem npm
Reason Verified
Discovered via Registry attestation endpoint
Source repo dvdsosa/zotero-native-mcp
Certificate issuer https://token.actions.githubusercontent.com
Certificate SAN https://github.com/dvdsosa/zotero-native-mcp/.github/workflows/publish.yml@refs/heads/main
Rekor log index 2704769964
Predicate type https://slsa.dev/provenance/v1
Subject digest sha512:e0e2692ab1518809b1621b611ec217720413d626b6bff3ca4ff3fd1c44aab2968cb9b7006c5bbe40834a6ca17f27627939772e4b0b37c7706537d1f8f

Background: How many MCP packages publish verified provenance →

Dependencies 96 packages
Packages resolved 96
Stale 31
Tree resolution Complete

Background: SBOMs and build attestations, explained →

MCP tools · 28 exposed · ~4,987 tokens

The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →

Tool Tokens
zotero_add_items_to_collection ~125

File existing items into a collection, keeping every collection they already belong to. An item in Zotero can sit in any number of collections, so this adds rather than moves. Items already in the collection are reported as unchanged and cost no write.

NameTypeReqDescription
collectionKeystringyesTarget collection key.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeysarrayyesKeys of the items to file.
NameTypeReqDescription
addedarrayyes
alreadyPresentarrayyes
collectionKeystringyes

No examples provided.

zotero_attach_file ~320

Attach a file from disk to a Zotero item, or add it as a standalone attachment. mode="linked" (default) records the path only: instant for any file size, but the file must stay put and the attachment does not sync to zotero.org. mode="imported" copies the file into Zotero's storage, so it syncs and survives the original being moved. Group libraries accept only "imported", since a local path means nothing to other members. filePath must be absolute. Pass parentItemKey to hang the file off an existing reference; omit it for a standalone attachment, optionally filed into collections.

NameTypeReqDescription
collectionsarrayCollections to file the attachment into. Only valid for standalone attachments (no parentItemKey).
filePathstringyesAbsolute path to the file on this machine, e.g. "/Users/me/papers/smith-2024.pdf".
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
modestring"linked" stores the path only (instant, no copy, no sync); "imported" copies the file into Zotero (syncs).
parentItemKeystringItem this file belongs to. Omit to create a standalone attachment item.
tagsarrayTags to attach.
titlestringAttachment title shown in Zotero. Defaults to the file name.
NameTypeReqDescription
attachmentobjectyes
attachmentKeystringyes
bytesnumberyes
contentTypestringyes
filePathstringyes
modestringyes
uploadedbooleanyesTrue when file bytes were transferred; false for linked files and deduplicated uploads.

No examples provided.

zotero_authorize ~191

Request a local API key so write tools (creating collections, items, and attachments) can run. This raises a modal dialog inside Zotero on the user's screen with three choices: "Allow" issues a single-use key, "Always Allow" issues a persistent one, and "Deny" refuses. Tell the user to expect the dialog, and to pick "Always Allow" for a session that will perform several writes. The key is stored locally and reused; write tools also re-authorize on their own when a single-use key is spent, so calling this manually is only needed to grant access up front. Calling it when a key is already stored reuses that key and shows no dialog.

NameTypeReqDescription
forcebooleanRequest a new key even though one is already stored. Rarely needed: a stored key is reused, and replacing a persistent key with a single-use one makes things worse.
NameTypeReqDescription
alreadyHeldbooleanyesTrue when an existing stored key was reused and no dialog appeared.
authorizedbooleanyes
messagestringyes
persistentbooleanyesTrue when the key persists; false keys are consumed by the next write.

No examples provided.

zotero_create_collection ~120

Create one or more collections, optionally nested under an existing collection. Up to 50 per call. Creating a nested tree takes one call per level, since a child needs its parent's key. Requires write access; zotero_authorize runs automatically if none has been granted.

NameTypeReqDescription
collectionsarrayyesCollections to create, at most 50 per call.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
NameTypeReqDescription
createdarrayyes
failuresarrayyes
libraryVersionnumber|nullyes

No examples provided.

zotero_create_items ~158

Create up to 50 items in one call. Set `collections` on an item to file it into collections as it is created, which is cheaper than creating it and moving it afterwards. Notes and attachments are created by setting parentItem. To attach a file from disk use zotero_attach_file instead, which handles the whole attachment protocol. Check the returned `failures` array: Zotero validates each item independently, so some can succeed while others fail.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemsarrayyesItems to create, at most 50 per call.
NameTypeReqDescription
createdarrayyes
failuresarrayyes
libraryVersionnumber|nullyes

No examples provided.

zotero_delete_collection ~203

Move collections to Zotero's trash, which is reversible and the default. The items inside are never deleted either way: they stay in the library and in any other collection they belong to. Subcollections follow their parent. Pass permanent: true only on an explicit request from the user, to erase the collections outright with no way back. Note that a trashed collection cannot be listed through the local API, so record the key returned here if it may need restoring.

NameTypeReqDescription
collectionKeysarrayyesKeys of the collections to remove, at most 50 per call.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
permanentbooleanfalse (default) moves the collections to the trash, which is reversible. true erases them irreversibly. Only pass true on an explicit request from the user.
NameTypeReqDescription
erasedarrayyesCollections erased irreversibly. Empty when permanent is false.
libraryVersionnumber|nullyes
notFoundarrayyes
permanentbooleanyes
trashedarrayyesCollections moved to the trash. Empty when permanent is true.

No examples provided.

zotero_delete_items ~225

Move up to 50 items to Zotero's trash, where the user can restore them from the Zotero window or with zotero_restore_items. This is the default and it is reversible. Trashed items keep their attachments and files; Zotero empties the trash automatically after 30 days by default. Pass permanent: true only when the user has explicitly asked for an irreversible delete: that erases the items outright, takes their child notes and attachments with them, removes attachment files from disk, and cannot be undone by anything.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeysarrayyesKeys of the items to remove, at most 50 per call.
permanentbooleanfalse (default) moves the items to the trash, which is reversible. true erases them immediately and irreversibly, deleting attachment files from disk. Only pass true on an explicit request from the u…
NameTypeReqDescription
alreadyInTrasharrayyes
erasedarrayyesItems erased irreversibly. Empty when permanent is false.
libraryVersionnumber|nullyes
notFoundarrayyes
permanentbooleanyes
trashedarrayyesItems moved to the trash. Empty when permanent is true.

No examples provided.

zotero_empty_trash ~166

Permanently erase every item in the trash. This is irreversible and removes attachment files from disk. As an interlock against emptying a trash the caller has not looked at, expectedCount must equal the number of items actually in it: call zotero_list_trash first and pass its totalResults. If the two disagree the call is refused and nothing is deleted. Only use this when the user has explicitly asked to empty the trash.

NameTypeReqDescription
expectedCountintegeryesHow many items you expect to erase, from zotero_list_trash. A mismatch aborts the call.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
NameTypeReqDescription
erasednumberyes
libraryVersionnumber|nullyes

No examples provided.

zotero_export_items ~222

Export items in a citation format. Use format "bibtex", "biblatex", "ris", "csljson", "csv" or "tei" for a machine-readable export, or "bib" to render a formatted bibliography in a citation style (set `style`, e.g. "apa", "chicago-note-bibliography", "ieee"). Returns the export as text.

NameTypeReqDescription
formatstringExport format. "bib" renders a formatted bibliography using `style`.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeysarrayyesKeys of the items to export.
localestringLocale for format "bib", e.g. "en-US", "es-ES".
stylestringCitation style for format "bib", e.g. "apa", "ieee", "chicago-note-bibliography". Ignored otherwise.
NameTypeReqDescription
formatstringyes
itemCountnumberyes
outputstringyes
skippedKeysarrayyesRequested keys that are not top-level items and were left out.

No examples provided.

zotero_get_attachment_path ~130

Resolve an attachment to its absolute path on this machine, so the file can be opened and read directly. Works for both linked and imported attachments. Passing a regular item key returns the paths of all of its file attachments. Use this to read a PDF whose text Zotero has not indexed.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeystringyesAttachment key, or a parent item key to resolve all of its attachments.
NameTypeReqDescription
attachmentsarrayyes

No examples provided.

zotero_get_collection ~157

Fetch one collection by key, including its name, parent collection, item count and current version. The version is what zotero_update_collection and zotero_delete_collection use for conflict detection.

NameTypeReqDescription
collectionKeystringyesCollection key, e.g. "WXYZ5678".
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
collectionobjectyes

No examples provided.

zotero_get_item ~176

Fetch one item by key with all of its metadata. Set includeChildren to also return its notes and attachments, which is the quickest way to find the attachment key needed to read a PDF or its full text.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
includeChildrenbooleanAlso return child notes and attachments.
itemKeystringyesItem key, e.g. "ABCD1234".
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
childrenarray
itemobjectyes

No examples provided.

zotero_get_item_children ~187

List the child notes, attachments and annotations of an item. Attachment children carry the linkMode and filename needed by zotero_get_attachment_path and zotero_get_item_fulltext.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeystringyesParent item key.
limitintegerMaximum number of objects to return (1-500).
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
childrenarrayyes
hasMorebooleanyes
nextStartnumber|nullyes
returnednumberyes
startnumberyes
totalResultsnumber|nullyes

No examples provided.

zotero_get_item_fulltext ~149

Return the indexed full text of an attachment. Passing a regular item key works too: its attachments are searched and the first one with indexed text is used. Text comes from Zotero's own index, so it is available only for attachments Zotero has indexed. Long documents can be truncated with maxCharacters.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeystringyesAttachment key, or a parent item key to search its attachments.
maxCharactersintegerTruncate the returned text at this many characters.
NameTypeReqDescription
attachmentKeystringyes
contentstringyes
indexedPagesnumber|nullyes
totalCharactersnumberyes
totalPagesnumber|nullyes
truncatedbooleanyes

No examples provided.

zotero_get_item_type_fields ~105

List the valid field names and creator types for a Zotero item type, or list every item type when itemType is omitted. Call this before zotero_create_items with an unfamiliar item type: Zotero rejects a write outright if it carries a field the type does not define.

NameTypeReqDescription
itemTypestringItem type to describe, e.g. "journalArticle", "book", "thesis", "preprint". Omit to list all types.
NameTypeReqDescription
creatorTypesarray
fieldsarray
itemTypestring
itemTypesarray

No examples provided.

zotero_list_collections ~256

List collections in a library. scope="all" returns every collection flat (each carrying its parentCollection key, so the full tree can be reconstructed in one call), "top" returns only root-level collections, and "children" returns the direct subcollections of parentKey. Collection keys returned here are what zotero_create_items, zotero_add_items_to_collection and zotero_search_items take.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
limitintegerMaximum number of objects to return (1-500).
parentKeystringParent collection key; required when scope is "children".
scopestringWhich collections to return. "children" requires parentKey.
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
collectionsarrayyes
hasMorebooleanyes
nextStartnumber|nullyes
returnednumberyes
startnumberyes
totalResultsnumber|nullyes

No examples provided.

zotero_list_libraries ~46

List the personal library and every group library available locally. Use this to get the groupId that other tools take when the target is a group library rather than "My Library".

Input schema present but exposes no named parameters.

NameTypeReqDescription
groupsarrayyes
personalLibraryyes

No examples provided.

zotero_list_saved_searches ~184

List the saved searches defined in the library, with their conditions. Run one with zotero_run_saved_search. Note that the local API can actually execute saved searches, which the zotero.org web API cannot.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
limitintegerMaximum number of objects to return (1-500).
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
hasMorebooleanyes
nextStartnumber|nullyes
returnednumberyes
searchesarrayyes
startnumberyes
totalResultsnumber|nullyes

No examples provided.

zotero_list_tags ~172

List tags in the library, optionally only those used within one collection or matching a search. Useful for discovering how a library is organized before filtering zotero_search_items by tag.

NameTypeReqDescription
collectionKeystringOnly tags used by items in this collection.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
limitintegerMaximum number of objects to return (1-500).
qstringFilter tags by text.
qmodestringHow `q` matches. Ignored when `q` is omitted.
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
NameTypeReqDescription
hasMorebooleanyes
nextStartnumber|nullyes
returnednumberyes
startnumberyes
tagsarrayyes
totalResultsnumber|nullyes

No examples provided.

zotero_list_trash ~205

List the items currently in Zotero's trash, which are the ones zotero_restore_items can bring back. Note that trashed *collections* do not appear here: Zotero's local API offers no way to enumerate them, so a trashed collection can only be restored by key or from the Zotero window.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
limitintegerMaximum number of objects to return (1-500).
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
hasMorebooleanyes
itemsarrayyes
nextStartnumber|nullyes
returnednumberyes
startnumberyes
totalResultsnumber|nullyes

No examples provided.

zotero_remove_items_from_collection ~115

Remove items from one collection. The items stay in the library and in any other collection they belong to; nothing is deleted. Items that were not in the collection are reported as unchanged.

NameTypeReqDescription
collectionKeystringyesCollection to remove them from.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeysarrayyesKeys of the items to remove.
NameTypeReqDescription
collectionKeystringyes
notPresentarrayyes
removedarrayyes

No examples provided.

zotero_restore_collection ~142

Bring collections back out of Zotero's trash, undoing a non-permanent zotero_delete_collection. You must know the key: Zotero's local API cannot list trashed collections, so there is no way to discover them from here, the user can see them in the Zotero window's trash. A collection erased permanently cannot be restored at all.

NameTypeReqDescription
collectionKeysarrayyesKeys of the collections to restore, at most 50 per call.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
NameTypeReqDescription
notFoundarrayyes
restoredarrayyes

No examples provided.

zotero_restore_items ~135

Bring items back out of Zotero's trash, undoing a non-permanent zotero_delete_items. The items return to the collections they were in. Only works while they are still in the trash: nothing can recover an item that was erased permanently or that Zotero has already purged after its 30-day retention.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeysarrayyesKeys of the items to restore, at most 50 per call.
NameTypeReqDescription
notFoundarrayyes
restoredarrayyes
wereNotInTrasharrayyes

No examples provided.

zotero_run_saved_search ~199

Execute a saved search and return the matching items. The search runs against the local database using Zotero's own engine, so the results match what the saved search shows in the Zotero UI.

NameTypeReqDescription
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
limitintegerMaximum number of objects to return (1-500).
searchKeystringyesSaved search key, from zotero_list_saved_searches.
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
hasMorebooleanyes
itemsarrayyes
nextStartnumber|nullyes
returnednumberyes
startnumberyes
totalResultsnumber|nullyes

No examples provided.

zotero_search_items ~437

Search the local Zotero library. `q` runs Zotero's quicksearch: qmode "titleCreatorYear" (default) matches titles, creators and years, while "everything" also matches attachment full text and notes. Filters combine: pass collectionKey to search inside one collection, itemType to restrict by type ("-attachment" excludes a type), tag to filter by tag. Omit `q` to browse. Returns flattened item metadata; use zotero_get_item for one item in full.

NameTypeReqDescription
collectionKeystringRestrict the search to one collection.
directionstringSort direction.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
includeTrashedbooleanInclude items currently in the trash.
itemTypestringItem type filter. Supports Zotero syntax: "book", "book || journalArticle", "-attachment".
limitintegerMaximum number of objects to return (1-500).
qstringSearch text. Omit to list items without filtering by text.
qmodestring"titleCreatorYear" searches metadata only; "everything" also searches full text and notes (slower).
sinceintegerReturn only objects modified after this library version, for incremental syncing.
sortstringSort field.
startintegerZero-based offset for paging; pass the nextStart value from a previous call.
tagstringTag filter. Supports "tag1 || tag2" for OR and a leading "-" to exclude.
topLevelOnlybooleanReturn only top-level items, hiding child notes and attachments. Set false to include children.
verbosebooleanReturn Zotero's raw API envelope (library block, self/alternate links, full meta) instead of the flattened object. Costs many extra tokens per object; only useful when a URL or the raw meta block is…
NameTypeReqDescription
hasMorebooleanyes
itemsarrayyes
nextStartnumber|nullyes
returnednumberyes
startnumberyes
totalResultsnumber|nullyes

No examples provided.

zotero_status ~55

Check that the local Zotero instance is running and reachable, and report its version, schema version, instance ID, and whether write access has been granted yet. Call this first when any other tool reports a connection or authorization problem.

Input schema present but exposes no named parameters.

NameTypeReqDescription
apiVersionstring|nullyes
appNamestringyes
baseUrlstringyes
connectedbooleanyes
groupLibrariesnumberyes
personalLibraryyes
schemaVersionstring|nullyes
serverIdstringyes
writeAccessbooleanyes
zoteroVersionstring|nullyes

No examples provided.

zotero_update_collection ~193

Rename a collection and/or move it under a different parent. Pass parentCollectionKey=null to move a collection to the root of the library. The current version is fetched automatically unless expectedVersion is given, in which case the write fails with a conflict if the collection changed in the meantime.

NameTypeReqDescription
collectionKeystringyesKey of the collection to modify.
expectedVersionintegerVersion the collection is expected to be at, for conflict detection. Omit to use the current version.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
namestringNew name. Omit to leave the name unchanged.
parentCollectionKeyNew parent collection key, or null to move to the library root. Omit to leave the parent unchanged.
NameTypeReqDescription
collectionKeystringyes
libraryVersionnumber|nullyes
updatedbooleanyes

No examples provided.

zotero_update_item ~214

Patch fields on an existing item. Only the fields passed in `fields` change; everything else is left alone. Array fields are replaced wholesale, so to change collection membership prefer zotero_add_items_to_collection / zotero_remove_items_from_collection, which merge instead of overwriting. The current version is read automatically unless expectedVersion is supplied.

NameTypeReqDescription
expectedVersionintegerVersion the item is expected to be at, for conflict detection. Omit to use the current version.
fieldsobjectyesFields to set, as Zotero item JSON, e.g. {"title": "New title", "date": "2024", "tags": [{"tag": "to-read"}]}. Field names must be valid for the item's type.
groupIdintegerGroup library ID. Omit for the personal library ("My Library"), which is what almost every request wants. Group IDs come from zotero_list_libraries.
itemKeystringyesKey of the item to update.
NameTypeReqDescription
itemKeystringyes
libraryVersionnumber|nullyes
updatedbooleanyes

No examples provided.

Common questions

What is the Zotero Native MCP server?

Zotero Native MCP is listed in the public MCP registry as io.github.dvdsosa/zotero-native-mcp. Read and write your local Zotero 10 library. No plugin, no zotero.org API key, no cloud. This page covers its npm package (zotero-native-mcp).

Is the Zotero Native MCP server safe to use?

Zotero Native MCP scores 88 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 21 September 2026. It declares no install or post-install scripts. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

What tools does the Zotero Native MCP server expose?

Zotero Native MCP exposes 28 tools: zotero_status, zotero_authorize, zotero_list_libraries, zotero_get_item_type_fields, zotero_list_collections, and 23 more. Their descriptions and schemas cost roughly 4,987 tokens of context every time the server is loaded.

Is the Zotero Native MCP server still maintained?

Zotero Native MCP is still listed as active in the MCP registry. We last reached this channel on 21 September 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

What licence is the Zotero Native MCP server under?

Zotero Native MCP declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.