PluginBench
MCP Server
Active
MIT

io.github.introfini/mcp-server-zotero-dev MCP Server

io.github.introfini/mcp-server-zotero-dev

AI-powered Zotero plugin development with live screenshots, DOM inspection, and JavaScript execution.

What is the io.github.introfini/mcp-server-zotero-dev MCP server?

The MCP Server Zotero Dev is a Model Context Protocol server that enables AI assistants like Claude and Cursor to build, test, and debug Zotero 7+ plugins. It provides UI inspection, interaction, JavaScript execution, build integration, logging, and database access through a lightweight bridge plugin that enables Firefox Remote Debugging Protocol in Zotero.

This server gives AI assistants rich context into Zotero's state—screenshots, DOM trees, computed styles, debug logs, and error console—plus tools to interact with the UI, execute JavaScript in Zotero's privileged context, manage plugins, and access the database. It integrates with zotero-plugin-scaffold for hot-reload development, making it ideal for rapid plugin iteration with AI assistance.

How to install io.github.introfini/mcp-server-zotero-dev

Copy-paste configuration for popular MCP clients.

transport: stdio
Config generated by PluginBench — verify against the source before use.
Environment / auth
  • ZOTERO_RDP_PORT

    RDP port for Zotero connection

  • ZOTERO_RDP_HOST

    RDP host for Zotero connection

~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "mcp-server-zotero-dev": {
      "command": "npx",
      "args": [
        "-y",
        "@introfini/mcp-server-zotero-dev"
      ],
      "env": {
        "ZOTERO_RDP_PORT": "<YOUR_ZOTERO_RDP_PORT>",
        "ZOTERO_RDP_HOST": "<YOUR_ZOTERO_RDP_HOST>"
      }
    }
  }
}

Tools & capabilities

Tools this server exposes to the agent.

  • zotero_screenshot — Capture window, element, or region screenshots with optional highlighting
  • zotero_inspect_element — Find elements by CSS selector
  • zotero_get_dom_tree — Get DOM structure of a window or panel
  • zotero_get_styles — Get computed CSS styles for an element
  • zotero_list_windows — List all open Zotero windows
  • zotero_click_element — Click an element by CSS selector, with shadow DOM piercing and mouse event synthesis
  • zotero_send_keys — Type text into an input, textarea, or contenteditable element
  • zotero_execute_js — Execute JavaScript in Zotero's privileged context
  • zotero_inspect_object — Explore Zotero APIs by listing methods and properties of objects
  • zotero_open_preferences — Open Zotero's settings window, optionally to a specific pane
  • zotero_search_prefs — Search and discover preferences by pattern
  • zotero_get_pref — Get a preference value
  • zotero_set_pref — Set a preference value
  • zotero_scaffold_build — Build plugin in 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
  • zotero_read_logs — Read debug output from Zotero.debug
  • zotero_read_errors — Read error console entries
  • zotero_watch_logs — Stream logs in real-time

Use cases

  • Build and debug Zotero plugins with AI assistance using live screenshots and DOM inspection
  • Execute JavaScript snippets in Zotero's context to test APIs and explore the Zotero object model
  • Hot-reload plugins during development with integrated build and serve tools
  • Inspect and modify Zotero preferences and settings through the preferences API
  • Query the Zotero database to understand data structure and debug data-related issues

io.github.introfini/mcp-server-zotero-dev MCP server FAQ

What is the MCP Server Zotero Dev?

It's a Model Context Protocol server that connects AI assistants (Claude, Cursor, Windsurf) to Zotero, enabling them to build, test, and debug Zotero plugins. It provides UI inspection, JavaScript execution, build integration, and database access through a lightweight bridge plugin.

Is it free?

Yes, the MCP Server Zotero Dev is open-source under the MIT license and free to use.

How do I install it in Cursor or Claude?

Use `npx -y install-mcp @introfini/mcp-server-zotero-dev --client cursor` (or `claude-code` for Claude Code). Then install the zotero-mcp-bridge.xpi plugin in Zotero via Tools → Plugins, and restart Zotero.

What versions of Zotero does it support?

It works with Zotero 7, 8, 9, and 10 on all builds (release, beta, and dev).

Do I need any authentication or API keys?

No authentication is required. The server communicates with Zotero via Firefox Remote Debugging Protocol on localhost (port 6100 by default), which requires only the bridge plugin to be installed in Zotero.

Can I change the RDP port if 6100 is already in use?

Yes. Set `extensions.mcp-rdp.port` to your desired port in Zotero's Config Editor (Settings → Advanced), and set the same port in the `ZOTERO_RDP_PORT` environment variable in your MCP client config. Both must match.

README (reference)

Source of truth, from the repository.

<div align="center">

MCP Server Zotero Dev

Give your AI assistant superpowers for Zotero plugin development

License: MIT Zotero 7+

Architecture · Getting Started · Available Tools

<img src="docs/images/demo.png" alt="MCP Server Zotero Dev in action" width="800"> </div>

A Model Context Protocol (MCP) server that enables AI assistants like Claude, Cursor, and Windsurf to build, test, and debug Zotero 7, 8, 9, and 10 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.

✨ Features

CategoryCapabilities
🎯 UI InspectionScreenshots, DOM tree, element finding, computed styles
🖱️ UI InteractionClick elements and type text (shadow-DOM aware)
💻 JS ExecutionRun code in Zotero context, inspect APIs, test snippets
🔧 Build ToolsScaffold integration for build, serve, hot reload
📋 Logs & ErrorsStream debug output, error console, watch for issues
🗃️ DatabaseRead-only access to zotero.sqlite for debugging
🔌 Plugin ManagementInstall, reload, list plugins

🚀 Quick Start

Prerequisites

  • Node.js 20+ and npm
  • Zotero 7+ — Works on all Zotero 7, 8, 9, and 10 builds (release, beta, dev)
  • For plugin development: zotero-plugin-scaffold

1. Install MCP Server

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

<details> <summary><strong>Claude Code</strong></summary>
npx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code
</details> <details> <summary><strong>Cursor</strong></summary>
npx -y install-mcp @introfini/mcp-server-zotero-dev --client cursor
</details> <details> <summary><strong>VS Code / Copilot</strong></summary>
npx -y install-mcp @introfini/mcp-server-zotero-dev --client vscode
</details> <details> <summary><strong>Windsurf</strong></summary>
npx -y install-mcp @introfini/mcp-server-zotero-dev --client windsurf
</details> <details> <summary><strong>Manual Configuration</strong></summary>

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"
      }
    }
  }
}
</details>

Version & updates: pin an exact version as shown above. A bare npx <pkg> (no version) keeps running whatever npx cached and won't pick up new releases, so always include a version and -y (without -y, npx hangs waiting for an install prompt). Bump the pinned version to upgrade, or use @latest to 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 that install-mcp may write a config without -y or a version, so the manual configuration above is the most robust path.

Restart your AI assistant after adding the configuration.

2. Install MCP Bridge Plugin in Zotero

Download zotero-mcp-bridge.xpi and install:

  1. In Zotero: Tools → Plugins
  2. Click ⚙️ → Install Plugin From File
  3. Select the downloaded .xpi file
  4. Restart Zotero

This 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).

3. Start Developing!

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. 🎉


🧰 Available Tools (28 total)

<details> <summary><strong>UI Inspection</strong> — Screenshots, DOM, styles</summary>
ToolDescription
zotero_screenshotCapture window, element, or region screenshots
zotero_inspect_elementFind elements by CSS selector
zotero_get_dom_treeGet DOM structure of a window/panel
zotero_get_stylesGet computed CSS styles for element
zotero_list_windowsList all open Zotero windows

Screenshot Targets: Main window, preferences, PDF reader, dialogs, or any element by selector. Use highlightSelector to add a red border before capture.

</details> <details> <summary><strong>UI Interaction</strong> — Click and type in the Zotero UI</summary>
ToolDescription
zotero_click_elementClick 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_keysType 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.

</details> <details> <summary><strong>JavaScript Execution</strong> — Run code in Zotero context</summary>
ToolDescription
zotero_execute_jsExecute JavaScript in Zotero's privileged context. Auto-wraps code with top-level return statements in IIFE.
zotero_inspect_objectExplore Zotero APIs - list methods and properties of any object (e.g., Zotero.Items)
zotero_open_preferencesOpen Zotero's settings window, optionally to a specific pane (built-in or plugin)
zotero_search_prefsSearch/discover preferences by pattern (e.g., find all prefs containing "debug")
zotero_get_prefGet a preference value
zotero_set_prefSet a preference value

Examples: Zotero.Items.getAll(1), Zotero.Prefs.get('export.quickCopy.setting'), ZoteroPane.getSelectedItems()

Tip: Use zotero_inspect_object to explore APIs before writing code. Use zotero_search_prefs to discover preference keys.

</details> <details> <summary><strong>Build & Scaffold</strong> — Integration with zotero-plugin-scaffold</summary>
ToolDescription
zotero_scaffold_buildBuild plugin (dev or production mode)
zotero_scaffold_serveStart dev server with hot reload
zotero_scaffold_lintRun ESLint on plugin source
zotero_scaffold_typecheckRun TypeScript type checking
</details> <details> <summary><strong>Logs & Debugging</strong> — Error console and debug output</summary>
ToolDescription
zotero_read_logsRead debug output (Zotero.debug)
zotero_read_errorsRead error console entries
zotero_watch_logsStream logs in real-time
zotero_clear_logsClear log buffer
</details> <details> <summary><strong>Plugin Management</strong> — Install, reload, inspect</summary>
ToolDescription
zotero_plugin_reloadHot reload your dev plugin
zotero_plugin_installInstall plugin from XPI path
zotero_plugin_listList installed plugins with version/status
</details> <details> <summary><strong>Database Access</strong> — Read-only SQLite access</summary>
ToolDescription
zotero_db_queryExecute SELECT query on zotero.sqlite
zotero_db_schemaGet table schema information
zotero_db_statsGet 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.

</details>

🏗️ Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        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?

  • ✅ Lightweight plugin — Just enables RDP, Firefox DevTools does the rest
  • ✅ Zero-config after install — Just open Zotero normally, no special flags
  • ✅ Rich AI context — Screenshots, DOM, and logs help the AI understand your plugin's state
  • ✅ Hot reload — Integrates with zotero-plugin-scaffold for instant feedback
  • ✅ Full Zotero access — Execute any Zotero API in the privileged context
  • ✅ Cross-platform — Works on Linux, Windows, macOS

🔧 Environment Variables

VariableDescriptionDefault
ZOTERO_RDP_PORTRemote debugging port6100
ZOTERO_RDP_HOSTDebugging host127.0.0.1
ZOTERO_DATA_DIRPath to Zotero data directoryAuto-detect
ZOTERO_PROFILE_PATHPath to Zotero profileAuto-detect

🔌 Changing the RDP Port

The bridge listens on port 6100 by default. You only need to change it if you run two Zotero instances at the same time (a normal profile and a development one, say), or if another process already holds 6100.

The port lives on both sides of the bridge, and both have to agree on it.

1. Zotero side — set the plugin preference:

  1. Settings → Advanced → Config Editor, and accept the warning
  2. Search for extensions.mcp-rdp.port
  3. If it doesn't exist, create it: select Number, name it extensions.mcp-rdp.port, and enter your port
  4. Restart Zotero — the listener only opens at startup

Watch the type. The Config Editor pre-selects Boolean. Creating the preference without switching to Number stores true instead of a port, and Zotero then opens the bridge on a local pipe rather than a TCP port — the debug log reports success while no MCP client can connect.

2. Client side — set ZOTERO_RDP_PORT to the same value in your MCP client config:

{
  "mcpServers": {
    "zotero-dev": {
      "command": "npx",
      "args": ["-y", "@introfini/mcp-server-zotero-dev@1.1.2"],
      "env": {
        "ZOTERO_RDP_PORT": "6101"
      }
    }
  }
}

Change both or neither. Moving only one side disconnects the bridge: Zotero listens on one port while the client keeps dialing the other.

Actually running two instances

Launching Zotero a second time hands you the window you already have — like Firefox, it forwards to the running instance instead of starting another. A second instance needs its own profile and -no-remote:

# macOS; adjust the binary path on Windows/Linux
MOZ_NO_REMOTE=1 "/Applications/Zotero.app/Contents/MacOS/zotero" -P <profile-name> -no-remote

Give that profile its own extensions.mcp-rdp.port and the two bridges stay out of each other's way. Verified with 9.0.6 on 6100 and 10.0-beta.22 on 6101 at the same time.

Requires MCP Bridge plugin 1.0.5 or later. In 1.0.4 and earlier, extensions.mcp-rdp.port was read under the wrong preference branch and silently ignored, so the bridge stayed on 6100 no matter what you set. If you configured a custom port against an older build, it is stored as extensions.zotero.extensions.mcp-rdp.port — that name still works, but prefer the one above.

Disabling the bridge

Set extensions.mcp-rdp.enabled to false (Boolean) in the Config Editor and restart Zotero. The plugin stays installed but opens no listener, and no MCP client can reach Zotero until you set it back to true.

Checking what the bridge did

The plugin appends one line per lifecycle transition to mcp-rdp-events.log in your Zotero profile directory: startup, listener open, listener down, listener recovered, listener flapping, shutdown. It survives restarts and is readable without Zotero running, which makes it the first place to look when an MCP client reports Cannot connect to Zotero RDP:

2026-09-17T07:52:36.201Z startup v1.0.5 reason=1
2026-09-17T07:52:37.914Z listener DOWN on port 6177 - failed to open at startup: port 6177 does not answer (held by another process?)
2026-09-17T07:53:46.552Z listener RECOVERED on port 6177 after 6 failed checks, 69s down
2026-09-17T08:01:12.083Z shutdown v1.0.5 reason=2

What to read from it:

  • listener DOWN … failed to open at startup — something else holds the port: another Zotero instance, a previous one that has not released it, or a process that answers on the port without speaking RDP. The reason after the colon says which of the last two it is.
  • listener DOWN … stopped answering — the listener was up and then died. The health check reopens it; the next line tells you when that worked and how long the gap was.
  • listener RECOVERED … after N failed checks — the bridge came back on its own. A large N means the port was held for a long time; nothing is logged per attempt, so the file stays short no matter how long the outage.
  • listener FLAPPING, later closed by listener STEADY … after N flaps — the listener keeps dying and coming straight back on the first reopen. That is a different fault from an outage: the port is yours, something is tearing the listener down. The whole run costs these two lines however long it goes on, so N is the number to report if you open an issue.
  • A startup with no shutdown before it — Zotero was killed or crashed rather than exiting cleanly. Usually the answer to "the bridge stopped working" is simply that Zotero is not running.
  • No new lines at all — the plugin never started: disabled by preference, or not installed in the profile you are actually running.

log() output goes to dump() (lost unless Zotero was started from a console) and Zotero.debug() (a no-op unless debug output is enabled), so this file is the only durable record of a boot-time failure. A healthy session adds three lines (startup, open, shutdown); an outage adds two more, and a run of flaps two more, whatever their length. No failure mode writes per tick.


📸 Screenshot Examples

// 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"]' });

🧑‍💻 Development

# 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
<details> <summary><strong>Project Structure</strong></summary>
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/
│       │   └── bootstrap.js      # Starts RDP server (shipped verbatim)
│       ├── addon/
│       │   └── manifest.json
│       └── package.json
│
├── docs/                         # Documentation
└── package.json                  # Monorepo root
</details>

📚 Resources


🤝 Contributing

Contributions are welcome. See CONTRIBUTING.md for setup, test conventions and the codebase-specific rules worth knowing before you start.

The short version:

  1. Follow existing code patterns
  2. Add tests for new features, and skip rather than fail when Zotero is not running
  3. Update documentation
  4. There is no CI, so run npm run build, npm run typecheck, npm run lint and npm test yourself, and say in the PR which Zotero version you verified against

📄 License

MIT © introfini


Acknowledgments

Related MCP servers

Search 160k+ Russian B2B products from 8,900+ verified manufacturers (EN/RU).

0
View repository →

Extract, create, convert & validate invoices (UBL, CII, XRechnung, ZUGFeRD, PDF, Excel)

0
TypeScript
View repository →
ZTZTL Judge logo

ZTL Judge

Active

Zero-trust logic judge: your AI writes a claim as a ZFL table, the ZTL core judges it.

0
Python
Apache-2.0
View repository →

Pay-per-call AI evaluation MCP server. Score LLM outputs against benchmark rubrics via Workers AI.

15 paid AI agent primitives via x402 (USDC on Base). Pay-per-call MCP server.

View repository →
ABAbaPay logo

AbaPay

Active

Non-custodial stablecoin bill-pay rails on Celo & Base for AI agents, settled on-chain via MCP.

1
TypeScript
MIT
View repository →