Zotero MCP Server
by swairshah
- scripts
#!/usr/bin/env python3
"""
Simple script to query Zotero API directly.
Run with: python zotero_query.py "your search query"
"""
import os
import sys
from io import BytesIO
from dotenv import load_dotenv
from pyzotero import zotero
from pypdf import PdfReader
def get_pdf_content(zot, item_key: str) -> tuple:
"""Get the PDF content for a given item.
Returns (success, content, attachment_key)
"""
try:
# First get the item to find its attachments
item = zot.item(item_key)
# Look for PDF attachment in the links
if 'attachment' in item['links'] and item['links']['attachment']['attachmentType'] == 'application/pdf':
attachment_key = item['links']['attachment']['href'].split('/')[-1]
# Get the PDF content
pdf_content = zot.file(attachment_key)
return True, pdf_content, attachment_key
# If not found in links, check children
children = zot.children(item_key)
for child in children:
if child['data'].get('itemType') == 'attachment' and child['data'].get('contentType') == 'application/pdf':
pdf_content = zot.file(child['key'])
return True, pdf_content, child['key']
return False, None, None
except Exception as e:
print(f"Error getting PDF content: {e}")
return False, None, None
def main():
load_dotenv()
if not os.environ.get("ZOTERO_API_KEY") or not os.environ.get("ZOTERO_USER_ID"):
print("Error: ZOTERO_API_KEY and ZOTERO_USER_ID must be set in .env file")
sys.exit(1)
try:
zot = zotero.Zotero(
os.environ['ZOTERO_USER_ID'],
"user",
os.environ['ZOTERO_API_KEY'],
local=True
)
# Test the connection
zot.items(limit=1)
except Exception as e:
if "Local API is not enabled" in str(e):
print("Zotero local API is not enabled. Please enable it in Zotero Preferences -> Advanced -> Allow other applications on this computer to communicate with Zotero.")
sys.exit(1)
else:
print(f"Error connecting to Zotero: {e}")
sys.exit(1)
query = sys.argv[1] if len(sys.argv) > 1 else "machine learning"
items = zot.items(q=query)
print(f"\nFound {len(items)} items matching query '{query}':")
for item in items:
data = item['data']
title = data.get('title', 'No title')
key = data.get('key')
# Check for PDF
has_pdf, _, attachment_key = get_pdf_content(zot, key)
pdf_status = f"[PDF: {attachment_key}]" if has_pdf else "[No PDF]"
if has_pdf:
pdf_content = zot.file(attachment_key)
try:
# Try to decode as UTF-8 text first
reader = PdfReader(BytesIO(pdf_content))
# print(reader.pages[0].extract_text()[:1000])
print(reader.pages[0].extract_text())
for page in reader.pages:
print(page.extract_text())
except Exception as e:
# If decoding fails, show hex representation
print(f"Error decoding PDF content: {e}")
print("\nPDF Content (hex, first 100 bytes):")
print(pdf_content[:100].hex())
print(f"\n{pdf_status} {title}")
print(f"Key: {key}")
if data.get('abstractNote'):
print(f"Abstract: {data['abstractNote'][:200]}...")
print(data)
print("-" * 80)
if __name__ == "__main__":
main()