Find the passages in your PDFs that mean what you are looking for — not just the ones that contain your keywords.
Paste a paragraph from your draft and get back the pages of your library that support it, ranked by how close they are in meaning — in any language, straight inside Zotero. It also works for your AI assistant, through a built-in MCP server.

Keyword search only finds the words you type. If your source says "deep learning models cannot be inspected" and you search for "opacity of neural networks", it finds nothing.
Semantic search compares meanings. Every passage of every PDF in your library is turned into a vector that captures what it says, and your query is compared against all of them. You get relevant passages even when they use different words, or a different language.
.xpi from the latest release. In Zotero go to Tools → Plugins, click the gear icon, choose Install Plugin From File… and select the file.| Action | What it does |
|---|---|
| Open PDF (p. N) | Opens the PDF in Zotero's reader at the passage's page and searches for the passage |
| Show in library | Selects the item in the main Zotero window |
| Copy citation | Copies a formatted citation in your Quick Copy style, with the page |
| Copy prompt | Copies a ready-made prompt asking an LLM how the passage supports your text |
| To review / Cited / Irrelevant | Marks the passage; marks are saved with the search |
| Type filter | Keeps only the selected item types; nothing selected = everything |
| Group by document | Shows one card per document, with all its matching passages |
| Save as collection | Creates a Zotero collection with the items in the results |
| Copy list | Copies the list of documents, with pages and scores |
| Exclude document | Removes a document from the index (you can include it again later) |

The item pane has a Semantic Search section. It shows whether the selected PDF is indexed and which documents in your library are most similar to it, and lets you index, re-index or exclude it. The same actions are in the item context menu, together with Find Similar Documents and Search Passages Like This Abstract.

The plugin includes a Model Context Protocol server, so an AI assistant on your computer can search your library, read the passages and cite them properly. Zotero must be running.
Claude Code
claude mcp add --scope user --transport http zotero http://127.0.0.1:23119/semantic-search/mcp
Claude Desktop (claude_desktop_config.json, via mcp-remote)
{
"mcpServers": {
"zotero": { "command": "npx", "args": ["-y", "mcp-remote", "http://127.0.0.1:23119/semantic-search/mcp"] }
}
}
Any other MCP client can use the same URL (Streamable HTTP transport). The exact snippets are also shown in the plugin's preferences.
Then just ask, for example:
"Find sources in my Zotero library that support this paragraph, and give me the citations with page numbers."
"Which books in my library discuss the explainability of machine learning models? Quote the most relevant passages."
| Tool | Description |
|---|---|
semantic_search | Passages closest in meaning to a query, with item metadata, item type, page and text. Optional filters: min_similarity, item_types, group_by_item |
get_passage | The text around a result, for more context |
get_item | Full bibliographic data and a formatted citation |
find_similar_items | Documents most similar to a given one |
index_status | Size and state of the index |
list_saved_searches | Your saved searches |
Searches made through MCP do not end up in your search history. The endpoint only accepts local, non-browser connections and can be turned off in the preferences.
PDFs that have no text layer (typically scans) cannot be searched, so they are listed under Excluded documents with the reason no text. Click Run OCR there, or in the item pane. A terminal window opens and runs ocrmypdf; when it finishes, the PDF is replaced in place by its OCRed version and indexed automatically.
ocrmypdf must be installed (brew install ocrmypdf on macOS; see its docs for Windows and Linux). OCR languages are set in the preferences (tesseract codes, default ita+eng).
Zotero → Settings → Semantic Search
Everything happens on your computer: text extraction, embeddings, search and the MCP server. The only network requests are:
Where is the index stored?
In file_embeddings.db, next to zotero.sqlite in your Zotero data directory. The model and a small cache live in your Zotero profile. If you sync your data directory (e.g. with Dropbox), the index goes with it.
Why is one of my PDFs not in the results? Look at the item pane or at Excluded documents. PDFs without text (scans) can be fixed with Run OCR; encrypted PDFs cannot be read.
What model does it use? LEALLA-large, a compact multilingual sentence encoder from Google (109 languages). It runs inside Zotero via WebAssembly, with no Python, server or GPU needed.
I used the original Python version of this project. Do I lose my index?
No. The plugin reads the existing file_embeddings.db as is, including the saved searches and excluded documents, and only indexes PDFs added since.
npm test # unit tests (tokenizer and encoder vs. the reference model, chunker, MCP, scan kernel)
node scripts/build.mjs # build build/zotero-semantic-search-<version>.xpi
node scripts/build.mjs --wasm # also rebuild the WebAssembly encoder (Rust, wasm32-unknown-unknown)
addon/ is the plugin: content/lib/ holds the services (indexing, vector index, search, MCP), content/ui/ the windows, locale/ the English and Italian strings.wasm/ is the LEALLA-large forward pass and the int8 vector scan in Rust, compiled to WebAssembly SIMD.tools/ has the scripts used to check the encoder against the original TensorFlow model..model/model.safetensors and .model/vocab.txt (or MODEL_DIR).semantic-search@ildon.github.io, containing the absolute path of addon/, in your Zotero profile's extensions/ folder.Releasing: push a tag vX.Y.Z on a commit of master. The Release workflow runs the tests, builds the XPI with that version and publishes a GitHub release with the XPI and updates.json, from which installed copies update themselves.
git tag v2.3.0 && git push origin v2.3.0
96 commits
JavaScript
78.9%
Rust
6.9%
Fluent
5.9%
CSS
4.3%
HTML
2.7%
Python
1.2%
Find the passages in your PDFs that mean what you are looking for — not just the ones that contain your keywords.
Paste a paragraph from your draft and get back the pages of your library that support it, ranked by how close they are in meaning — in any language, straight inside Zotero. It also works for your AI assistant, through a built-in MCP server.

Keyword search only finds the words you type. If your source says "deep learning models cannot be inspected" and you search for "opacity of neural networks", it finds nothing.
Semantic search compares meanings. Every passage of every PDF in your library is turned into a vector that captures what it says, and your query is compared against all of them. You get relevant passages even when they use different words, or a different language.
.xpi from the latest release. In Zotero go to Tools → Plugins, click the gear icon, choose Install Plugin From File… and select the file.| Action | What it does |
|---|---|
| Open PDF (p. N) | Opens the PDF in Zotero's reader at the passage's page and searches for the passage |
| Show in library | Selects the item in the main Zotero window |
| Copy citation | Copies a formatted citation in your Quick Copy style, with the page |
| Copy prompt | Copies a ready-made prompt asking an LLM how the passage supports your text |
| To review / Cited / Irrelevant | Marks the passage; marks are saved with the search |
| Type filter | Keeps only the selected item types; nothing selected = everything |
| Group by document | Shows one card per document, with all its matching passages |
| Save as collection | Creates a Zotero collection with the items in the results |
| Copy list | Copies the list of documents, with pages and scores |
| Exclude document | Removes a document from the index (you can include it again later) |

The item pane has a Semantic Search section. It shows whether the selected PDF is indexed and which documents in your library are most similar to it, and lets you index, re-index or exclude it. The same actions are in the item context menu, together with Find Similar Documents and Search Passages Like This Abstract.

The plugin includes a Model Context Protocol server, so an AI assistant on your computer can search your library, read the passages and cite them properly. Zotero must be running.
Claude Code
claude mcp add --scope user --transport http zotero http://127.0.0.1:23119/semantic-search/mcp
Claude Desktop (claude_desktop_config.json, via mcp-remote)
{
"mcpServers": {
"zotero": { "command": "npx", "args": ["-y", "mcp-remote", "http://127.0.0.1:23119/semantic-search/mcp"] }
}
}
Any other MCP client can use the same URL (Streamable HTTP transport). The exact snippets are also shown in the plugin's preferences.
Then just ask, for example:
"Find sources in my Zotero library that support this paragraph, and give me the citations with page numbers."
"Which books in my library discuss the explainability of machine learning models? Quote the most relevant passages."
| Tool | Description |
|---|---|
semantic_search | Passages closest in meaning to a query, with item metadata, item type, page and text. Optional filters: min_similarity, item_types, group_by_item |
get_passage | The text around a result, for more context |
get_item | Full bibliographic data and a formatted citation |
find_similar_items | Documents most similar to a given one |
index_status | Size and state of the index |
list_saved_searches | Your saved searches |
Searches made through MCP do not end up in your search history. The endpoint only accepts local, non-browser connections and can be turned off in the preferences.
PDFs that have no text layer (typically scans) cannot be searched, so they are listed under Excluded documents with the reason no text. Click Run OCR there, or in the item pane. A terminal window opens and runs ocrmypdf; when it finishes, the PDF is replaced in place by its OCRed version and indexed automatically.
ocrmypdf must be installed (brew install ocrmypdf on macOS; see its docs for Windows and Linux). OCR languages are set in the preferences (tesseract codes, default ita+eng).
Zotero → Settings → Semantic Search
Everything happens on your computer: text extraction, embeddings, search and the MCP server. The only network requests are:
Where is the index stored?
In file_embeddings.db, next to zotero.sqlite in your Zotero data directory. The model and a small cache live in your Zotero profile. If you sync your data directory (e.g. with Dropbox), the index goes with it.
Why is one of my PDFs not in the results? Look at the item pane or at Excluded documents. PDFs without text (scans) can be fixed with Run OCR; encrypted PDFs cannot be read.
What model does it use? LEALLA-large, a compact multilingual sentence encoder from Google (109 languages). It runs inside Zotero via WebAssembly, with no Python, server or GPU needed.
I used the original Python version of this project. Do I lose my index?
No. The plugin reads the existing file_embeddings.db as is, including the saved searches and excluded documents, and only indexes PDFs added since.
npm test # unit tests (tokenizer and encoder vs. the reference model, chunker, MCP, scan kernel)
node scripts/build.mjs # build build/zotero-semantic-search-<version>.xpi
node scripts/build.mjs --wasm # also rebuild the WebAssembly encoder (Rust, wasm32-unknown-unknown)
addon/ is the plugin: content/lib/ holds the services (indexing, vector index, search, MCP), content/ui/ the windows, locale/ the English and Italian strings.wasm/ is the LEALLA-large forward pass and the int8 vector scan in Rust, compiled to WebAssembly SIMD.tools/ has the scripts used to check the encoder against the original TensorFlow model..model/model.safetensors and .model/vocab.txt (or MODEL_DIR).semantic-search@ildon.github.io, containing the absolute path of addon/, in your Zotero profile's extensions/ folder.Releasing: push a tag vX.Y.Z on a commit of master. The Release workflow runs the tests, builds the XPI with that version and publishes a GitHub release with the XPI and updates.json, from which installed copies update themselves.
git tag v2.3.0 && git push origin v2.3.0
96 commits
JavaScript
78.9%
Rust
6.9%
Fluent
5.9%
CSS
4.3%
HTML
2.7%
Python
1.2%