pydantic-zotero-mcp
pydantic-zotero-mcp
MCP-сервер, который предоставляет ИИ-агентам доступ на чтение к библиотеке Zotero — поиск, метаданные элементов, коллекции, теги, собственные заметки исследователя и индексированный полный текст прикреплённых PDF-файлов.
Требования см. в PRD.md.
Статус: M1 (чтение ядра) + M2 (полный текст) реализованы. Форматирование цитат и экспорт (M3), промпты (M4) и инструменты записи (M5) ещё не созданы — см. Не реализовано.
Установка
Как инструмент (pipx)
Устанавливает команду zotero-mcp в собственное изолированное окружение:
pipx install pydantic-zotero-mcp # or: pipx install /path/to/checkout
zotero-mcp --helpВ окружение другого проекта
uv add pydantic-zotero-mcp # or: uv pip install pydantic-zotero-mcpДля разработки этого сервера
git clone https://github.com/jmlon/pydantic-zotero-mcp
cd pydantic-zotero-mcp
uv sync # creates ./.venv from this project's own lock file
uv run pytest
uv run ruff checkRelated MCP server: zotero-cli-cc
Настройка
Получите ключ API только для чтения и ваш числовой идентификатор пользователя на https://www.zotero.org/settings/keys. Идентификатор библиотеки — это число, а не ваше имя пользователя.
export ZOTERO_API_KEY=...
export ZOTERO_LIBRARY_ID=123456 # numeric
export ZOTERO_LIBRARY_TYPE=user # or groupПеременная | По умолчанию | Назначение |
| — | Ключ веб-API (обязателен, если не |
| — | Числовой идентификатор пользователя или группы |
|
|
|
|
| Чтение через локальный API Zotero 7: без ключа, без лимитов, только чтение |
|
| Зарезервировано для M5; инструментов записи пока нет |
|
| Потолок полного текста по умолчанию; |
|
| Зарезервировано для M3 |
|
| Лимит одновременных запросов (Zotero просит ≤ 4) |
|
|
|
|
| Адрес привязки HTTP |
|
| HTTP-порт |
|
| Путь монтирования HTTP |
| — | Bearer-токен; обязателен для HTTP |
Флаги CLI переопределяют переменные окружения.
Запуск
После установки zotero-mcp — это точка входа: не нужен путь к интерпретатору, не нужен python -m, не нужно
угадывать рабочую директорию — именно то, что нужно клиенту MCP в command::
# stdio (default) — an agent launches this as a subprocess
zotero-mcp
# streamable HTTP — requires ZOTERO_MCP_AUTH_TOKEN
ZOTERO_MCP_AUTH_TOKEN=secret zotero-mcp --transport http --port 8000
# read the Zotero desktop app instead of the web API
zotero-mcp --localИз клонированного репозитория, без установки, по-прежнему работает python -m zotero_mcp:
uv run python -m zotero_mcpЗапуск с --transport http без токена завершается с кодом 2, а не обслуживает
неаутентифицированные запросы: это канал чтения в личную библиотеку.
В памяти (встроено в процесс агента)
Никаких подпроцессов и сокетов. Настройки внедряются, поэтому хосту не нужны переменные окружения:
from fastmcp import Client
from zotero_mcp import ZoteroSettings, create_server
server = create_server(
ZoteroSettings(
api_key=key,
library_id="123456",
library_type="user",
)
)
async with Client(server) as client: # lifespan opens here
result = await client.call_tool("search_items", {"query": "attention"})
print(result.structured_content["items"]) # dict; result.data is a modelИмпорт zotero_mcp не имеет побочных эффектов — ни чтения конфигурации, ни создания клиента, ни
сетевых операций — именно это делает встраивание возможным. Есть тест, который это проверяет.
Обнаружение через точку входа
Для хост-приложений, которые обнаруживают встроенные MCP-серверы через точки входа Python,
этот пакет объявляет одну в группе deep_research.mcp_servers:
[project.entry-points."deep_research.mcp_servers"]
zotero = "zotero_mcp:build_server"build_server() не принимает аргументов и получает настройки из окружения — установите
этот пакет в окружение хоста, и хост сможет найти и запустить сервер
в процессе по имени zotero, без импорта по пути из конфигурационного файла.
Одно замечание по настройке для автоматизированных хостов: потолок полного текста по умолчанию у этого сервера — 100 000
символов (~25–30 тыс. токенов для одного вызова get_item_fulltext), что щедро для
интерактивного использования и слишком много для агента, делающего множество вызовов в рамках токенного бюджета —
передавайте меньший max_chars в каждом вызове или снизьте ZOTERO_FULLTEXT_MAX_CHARS.
Инструменты
Инструмент | Назначение |
| Размер, режим, права. Дешёвый ориентировочный вызов — используйте первым |
| Основная точка входа. |
| Недавно добавленные элементы, сначала новые |
| «Есть ли у меня уже это?» по DOI, ISBN, arXiv ID или ключу |
| Полные метаданные; |
| Вложения и заметки, с |
| Собственные заметки исследователя, HTML удалён |
| Индексированный текст вложений; разрешение родитель → вложение |
| Вложенное дерево коллекций |
| Элементы в одной коллекции |
| Словарь тегов, опционально с фильтром по префиксу |
Ресурсы: zotero://library/info, zotero://collections,
zotero://items/{key}, zotero://items/{key}/fulltext,
zotero://collections/{key}/items, zotero://schema/item-types,
zotero://schema/item-types/{type}/fields.
Заметки по дизайну
Проекция — это суть. Сырой JSON Zotero — это ~1 КБ на элемент из links, library,
meta и пустых полей типов. zotero_mcp/projection.py сокращает страницу из 25 элементов
с ~6 100 до ~2 400 оценочных токенов (39% от сырого), в пределах бюджета PRD в 4 000. Поля
со значением null отбрасываются при сериализации через CompactModel.
pyzotero синхронен и хранит состояние. Zotero.request и Zotero.links
перезаписываются каждым вызовом, а Total-Results считывается с экземпляра
после — поэтому общий клиент, используемый конкурентно, сообщил бы итоги другого
вызова. gateway.py хранит пул из до ZOTERO_MAX_CONCURRENCY клиентов, выдаёт
по одному на операцию и читает метаданные ответа в том же рабочем потоке, который
удерживает клиент. Каждый вызов проходит через anyio.to_thread.run_sync, поэтому цикл событий
никогда не блокируется.
Backoff — забота pyzotero. pyzotero ≥ 1.13 уже учитывает Backoff /
Retry-After и повторяет 429 внутри, поэтому шлюз не реализует это заново. Он
добавляет ограниченные 3 попытки повтора только для транзиентных транспортных ошибок и ошибок 5xx.
Ничего не обрезается молча. Поиски сообщают total_matched, truncated и
next_start; полный текст сообщает total_chars и truncated.
Результаты — это кандидаты, а не вердикты (PRD D3). find_item_by_identifier возвращает
matched_on (key / doi / title / identifier / none), а также уровень уверенности и
все правдоподобные кандидаты — препринт и его опубликованная версия сохраняются оба. Фильтрует
вызывающая сторона.
Отклонения от PRD
О них стоит знать, поскольку каждое было осознанным решением в ходе реализации:
Нет модульного объекта
mcp. PRD 7.2 требовал и модульныйmcp = create_server(), и отсутствие побочных эффектов при импорте. Это противоречит друг другу: создание сервера проверяет конфигурацию, поэтому модульный экземпляр вызываетImportErrorна любой машине без переменных окружения Zotero и ломает путь встраивания в память, который он должен был поддерживать. Существуют толькоcreate_server()/build_default_server().Инструменты записи будут регистрироваться условно, а не с
enabled=False. PRD 5.5 указывал@mcp.tool(enabled=False), но в FastMCP 3.x нет аргументаenabled, а отключённый, но перечисленный инструмент всё равно занимает контекст. Когда выйдет M5, инструменты записи просто не будут регистрироваться, если толькоZOTERO_ALLOW_WRITES=true.Этот сервер нацелен на FastMCP 3.x. Две особенности 3.x формируют код здесь:
enabledотсутствует в декораторах, аresult.data— это сгенерированная модель pydantic, тогда какresult.structured_content— это обычный словарь; тесты проверяют второе, что также проверяет пропуск null-значений на проводе.has_fulltextтрёхзначный. PRD 6 типизировал его какbool, но определение его для родительского элемента требует отдельного запроса детей для каждого элемента, что сделало бы поиск из 25 элементов 26 запросами. Он равенFalse, когда у элемента вообще нет детей,True/Falseдля вложений и послеget_item(include_children=True), иnull(опущен), когда не определён.ItemSummary.num_childrenдаёт дешёвый сигнал.find_item_by_identifierвозвращаетCitationMatch, а неItemSummary | None. Это следует из D3 — старая сигнатура делала ровно тот запрос на идентичность, который это решение перенесло на клиента.matched_onполучилkeyиidentifierсверх четырёх значений из PRD, чтобы отличать точное совпадение по ключу от слабого совпадения по поиску.list_recent_items(since_days=...)фильтрует локально. У Zotero нет серверного фильтра по дате, поэтому узкое окно может вернуть меньше элементов, чемlimit; в ответеhintсообщает, когда это произошло.
Тесты
uv run pytest # 80 passedНабор использует внутрипроцессный транспорт FastMCP с FakeZotero, который воспроизводит
поведение pyzotero по чтению метаданных с экземпляра. Без сети, без подпроцессов, без
реальных учётных данных. Покрытие: поверхность схемы, проекция и токенный бюджет, пагинация
и отчётность об обрезке, потолок полного текста и разрешение родителя, полнота совпадений
(пары препринт/опубликованная версия возвращаются обе), качество сообщений об ошибках, проверка
шаблонов ресурсов, включая попытки обхода, проверка конфигурации, приоритет CLI, повторные
попытки/кэширование шлюза и проверка чистоты импорта, которая падает, если импорт пакета
касается сети.
Не реализовано
M3 —
format_citation,format_bibliography,export_itemsM4 — четыре промпта (
literature_review,find_related_work,check_citations,summarize_reading), инструментирование LogfireM5 — инструменты записи (
create_item,update_item_fields,add_item_tags,add_items_to_collection,create_note) с семантикой PATCH с проверкой версий. Удаление навсегда вне области действия.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityCmaintenanceA lightweight MCP server that connects AI agents to a local Zotero library for paper management and metadata retrieval. It enables users to search titles and abstracts, browse collections, and automatically ingest papers via arXiv ID or DOI with PDF attachments.815MIT
- AlicenseNot gradedqualityAmaintenanceMCP server that exposes 45 tools for Zotero reference management, enabling AI agents to read/write items, search, extract PDF text, and manage workspaces via the Zotero CLI.198AGPL 3.0
- AlicenseNot gradedqualityAmaintenanceMCP server that lets AI assistants search, create, organize, and cite from a Zotero library.3MIT
- AlicenseNot gradedqualityDmaintenanceMCP server that connects AI assistants to your Zotero library, enabling full-text PDF extraction and metadata search.MIT
Related MCP Connectors
Remote MCP server for full read/write access to a Zotero library
Agentic search over your Dewey document collections from any MCP-compatible client.
An MCP server that gives your AI access to the source code and docs of all public github repos
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/jmlon/pydantic-zotero-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server