Metadata-Version: 2.4
Name: zotero-curator
Version: 0.1.1
Summary: Research-focused MCP server and setup helper for Zotero
Project-URL: Repository, https://github.com/JGSphaela/Curator-for-Zotero
Project-URL: Issues, https://github.com/JGSphaela/Curator-for-Zotero/issues
Project-URL: Upstream, https://github.com/kujenga/zotero-mcp
Author: Sphaela / JGSphaela contributors
Maintainer: Sphaela / JGSphaela contributors
License: MIT License
        
        Original work:
        Copyright (c) 2025 Aaron Taylor
        
        Modifications and continued development:
        Copyright (c) 2026 Sphaela / JGSphaela contributors
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: citations,llm,mcp,research,zotero
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.11
Requires-Dist: mcp[cli]>=1.2.1
Requires-Dist: platformdirs>=4.3.6
Requires-Dist: pydantic>=2.10.6
Requires-Dist: python-dotenv>=1.0.1
Requires-Dist: pyzotero>=1.6.8
Provides-Extra: all
Requires-Dist: chromadb>=0.5.0; extra == 'all'
Requires-Dist: pymupdf>=1.24.0; extra == 'all'
Requires-Dist: sentence-transformers>=3.0.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
Requires-Dist: pytest>=8.3.4; extra == 'dev'
Requires-Dist: ruff>=0.9.4; extra == 'dev'
Provides-Extra: pdf
Requires-Dist: pymupdf>=1.24.0; extra == 'pdf'
Provides-Extra: semantic
Requires-Dist: chromadb>=0.5.0; extra == 'semantic'
Requires-Dist: sentence-transformers>=3.0.0; extra == 'semantic'
Description-Content-Type: text/markdown

# Curator for Zotero

Curator for Zotero is a research-focused MCP server for Zotero. It lets AI coding and research assistants search your library, inspect metadata, read indexed attachment text in manageable chunks, navigate outlines/sections, and safely organize items with dry-run-first write tools.

This project is independently maintained and is based on the MIT-licensed [`kujenga/zotero-mcp`](https://github.com/kujenga/zotero-mcp). See [ACKNOWLEDGEMENTS.md](ACKNOWLEDGEMENTS.md) and [LICENSE](LICENSE).

## Why this repo exists

The original Python MCP server was useful but awkward to configure across Codex, Claude Desktop, Cursor, Claude Code, and other clients because each app needed a hand-maintained virtualenv path. Curator fixes that by making the server a normal published Python tool that clients can launch with `uvx`:

```bash
uvx --from zotero-curator zotero-curator serve
```

That command lets each MCP client start its own stdio server process without knowing about a local checkout path, a repo-local `.venv`, or per-app shell setup.

## Recommended install: `uvx`

Install [`uv`](https://docs.astral.sh/uv/) once, then configure Curator through the published package:

```bash
uvx --from zotero-curator zotero-curator setup --local
uvx --from zotero-curator zotero-curator doctor
```

`uvx` keeps Python environments out of Claude/Codex/Cursor config files. It resolves and caches the published `zotero-curator` package, then runs the requested console command.

For GUI-launched clients on macOS, prefer the absolute `uvx` path from:

```bash
command -v uvx
```

Common Homebrew paths are `/opt/homebrew/bin/uvx` on Apple Silicon and `/usr/local/bin/uvx` on Intel macOS.

Optional persistent install:

```bash
uv tool install zotero-curator
zotero-curator setup --local
zotero-curator doctor
```

## Let an agent set it up

Copy this prompt into Codex, Claude Code, Cursor, or another local coding agent:

```text
Install Curator for Zotero for me by following this repo's AGENTS.md. Use the published uvx workflow and configure these MCP clients: CLIENTS_TO_CONFIGURE.
```

Replace `CLIENTS_TO_CONFIGURE` with the clients you use, for example `Claude Desktop and Codex`.

From a local checkout:

```bash
uv sync --extra dev
uv run zotero-curator doctor
uv run pytest
uv run ruff check .
```

## Zotero local API setup

1. Open Zotero.
2. Go to Settings → Advanced → Allow other applications on this computer to communicate with Zotero.
3. Run:

```bash
uvx --from zotero-curator zotero-curator setup --local
uvx --from zotero-curator zotero-curator doctor
```

Local mode uses library id `0` and does not require an API key.

## Web API setup

```bash
uvx --from zotero-curator zotero-curator setup --web --library-id YOUR_LIBRARY_ID --api-key YOUR_API_KEY
```

For group libraries, add `--library-type group`.

## MCP client config

Recommended `uvx` config for Claude Desktop, Cursor, and other JSON-style MCP clients:

```json
{
  "mcpServers": {
    "zotero": {
      "command": "/opt/homebrew/bin/uvx",
      "args": [
        "--from",
        "zotero-curator",
        "zotero-curator",
        "serve"
      ]
    }
  }
}
```

Replace `/opt/homebrew/bin/uvx` with the output of `command -v uvx` on your machine.

Recommended `uvx` config for Codex:

```toml
[mcp_servers.zotero]
type = "stdio"
command = "/opt/homebrew/bin/uvx"
args = ["--from", "zotero-curator", "zotero-curator", "serve"]
startup_timeout_sec = 30
```

If you prefer a pinned release, pin the package in the `--from` argument:

```toml
args = ["--from", "zotero-curator==0.1.0", "zotero-curator", "serve"]
```

Installed-tool fallback:

```json
{
  "mcpServers": {
    "zotero": {
      "command": "zotero-curator",
      "args": ["serve"]
    }
  }
}
```

Generate config snippets:

```bash
uvx --from zotero-curator zotero-curator mcp-config --uvx --format json
uvx --from zotero-curator zotero-curator mcp-config --uvx --format toml
```

Current workflow note: `setup` writes Curator's central Zotero settings and prints client config snippets. `mcp-config` only prints JSON/TOML. Neither command edits Claude, Codex, Cursor, or other client config files yet. A future `install-client` or `client-config apply` command should detect known config paths, back up existing files, merge the `zotero` MCP server entry, support `--dry-run`, and preserve user-managed settings.

Release instructions are in [docs/release.md](docs/release.md). Claude Desktop MCPB bundle notes are in [docs/mcpb.md](docs/mcpb.md).

## Add arXiv papers

Curator can create a Zotero `preprint` item directly from an arXiv id, abstract URL, or PDF URL:

```bash
uvx --from zotero-curator zotero-curator add-arxiv https://arxiv.org/abs/2410.03529
```

The command is dry-run-first. To apply it, configure Web API mode with a write-enabled API key, enable writes globally, and pass `--apply`:

```bash
uvx --from zotero-curator zotero-curator setup --web --library-id YOUR_LIBRARY_ID --api-key YOUR_WRITE_ENABLED_API_KEY --write-enabled
uvx --from zotero-curator zotero-curator add-arxiv 2410.03529 --tag AI --collection COLLECTION_KEY --apply
```

This imports arXiv metadata first and stores the PDF as a Zotero file attachment by default. Use `--link-pdf` to attach only the arXiv PDF URL, `--no-pdf` to create only the metadata item, or `--pdf-mode {stored,linked,none}` for explicit control.

## Settings

Curator stores central settings in the platform config directory. Print the exact path with:

```bash
uvx --from zotero-curator zotero-curator setup-info
```

On macOS this is typically:

```text
~/Library/Application Support/zotero-curator/config.toml
```

On many Linux systems this is typically:

```text
~/.config/zotero-curator/config.toml
```

Example:

```toml
[zotero]
local = true
library_type = "user"
library_id = "0"
write_enabled = false
response_format = "markdown"
```

Environment variables override file settings:

| Variable | Purpose |
| --- | --- |
| `ZOTERO_LOCAL` | `true` for local API, `false` for Web API |
| `ZOTERO_LIBRARY_ID` | Zotero user/group library id |
| `ZOTERO_LIBRARY_TYPE` | `user` or `group` |
| `ZOTERO_API_KEY` | Zotero Web API key |
| `ZOTERO_WRITE_ENABLED` | Enable non-dry-run write tools |
| `ZOTERO_CURATOR_CONFIG` | Override settings file path |
| `ZOTERO_CURATOR_CONFIG_DIR` | Override settings directory |

## Tools

Read/navigation:

- `zotero_healthcheck`
- `zotero_diagnostics`
- `zotero_search_items`
- `zotero_find_item_by_doi`
- `zotero_item_metadata`
- `zotero_item_fulltext`
- `zotero_item_fulltext_info`
- `zotero_pdf_pages` (`pdf` extra)
- `zotero_pdf_outline` (`pdf` extra)
- `zotero_item_text_chunk`
- `zotero_item_search_text`
- `zotero_item_outline`
- `zotero_item_read_section`
- `zotero_item_children`
- `zotero_list_collections`
- `zotero_collection_items`
- `zotero_list_tags`
- `zotero_semantic_rebuild` (`semantic` extra)
- `zotero_semantic_search` (`semantic` extra)

Write/organization tools are dry-run-first and additionally require `write_enabled = true` for real changes:

- `zotero_write_status`
- `zotero_add_arxiv`
- `zotero_create_collection`
- `zotero_rename_collection`
- `zotero_delete_collection`
- `zotero_update_item_tags`
- `zotero_update_item_collections`
- `zotero_update_item_metadata`
- `zotero_create_child_note`
- `zotero_apply_organization_plan`

## Safety model

Write tools default to `dry_run=true`. Real write calls require all of the following:

1. Web API mode: `local = false`.
2. A Zotero API key with write access.
3. `write_enabled = true` in settings, or `ZOTERO_WRITE_ENABLED=true`.
4. The individual tool call sets `dry_run=false`.

The Zotero local API is treated as read-only by Curator because Zotero's Local API v3 documentation says: "Write requests are currently unsupported. Only `GET` is accepted." Local mode can be used for reads and dry-runs, but Curator blocks non-dry-run write tools before they call Zotero. This keeps the implementation aligned with the current API protocol and makes it easy to re-enable local writes later when Zotero adds support.

## Optional extras

The base install stays small. Heavy PDF and semantic dependencies are opt-in. For persistent installs:

```bash
uv tool install 'zotero-curator[pdf]'
uv tool install 'zotero-curator[semantic]'
uv tool install 'zotero-curator[all]'
```

For `uvx`-launched MCP clients, request the extra in the `--from` package:

```bash
uvx --from 'zotero-curator[pdf]' zotero-curator serve
uvx --from 'zotero-curator[semantic]' zotero-curator serve
uvx --from 'zotero-curator[all]' zotero-curator serve
```

From a checkout:

```bash
uv pip install --python .venv/bin/python -e '.[pdf]'
uv pip install --python .venv/bin/python -e '.[semantic]'
```

The `pdf` extra enables page-aware PDF reads and bookmark extraction from stored Zotero attachments. The `semantic` extra stores a local Chroma index under the platform data directory shown by `zotero-curator doctor`; rebuild with `zotero_semantic_rebuild` after major library changes, then search with `zotero_semantic_search`. See [docs/optional-extras.md](docs/optional-extras.md) for storage and rebuild details.

## Runtime diagnostics

Curator writes structured JSONL runtime logs under the platform log directory shown by:

```bash
uvx --from zotero-curator zotero-curator doctor
```

Set `response_format = "json"` in the central settings file, or set `ZOTERO_CURATOR_RESPONSE_FORMAT=json`, to make action-style write responses return structured JSON instead of Markdown. The `zotero_diagnostics` MCP tool reports resolved settings, log paths, and Zotero API reachability.

Batch organization plans include completed/error counts and a per-step report. Automatic rollback is intentionally not attempted; use the report to build and dry-run a corrective plan before applying fixes.

## Development status

Implemented:

- Python package with console scripts: `zotero-curator` and compatibility alias `zotero-mcp`.
- Central settings, diagnostics, and structured runtime logs.
- Client config generation for JSON and TOML MCP clients.
- Read/search/full-text tools.
- Dry-run-first write tools.
- arXiv preprint import from IDs, abstract URLs, and PDF URLs.
- Test and lint configuration.
- CI skeleton.

Next polish:

- Client config apply command that safely injects the recommended `uvx` server entry into Claude/Codex/Cursor configs.
- PyPI trusted publishing and signed GitHub releases.
- Claude Desktop `.mcpb` packaging.
- Optional semantic index and PDF extraction extras.
- Richer structured JSON responses while keeping Markdown defaults.
