# principia-mcp
MCP server that gives Claude access to your local Zotero library. Claude discovers papers via metadata search, then reads PDFs directly.
## How It Works
```
You: "What does Mannheim say about conformal gravity?"
│
▼
Claude: search_papers("conformal gravity", collection="mannheim")
│
▼
MCP returns: [{id: 212, title: "Making the Case...", pdf_path: "/home/.../paper.pdf"}]
│
▼
Claude: Read("/home/.../paper.pdf") ← Claude sees equations visually
│
▼
Claude: "Mannheim argues that conformal gravity can explain galaxy rotation curves..."
```
No embeddings, no text extraction. Claude reads PDFs natively.
## Installation
```bash
git clone https://github.com/phelps-matthew/principia-mcp
cd principia-mcp
uv sync
```
## Configure Claude Code
Add the MCP server (user-wide):
```bash
claude mcp add principia -s user -- uv run --directory /path/to/principia-mcp principia-mcp
```
Or for just one project:
```bash
claude mcp add principia -s project -- uv run --directory /path/to/principia-mcp principia-mcp
```
Verify with `claude mcp list` or `/mcp` in a new session.
## MCP Tools
| Tool | Description |
|------|-------------|
| `list_collections()` | List Zotero collections with paper counts |
| `list_papers(collection?, limit?)` | Browse papers in library or collection |
| `search_papers(query, collection?, limit?)` | Keyword search on title/abstract |
| `get_paper(paper_id)` | Get metadata + PDF path for a paper |
## Zotero Integration
Reads directly from `~/Zotero/`:
- `zotero.sqlite` - metadata database
- `storage/[key]/` - PDF files
No export needed. Add a paper to Zotero and it's available immediately.
Set `ZOTERO_DIR` environment variable if your Zotero data is elsewhere.
## Development
```bash
uv sync # Install dependencies
uv run pytest # Run tests
uv run principia-mcp # Run server
uv run mcp dev src/principia_mcp/server.py # Dev/debug mode
```
## Project Structure
```
src/principia_mcp/
├── server.py # FastMCP server, tool definitions
├── models.py # Pydantic models (Paper, Collection)
├── zotero.py # ZoteroReader - reads Zotero SQLite DB
└── search.py # FTS5 index for fast search (optional)
```