This server turns your AI assistant into a Zotero plugin development partner by exposing the Firefox Remote Debugging Protocol and local build tools. It gives Claude or Cursor access to 26 operations including taking screenshots of Zotero windows, executing privileged JavaScript in the app context, inspecting DOM trees, streaming debug logs, and hot reloading plugins. You can query the SQLite database read-only, explore Zotero's internal APIs with object inspection, and integrate directly with zotero-plugin-scaffold for building and serving. Requires the lightweight MCP Bridge plugin installed in Zotero 7+ to enable RDP on port 6100. Useful when you're building or debugging Zotero extensions and want your AI to see what's actually happening in the running application.
Give your AI assistant superpowers for Zotero plugin development
Architecture · Getting Started · Available Tools
A Model Context Protocol (MCP) server that enables AI assistants like Claude, Cursor, and Windsurf to build, test, and debug Zotero 7, 8, and 9 plugins. Screenshots, DOM state, debug logs, and JavaScript execution give the AI rich context to understand what's happening—and tools to help you fix it.
| Category | Capabilities |
|---|---|
| 🎯 UI Inspection | Screenshots, DOM tree, element finding, computed styles |
| 🖱️ UI Interaction | Click elements and type text (shadow-DOM aware) |
| 💻 JS Execution | Run code in Zotero context, inspect APIs, test snippets |
| 🔧 Build Tools | Scaffold integration for build, serve, hot reload |
| 📋 Logs & Errors | Stream debug output, error console, watch for issues |
| 🗃️ Database | Read-only access to zotero.sqlite for debugging |
| 🔌 Plugin Management | Install, reload, list plugins |
Use install-mcp to add the server to your AI assistant:
npx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code
Supported clients: claude-code, cursor, windsurf, vscode, cline, roo-cline, claude, zed, goose, warp, codex
npx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code
npx -y install-mcp @introfini/mcp-server-zotero-dev --client cursor
npx -y install-mcp @introfini/mcp-server-zotero-dev --client vscode
npx -y install-mcp @introfini/mcp-server-zotero-dev --client windsurf
Add to your MCP client config:
{
"mcpServers": {
"zotero-dev": {
"command": "npx",
"args": ["-y", "@introfini/mcp-server-zotero-dev@1.1.1"],
"env": {
"ZOTERO_RDP_PORT": "6100"
}
}
}
}
Version & updates: pin an exact version as shown above. A bare
npx <pkg>(no version) keeps running whatevernpxcached and won't pick up new releases, so always include a version and-y(without-y,npxhangs waiting for an install prompt). Bump the pinned version to upgrade, or use@latestto always fetch the newest at launch (auto-updates, but a bad release would run automatically and it adds a registry check on every start). Note thatinstall-mcpmay write a config without-yor a version, so the manual configuration above is the most robust path.
Restart your AI assistant after adding the configuration.
Download zotero-mcp-bridge.xpi and install:
.xpi fileThis lightweight plugin enables the Remote Debugging Protocol when Zotero starts. It only needs to be installed once and works on all Zotero 7+ builds (release, beta, and dev).
Just open Zotero normally and ask your AI assistant:
"Take a screenshot of Zotero and list installed plugins"
That's it! No special launch flags, no configuration. 🎉
| Tool | Description |
|---|---|
zotero_screenshot | Capture window, element, or region screenshots |
zotero_inspect_element | Find elements by CSS selector |
zotero_get_dom_tree | Get DOM structure of a window/panel |
zotero_get_styles | Get computed CSS styles for element |
zotero_list_windows | List all open Zotero windows |
Screenshot Targets: Main window, preferences, PDF reader, dialogs, or any element by selector. Use
highlightSelectorto add a red border before capture.
| Tool | Description |
|---|---|
zotero_click_element | Click an element by CSS selector (toolbar/menu button, preference control, list row). Pierces shadow DOM; index picks among multiple matches; mouseEvents synthesizes a full mouse sequence. |
zotero_send_keys | Type text into an input/textarea/contenteditable (focuses it first, fires input/change). Optional clear and pressEnter. |
Resolution tries light DOM first, then pierces open shadow roots (Zotero's XUL custom elements keep internals in shadow DOM). Limitation: cannot dismiss a blocking native modal dialog (
Services.prompt.confirmEx) — its nested modal loop blocks the eval thread these tools run on.
| Tool | Description |
|---|---|
zotero_execute_js | Execute JavaScript in Zotero's privileged context. Auto-wraps code with top-level return statements in IIFE. |
zotero_inspect_object | Explore Zotero APIs - list methods and properties of any object (e.g., Zotero.Items) |
zotero_open_preferences | Open Zotero's settings window, optionally to a specific pane (built-in or plugin) |
zotero_search_prefs | Search/discover preferences by pattern (e.g., find all prefs containing "debug") |
zotero_get_pref | Get a preference value |
zotero_set_pref | Set a preference value |
Examples:
Zotero.Items.getAll(1),Zotero.Prefs.get('export.quickCopy.setting'),ZoteroPane.getSelectedItems()Tip: Use
zotero_inspect_objectto explore APIs before writing code. Usezotero_search_prefsto discover preference keys.
| Tool | Description |
|---|---|
zotero_scaffold_build | Build plugin (dev or production mode) |
zotero_scaffold_serve | Start dev server with hot reload |
zotero_scaffold_lint | Run ESLint on plugin source |
zotero_scaffold_typecheck | Run TypeScript type checking |
| Tool | Description |
|---|---|
zotero_read_logs | Read debug output (Zotero.debug) |
zotero_read_errors | Read error console entries |
zotero_watch_logs | Stream logs in real-time |
zotero_clear_logs | Clear log buffer |
| Tool | Description |
|---|---|
zotero_plugin_reload | Hot reload your dev plugin |
zotero_plugin_install | Install plugin from XPI path |
zotero_plugin_list | List installed plugins with version/status |
| Tool | Description |
|---|---|
zotero_db_query | Execute SELECT query on zotero.sqlite |
zotero_db_schema | Get table schema information |
zotero_db_stats | Get database statistics (items, attachments, collections, size) |
Note: Database access is read-only and requires Zotero to be closed, or uses a copy of the database.
┌─────────────────────────────────────────────────────────────────┐
│ AI Assistant │
│ (Claude, Cursor, Windsurf) │
└─────────────────────────┬───────────────────────────────────────┘
│ MCP Protocol (stdio)
▼
┌─────────────────────────────────────────────────────────────────┐
│ MCP Server (Node.js/TypeScript) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────────────┐ │
│ │ Scaffold │ │ RDP │ │ Database │ │
│ │ Integration │ │ Client │ │ Reader │ │
│ └──────────────┘ └──────┬───────┘ └──────────────────────┘ │
└─────────────────────────────┼───────────────────────────────────┘
│ Firefox RDP (port 6100)
▼
┌─────────────────────────────────────────────────────────────────┐
│ Zotero Application │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ MCP Bridge for Zotero │ │
│ │ Starts DevToolsServer on launch │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Firefox DevTools Server (built-in) │ │
│ │ JS Execution • DOM • Console • Screenshots │ │
│ └──────────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Your Plugin (dev) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
Why this approach?
| Variable | Description | Default |
|---|---|---|
ZOTERO_RDP_PORT | Remote debugging port | 6100 |
ZOTERO_RDP_HOST | Debugging host | 127.0.0.1 |
ZOTERO_DATA_DIR | Path to Zotero data directory | Auto-detect |
ZOTERO_PROFILE_PATH | Path to Zotero profile | Auto-detect |
// Capture main Zotero window
await zotero_screenshot({ target: 'main-window' });
// Capture your plugin's panel with highlight
await zotero_screenshot({
target: 'element',
selector: '#my-plugin-panel',
highlightSelector: '#my-plugin-button'
});
// Capture a specific window by ID (use zotero_list_windows to find IDs)
await zotero_screenshot({
target: 'window',
windowId: 12345
});
// Capture element after triggering UI action
await zotero_execute_js({ code: 'document.querySelector("#menu").click()' });
await zotero_screenshot({ target: 'element', selector: 'menupopup[state="open"]' });
# Clone and install
git clone https://github.com/introfini/mcp-server-zotero-dev.git
cd mcp-server-zotero-dev
npm install
# Build everything
npm run build
# Build individual packages
npm run build:server
npm run build:plugin
# Run tests
npm test
# Development mode (watch)
npm run dev
mcp-server-zotero-dev/
├── packages/
│ ├── mcp-server/ # MCP server (npm package)
│ │ ├── src/
│ │ │ ├── index.ts # MCP server entry
│ │ │ ├── rdp/ # RDP client
│ │ │ ├── tools/ # Tool implementations
│ │ │ └── prompts/ # Slash commands
│ │ └── package.json
│ │
│ └── zotero-plugin-mcp-rdp/ # Tiny Zotero plugin (.xpi)
│ ├── src/
│ │ └── index.ts # Starts RDP server
│ ├── addon/
│ │ └── manifest.json
│ └── package.json
│
├── docs/ # Documentation
└── package.json # Monorepo root
Contributions are welcome! Please:
npm test and npm run lint passMIT © introfini
ZOTERO_RDP_PORTRDP port for Zotero connection
ZOTERO_RDP_HOSTRDP host for Zotero connection
csoai-org/pdf-document-mcp
xt765/mcp-document-converter
io.github.xjtlumedia/markdown-formatter
io.github.ai-aviate/better-notion
suekou/mcp-notion-server
meterlong/mcp-doc