Other formats agents might prefer:
markdownjsonllms.txt

Agent? You probably want markdown or json, or Pod over MCP.

Reported issues for Zotero MCP

Pod holds 24 of 229 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to Zotero MCP.

Most discussed

Collection scoping fails in local/hybrid mode: advanced_search returns empty, search_by_tag ignores collection_key and item_type

With ZOTERO_LOCAL=true set alongside ZOTERO_API_KEY/ZOTERO_LIBRARY_ID (hybrid: local reads, web-API writes), collection-scoped search fails:

  1. zotero_advanced_search returns "No items found" for any query containing a collection condition, even when its other conditions match hundreds of items.
  2. zotero_search_by_tag ignores both collection_key and item_type, returning library-wide results including notes and attachments.

Environment

zotero-mcp-server 0.6.4 (cu

Read the thread · 2026-08-02 · closed · external user · 8 comments

feature: add items by bibtex and/or CSL JSON

The write API supports adding files by Epub/PDF in the zotero_add_from_file method. But there are other types of files we might wish to import to ingest existing ref and they are in many ways easier, since they require less work to recover the metadata. Also most LLMs are very fluent in bibtex. I propose we allow importing of those as well

Read the thread · 2026-04-21 · closed · outside contributor · 9 comments

usage for codex cli

  • system: Windows11 Can zotero-mcp be work for codex cli in Windows 11? If work,how to modify config? Or how to config?

I try to add configs in \.codex\config.toml as:

[mcp_servers.zetero]
type = "stdio"
command = "cmd"
args = [  "/c", "C:\\Users\\livin\\.local\\bin\\zotero-mcp.exe" ]
env = { ZOTERO_LOCAL = "true" }

BUT, it can't work.

Image

Read the thread · 2026-03-24 · closed · external user · 8 comments

Suggestion to speed up the update of semantic search database

I have a large database, and it takes a couple of hours to run zotero-mcp update-db --fulltext, which is fine for an initial run, but I was surprised that it takes almost as long on subsequent runs. I asked Claude Code to look at the code and suggest a way to improve this. I'm not a coder, so this is an AI's suggestion. Please forgive me if this is way off-base. But maybe it will help?


Looking at the code, it DOES check ChromaDB (document_exists(item_key)) before adding items, BUT the

Read the thread · 2025-10-23 · closed · external user · 8 comments

Error: Zotero API connection error:

code: zotero-mcp update-db

ERROR: Starting database update... Error updating database: Zotero API connection error: Code: 500 URL: http://localhost:23119/api/users/0/items?locale=en-US&start=0&limit=100&format=json Method: GET Response:

Database update completed:

Read the thread · 2025-10-22 · closed · external user · 11 comments

Add --pdf-timeout option to skip slow PDFs during fulltext extraction

Problem

When running zotero-mcp update-db --fulltext on large libraries, the process can hang indefinitely on PDFs with complex formatting or layout issues. The extraction gets stuck in pdfminer's layout analysis phase, causing the entire indexing process to stall.

Example: In my library of ~8,800 items, the first 500 PDFs processed quickly (a few seconds each), but then the process hung at item 525 for over 15 minutes before I had to cancel it. The traceback showed it was stuck in `pdfminer

Read the thread · 2025-10-16 · closed · external user · 16 comments

Can't access MCP server in Claude Desktop

Expected behaviour:

zotero-mcp setup sets up the MCP server and I can access it in Claude Desktop using /tools zotero

Actual behaviour:

zotero-mcp setup runs without errors, generates a claude_desktop_config.json, but even after restarting Claude Desktop, no Zotero tool is to be found.

Observation:

The claude_desktop_config.json that's generated is placed into "%APPDATA%/Roaming/Claude Desktop". However, if (within Claude Desktop) I click Developer -> Open app config file

Read the thread · 2025-07-15 · open · external user · 12 comments

Connection refused on local API

The web API works fine. But for local API, I've tried on both Smithery and VS Code, both get the error message:

[Errno 111] Connection refused

I can ensure local API is enabled in Zotero advanced settings. And in command line:

curl http://localhost:23119/api/users/0/items?limit=1

works fine and returns a recent item.

Read the thread · 2025-04-07 · closed · external user · 8 comments

Most recent

zotero_manage_note (create) silently stores Markdown input as plain text — no warning, no conversion

Environment

  • zotero-mcp v0.11.0 (HTTP transport), Zotero 7 on Windows
  • Client: Qwen Code (agent CLI), but reproducible with any MCP client

Steps to reproduce

  1. Call zotero_manage_note with action: "create" and a note containing standard Markdown, e.g.:
    • ## Heading
    • **bold text**
    • - list item
  2. Read the note back via zotero_get_notes with raw_html: true.

Expected behavior Either (a) Markdown is converted to HTML (like other Zotero tooling does), or (b)

Read the thread · 2026-08-29 · open · external user · 0 comments

zotero-cli get children --json returns zero items because child Key lines are not parsed

Summary

zotero-cli --json get children <parent_key> can report count: 0 even though Markdown mode correctly lists the parent item's children.

Confirmed with zotero-mcp-server 0.11.0 in Web API mode, and the same parsing path is present on current main.

Minimal reproduction

For any parent item with attachment or note children:

$ zotero-cli get children <parent_key>
## Attachments
   - Key: <attachment_key>
## Notes
   - Key: <note_key>

$ zotero-cli --json get childr

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/500) · 2026-08-28 · open · external user · 0 comments

### zotero-cli --json search returns empty in local mode (local API itemKey filter returns children first, limit=len(chunk) truncates parents)

## Summary

`zotero-cli --json search "<query>"` returns `count: 0` (empty items) when running in **local mode** (`ZOTERO_LOCAL=true`), even though the same search works in markdown mode and returns items via the web API. The markdown (`non-JSON`) path works fine, so the JSON rendering pipeline is where the bug lives.

## Environment

- `zotero-mcp-server` 0.11.0 (latest on PyPI as of today)
- Windows 11, Zotero 9 desktop, local API enabled on port 23119
- Hybrid config: `ZOTERO_LOCAL=true`, `ZO

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/499) · 2026-08-27 · open · external user · 0 comments

### search_items unit tests escape their mock when a real semantic config exists, and a stalled connect kills the suite

## Describe the bug

The mocked `search_items` unit tests in `tests/test_tag_filter_normalization.py` (`TestSearchItemsIntegration`) are hermetic only on machines that have no real zotero-mcp setup. On a developer machine with a populated `~/.config/zotero-mcp/config.json` and semantic index, they escape their mock and touch the real index and the real network, and under the wrong conditions one of them takes the whole suite down with it.

## Mechanism

The tests patch `zotero_mcp.tools.search._

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/498) · 2026-08-25 · open · external user · 0 comments

### Consolidate scattered duplicate-matching logic behind shared match-key primitives

## Problem

Four places in the codebase answer "are these the same work?", and they disagree substantively — not just stylistically.

| Site | Question | DOI key | Title key |
|---|---|---|---|
| `find_existing_items` (`tools/_helpers.py:787`) | does an item with *this* id exist? | `normalize_doi()`, case **preserved** | none, by design |
| `_maybe_reuse_existing` (`tools/write.py:5039`) | batch-import reuse | delegates to the above | none, "out of scope" |
| `_collect_duplicate_groups` (`tools/

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/496) · 2026-08-25 · open · outside contributor · 0 comments

### Deduplicate identical attachment files in the semantic index by content hash

## Problem

The same PDF filed under two Zotero items is embedded twice, in full. There is no content hashing anywhere in the index path — the only `hashlib` use in extraction or indexing is `fulltext_cache.py:74`, which hashes `attachment_key:mtime_ns:size`, an identity key rather than file content.

Index identity is the item key throughout: chunk ids are `{item_key}#{ci}`, so two items pointing at byte-identical files are two independent document sets. The cost is embedding compute (the expen

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/495) · 2026-08-25 · open · outside contributor · 0 comments

### Semantic index should cover every readable attachment, not one per item

## Problem

The semantic index covers exactly one attachment per item. An item holding both the article and its online supplement is indexed from one of them; the other is never extracted, never embedded, and never searchable.

`_resolve_extraction_target` (`local_db.py:886`) collects every readable attachment, then `pick_by_priority` (`extract.py:292`) returns a single one: the first non-empty category bucket in `attachment_priority` order, and within that bucket `max(bucket, key=size)`.

The s

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/494) · 2026-08-25 · open · outside contributor · 0 comments

### Feature request: dedupe cross-library copies in semantic search results (with over-fetch so limit stays meaningful)

## Feature request

When the same paper is saved in more than one indexed library, cross-library semantic search returns one hit per copy. Each copy is a distinct Zotero item (its own key, its own tags), so this is correct behavior rather than a bug, but it quietly eats the result budget: in my library (personal + 3 group libraries, with heavy overlap between two of the groups) a `zotero_semantic_search` call with `limit=10` routinely returns ~5 unique papers, with the top hits appearing as adja

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/493) · 2026-08-24 · open · external user · 4 comments

### Semantic search hits from group libraries fail enrichment: results render as bare item keys

## Describe the bug

Since #163 the indexer stamps each document with its library's `group_id`, and `search()` spans all indexed libraries by default. But `_enrich_search_results` fetches every hit with `self.zotero_client.item(item_key)`, a single client bound to the *active* library. A group item is not reachable at `/api/users/<id>/items/<key>`, so the fetch 404s and the result renders as `## 1. Item WTDQVCR3` with no title or authors.

The `library_id` parameter on `zotero_semantic_search` d

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/492) · 2026-08-24 · open · external user · 2 comments

### The Zotero API lock has no stated policy for item creation, and the guard the code names doesn't cover it

Splitting this out of #443, where it came up while narrowing the API lock. It
isn't a blocker for that PR — it's a question about the codebase's concurrency
model that predates it and is better answered once, in one place, than per-hunk.

### The lock does two jobs, and only one is written down

`_zotero_api_lock` is documented as protecting the single-threaded local API on
port 23119 from concurrent access. That's job one, and it's explicit.

Job two is implicit: wherever the lock happens to be

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/486) · 2026-08-24 · closed · outside contributor · 1 comment

### Windows: server stalls on tool calls — `_sync_semantic_update` imports chromadb before checking config

## Describe the bug

On Windows, after starting the MCP server, **every tool call hangs until the client timeout** (e.g. `-32001 Request timed out` after ~120s). The server never responds to `tools/call`; only `initialize` and `tools/list` work. Each fresh server process reproduces the stall on its first tool call.

## Environment

- OS: Windows 11 x64
- zotero-mcp-server **0.10.0** (installed via `uv tool install 'zotero-mcp-server[all]'`)
- fastmcp 3.4.7 / Python mcp SDK 1.29.0 (server side)
-

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/485) · 2026-08-24 · closed · external user · 6 comments

### CROSSREF_TYPE_MAP covers 13 of CrossRef's 30 types, so add_by_doi silently drops journal, volume, issue and pages for the other 17

`add_by_doi` maps CrossRef's type to a Zotero item type through
`CROSSREF_TYPE_MAP`. Seventeen of CrossRef's thirty published types are not in
the table and fall through to `document`.

That is not a labelling problem. The item is built from a Zotero item template
and only keeps fields the template has, and a `document` template has no
`publicationTitle`, `volume`, `issue` or `pages` — so those values are discarded
on the way in, with nothing reported.

This is the `add_by_doi` sibling of #465, 

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/476) · 2026-08-23 · closed · outside contributor · 0 comments

### zotero_update_item reports a write that dropped fields as "Successfully updated", so an item stuck in the wrong type can never be repaired and nothing says why

`zotero_update_item` skips fields that are not valid for the item's type rather
than writing them, which is right. It then reports the call as a success, with
the skip list appended below the diff. A caller reads the headline and concludes
the write is done.

Reproduced against `main` @ f331646 on 2026-08-23.

## Reproduction

Any item whose type lacks the fields being written. A `webpage` that should be a
`journalArticle` is the case that prompted this — the natural output of
`zotero_add_by_url

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/475) · 2026-08-23 · closed · outside contributor · 0 comments

### zotero_add_by_url never reads a publisher page's embedded citation, so an article landing page becomes a webpage item whose only field is the URL

Adding a journal article's landing page produces a `webpage` item with no title,
no authors and no journal — its only populated field is the URL. The metadata is
on the page, in the same Highwire `citation_*` tags Zotero's own browser
connector reads.

Reproduced against `main` @ f331646 on 2026-08-23.

## Reproduction

```python
from unittest.mock import patch
from zotero_mcp.tools import write

URL = "https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0287795"
write.add_by_url(u

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/474) · 2026-08-23 · closed · outside contributor · 0 comments

### zotero_get_item_metadata(format="bibtex") returns an empty string for any item Better BibTeX does not index (trashed items in particular)

`zotero_get_item_metadata` with `format="bibtex"` returns `""` for items it reads
correctly in every other format. The caller gets a successful call and an empty
result, which is indistinguishable from "this item has no BibTeX" and from "this
item does not exist".

Reproduced against `main` @ f331646 on 2026-08-23, against a live 15k-item
library.

## Reproduction

Any item Better BibTeX does not index. A **trashed** item is the reliable case —
a deduplicated duplicate, for instance, which stays

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/473) · 2026-08-23 · closed · outside contributor · 0 comments

### Implement local write support

The Zotero API now supports [local write](https://www.zotero.org/support/dev/web_api/v3/local_api#write_requests).

It should be implemented in this MCP server and the remote web server removed since it has now lost is purpose

[Read the thread](https://github.com/54yyyu/zotero-mcp/issues/471) · 2026-08-22 · open · outside contributor · 1 comment

The remaining reports are on [the project's issue tracker](https://github.com/54yyyu/zotero-mcp/issues).