{
  "markdown": "<div align=\"center\">\n\n# MCP Server Zotero Dev\n\n**Give your AI assistant superpowers for Zotero plugin development**\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-8b5cf6.svg?style=flat-square)](LICENSE)\n[![Zotero 7+](https://img.shields.io/badge/Zotero-7%2B-CC2936?style=flat-square&logo=zotero&logoColor=white)](https://www.zotero.org)\n\n[Architecture](ARCHITECTURE.md) · [Getting Started](#quick-start) · [Available Tools](#available-tools)\n\n<img src=\"docs/images/demo.png\" alt=\"MCP Server Zotero Dev in action\" width=\"800\">\n\n</div>\n\n---\n\nA **Model Context Protocol (MCP) server** that enables AI assistants like Claude, Cursor, and Windsurf to build, test, and debug [Zotero](https://www.zotero.org) 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.\n\n## ✨ Features\n\n| Category | Capabilities |\n|----------|-------------|\n| 🎯 **UI Inspection** | Screenshots, DOM tree, element finding, computed styles |\n| 🖱️ **UI Interaction** | Click elements and type text (shadow-DOM aware) |\n| 💻 **JS Execution** | Run code in Zotero context, inspect APIs, test snippets |\n| 🔧 **Build Tools** | Scaffold integration for build, serve, hot reload |\n| 📋 **Logs & Errors** | Stream debug output, error console, watch for issues |\n| 🗃️ **Database** | Read-only access to zotero.sqlite for debugging |\n| 🔌 **Plugin Management** | Install, reload, list plugins |\n\n---\n\n## 🚀 Quick Start\n\n### Prerequisites\n\n- **Node.js** 20+ and npm\n- **Zotero 7+** — Works on all Zotero 7, 8, 9, and 10 builds (release, beta, dev)\n- For plugin development: [zotero-plugin-scaffold](https://github.com/windingwind/zotero-plugin-scaffold)\n\n### 1. Install MCP Server\n\nUse [install-mcp](https://www.npmjs.com/package/install-mcp) to add the server to your AI assistant:\n\n```bash\nnpx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code\n```\n\nSupported clients: `claude-code`, `cursor`, `windsurf`, `vscode`, `cline`, `roo-cline`, `claude`, `zed`, `goose`, `warp`, `codex`\n\n<details>\n<summary><strong>Claude Code</strong></summary>\n\n```bash\nnpx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code\n```\n</details>\n\n<details>\n<summary><strong>Cursor</strong></summary>\n\n```bash\nnpx -y install-mcp @introfini/mcp-server-zotero-dev --client cursor\n```\n</details>\n\n<details>\n<summary><strong>VS Code / Copilot</strong></summary>\n\n```bash\nnpx -y install-mcp @introfini/mcp-server-zotero-dev --client vscode\n```\n</details>\n\n<details>\n<summary><strong>Windsurf</strong></summary>\n\n```bash\nnpx -y install-mcp @introfini/mcp-server-zotero-dev --client windsurf\n```\n</details>\n\n<details>\n<summary><strong>Manual Configuration</strong></summary>\n\nAdd to your MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"zotero-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@introfini/mcp-server-zotero-dev@1.1.1\"],\n      \"env\": {\n        \"ZOTERO_RDP_PORT\": \"6100\"\n      }\n    }\n  }\n}\n```\n</details>\n\n> **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.\n\n**Restart your AI assistant** after adding the configuration.\n\n### 2. Install MCP Bridge Plugin in Zotero\n\nDownload [zotero-mcp-bridge.xpi](https://github.com/introfini/mcp-server-zotero-dev/releases/latest) and install:\n\n1. In Zotero: **Tools → Plugins**\n2. Click ⚙️ → **Install Plugin From File**\n3. Select the downloaded `.xpi` file\n4. **Restart Zotero**\n\n> 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).\n\n### 3. Start Developing!\n\nJust open Zotero normally and ask your AI assistant:\n\n> \"Take a screenshot of Zotero and list installed plugins\"\n\nThat's it! No special launch flags, no configuration. 🎉\n\n---\n\n## 🧰 Available Tools (28 total)\n\n<details>\n<summary><strong>UI Inspection</strong> — Screenshots, DOM, styles</summary>\n\n| Tool | Description |\n|------|-------------|\n| `zotero_screenshot` | Capture window, element, or region screenshots |\n| `zotero_inspect_element` | Find elements by CSS selector |\n| `zotero_get_dom_tree` | Get DOM structure of a window/panel |\n| `zotero_get_styles` | Get computed CSS styles for element |\n| `zotero_list_windows` | List all open Zotero windows |\n\n> **Screenshot Targets**: Main window, preferences, PDF reader, dialogs, or any element by selector. Use `highlightSelector` to add a red border before capture.\n\n</details>\n\n<details>\n<summary><strong>UI Interaction</strong> — Click and type in the Zotero UI</summary>\n\n| Tool | Description |\n|------|-------------|\n| `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. |\n| `zotero_send_keys` | Type text into an input/textarea/contenteditable (focuses it first, fires input/change). Optional `clear` and `pressEnter`. |\n\n> 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.\n\n</details>\n\n<details>\n<summary><strong>JavaScript Execution</strong> — Run code in Zotero context</summary>\n\n| Tool | Description |\n|------|-------------|\n| `zotero_execute_js` | Execute JavaScript in Zotero's privileged context. Auto-wraps code with top-level `return` statements in IIFE. |\n| `zotero_inspect_object` | Explore Zotero APIs - list methods and properties of any object (e.g., `Zotero.Items`) |\n| `zotero_open_preferences` | Open Zotero's settings window, optionally to a specific pane (built-in or plugin) |\n| `zotero_search_prefs` | Search/discover preferences by pattern (e.g., find all prefs containing \"debug\") |\n| `zotero_get_pref` | Get a preference value |\n| `zotero_set_pref` | Set a preference value |\n\n> **Examples**: `Zotero.Items.getAll(1)`, `Zotero.Prefs.get('export.quickCopy.setting')`, `ZoteroPane.getSelectedItems()`\n>\n> **Tip**: Use `zotero_inspect_object` to explore APIs before writing code. Use `zotero_search_prefs` to discover preference keys.\n\n</details>\n\n<details>\n<summary><strong>Build & Scaffold</strong> — Integration with zotero-plugin-scaffold</summary>\n\n| Tool | Description |\n|------|-------------|\n| `zotero_scaffold_build` | Build plugin (dev or production mode) |\n| `zotero_scaffold_serve` | Start dev server with hot reload |\n| `zotero_scaffold_lint` | Run ESLint on plugin source |\n| `zotero_scaffold_typecheck` | Run TypeScript type checking |\n\n</details>\n\n<details>\n<summary><strong>Logs & Debugging</strong> — Error console and debug output</summary>\n\n| Tool | Description |\n|------|-------------|\n| `zotero_read_logs` | Read debug output (Zotero.debug) |\n| `zotero_read_errors` | Read error console entries |\n| `zotero_watch_logs` | Stream logs in real-time |\n| `zotero_clear_logs` | Clear log buffer |\n\n</details>\n\n<details>\n<summary><strong>Plugin Management</strong> — Install, reload, inspect</summary>\n\n| Tool | Description |\n|------|-------------|\n| `zotero_plugin_reload` | Hot reload your dev plugin |\n| `zotero_plugin_install` | Install plugin from XPI path |\n| `zotero_plugin_list` | List installed plugins with version/status |\n\n</details>\n\n<details>\n<summary><strong>Database Access</strong> — Read-only SQLite access</summary>\n\n| Tool | Description |\n|------|-------------|\n| `zotero_db_query` | Execute SELECT query on zotero.sqlite |\n| `zotero_db_schema` | Get table schema information |\n| `zotero_db_stats` | Get database statistics (items, attachments, collections, size) |\n\n> **Note**: Database access is read-only and requires Zotero to be closed, or uses a copy of the database.\n\n</details>\n\n---\n\n## 🏗️ Architecture\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                        AI Assistant                             │\n│                  (Claude, Cursor, Windsurf)                     │\n└─────────────────────────┬───────────────────────────────────────┘\n                          │ MCP Protocol (stdio)\n                          ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                  MCP Server (Node.js/TypeScript)                │\n│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────────┐   │\n│  │   Scaffold   │  │     RDP      │  │      Database        │   │\n│  │  Integration │  │    Client    │  │      Reader          │   │\n│  └──────────────┘  └──────┬───────┘  └──────────────────────┘   │\n└─────────────────────────────┼───────────────────────────────────┘\n                              │ Firefox RDP (port 6100)\n                              ▼\n┌─────────────────────────────────────────────────────────────────┐\n│                      Zotero Application                         │\n│  ┌──────────────────────────────────────────────────────────┐   │\n│  │            MCP Bridge for Zotero                         │   │\n│  │         Starts DevToolsServer on launch                  │   │\n│  └──────────────────────────────────────────────────────────┘   │\n│  ┌──────────────────────────────────────────────────────────┐   │\n│  │              Firefox DevTools Server (built-in)          │   │\n│  │           JS Execution • DOM • Console • Screenshots     │   │\n│  └──────────────────────────────────────────────────────────┘   │\n│  ┌──────────────────────────────────────────────────────────┐   │\n│  │                   Your Plugin (dev)                      │   │\n│  └──────────────────────────────────────────────────────────┘   │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n**Why this approach?**\n\n- ✅ **Lightweight plugin** — Just enables RDP, Firefox DevTools does the rest\n- ✅ **Zero-config after install** — Just open Zotero normally, no special flags\n- ✅ **Rich AI context** — Screenshots, DOM, and logs help the AI understand your plugin's state\n- ✅ **Hot reload** — Integrates with zotero-plugin-scaffold for instant feedback\n- ✅ **Full Zotero access** — Execute any Zotero API in the privileged context\n- ✅ **Cross-platform** — Works on Linux, Windows, macOS\n\n---\n\n## 🔧 Environment Variables\n\n| Variable | Description | Default |\n|----------|-------------|---------|\n| `ZOTERO_RDP_PORT` | Remote debugging port | `6100` |\n| `ZOTERO_RDP_HOST` | Debugging host | `127.0.0.1` |\n| `ZOTERO_DATA_DIR` | Path to Zotero data directory | Auto-detect |\n| `ZOTERO_PROFILE_PATH` | Path to Zotero profile | Auto-detect |\n\n---\n\n## 🔌 Changing the RDP Port\n\nThe 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.\n\nThe port lives on **both sides of the bridge**, and both have to agree on it.\n\n**1. Zotero side** — set the plugin preference:\n\n1. **Settings → Advanced → Config Editor**, and accept the warning\n2. Search for `extensions.mcp-rdp.port`\n3. If it doesn't exist, create it: select **Number**, name it `extensions.mcp-rdp.port`, and enter your port\n4. **Restart Zotero** — the listener only opens at startup\n\n> **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.\n\n**2. Client side** — set `ZOTERO_RDP_PORT` to the same value in your MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"zotero-dev\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@introfini/mcp-server-zotero-dev@1.1.2\"],\n      \"env\": {\n        \"ZOTERO_RDP_PORT\": \"6101\"\n      }\n    }\n  }\n}\n```\n\n> **Change both or neither.** Moving only one side disconnects the bridge: Zotero listens on one port while the client keeps dialing the other.\n\n### Actually running two instances\n\nLaunching 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`:\n\n```bash\n# macOS; adjust the binary path on Windows/Linux\nMOZ_NO_REMOTE=1 \"/Applications/Zotero.app/Contents/MacOS/zotero\" -P <profile-name> -no-remote\n```\n\nGive 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.\n\n> **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.\n\n### Disabling the bridge\n\nSet `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`.\n\n---\n\n## 📸 Screenshot Examples\n\n```typescript\n// Capture main Zotero window\nawait zotero_screenshot({ target: 'main-window' });\n\n// Capture your plugin's panel with highlight\nawait zotero_screenshot({\n  target: 'element',\n  selector: '#my-plugin-panel',\n  highlightSelector: '#my-plugin-button'\n});\n\n// Capture a specific window by ID (use zotero_list_windows to find IDs)\nawait zotero_screenshot({\n  target: 'window',\n  windowId: 12345\n});\n\n// Capture element after triggering UI action\nawait zotero_execute_js({ code: 'document.querySelector(\"#menu\").click()' });\nawait zotero_screenshot({ target: 'element', selector: 'menupopup[state=\"open\"]' });\n```\n\n---\n\n## 🧑‍💻 Development\n\n```bash\n# Clone and install\ngit clone https://github.com/introfini/mcp-server-zotero-dev.git\ncd mcp-server-zotero-dev\nnpm install\n\n# Build everything\nnpm run build\n\n# Build individual packages\nnpm run build:server\nnpm run build:plugin\n\n# Run tests\nnpm test\n\n# Development mode (watch)\nnpm run dev\n```\n\n<details>\n<summary><strong>Project Structure</strong></summary>\n\n```\nmcp-server-zotero-dev/\n├── packages/\n│   ├── mcp-server/               # MCP server (npm package)\n│   │   ├── src/\n│   │   │   ├── index.ts          # MCP server entry\n│   │   │   ├── rdp/              # RDP client\n│   │   │   ├── tools/            # Tool implementations\n│   │   │   └── prompts/          # Slash commands\n│   │   └── package.json\n│   │\n│   └── zotero-plugin-mcp-rdp/    # Tiny Zotero plugin (.xpi)\n│       ├── src/\n│       │   └── bootstrap.js      # Starts RDP server (shipped verbatim)\n│       ├── addon/\n│       │   └── manifest.json\n│       └── package.json\n│\n├── docs/                         # Documentation\n└── package.json                  # Monorepo root\n```\n\n</details>\n\n---\n\n## 📚 Resources\n\n- **[Architecture & Technical Learnings](ARCHITECTURE.md)** — Deep dive into RDP protocol, actor hierarchy, and common pitfalls\n- **[Zotero Plugin Development](https://www.zotero.org/support/dev/client_coding/plugin_development)** — Official docs\n- **[Zotero 10 for Developers](https://www.zotero.org/support/dev/zotero_10_for_developers)** — Migration guide for the latest major\n- **[Zotero 7 for Developers](https://www.zotero.org/support/dev/zotero_7_for_developers)** — Migration guide\n- **[zotero-plugin-scaffold](https://github.com/windingwind/zotero-plugin-scaffold)** — Build tooling\n- **[zotero-plugin-template](https://github.com/windingwind/zotero-plugin-template)** — Starter template\n- **[zotero-plugin-toolkit](https://github.com/windingwind/zotero-plugin-toolkit)** — API helpers\n- **[Firefox RDP Protocol](https://firefox-source-docs.mozilla.org/devtools/backend/protocol.html)** — Protocol docs\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome. See **[CONTRIBUTING.md](CONTRIBUTING.md)** for setup, test conventions and the codebase-specific rules worth knowing before you start.\n\nThe short version:\n\n1. Follow existing code patterns\n2. Add tests for new features, and skip rather than fail when Zotero is not running\n3. Update documentation\n4. 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\n\n---\n\n## 📄 License\n\nMIT © [introfini](https://github.com/introfini)\n\n---\n\n## Acknowledgments\n\n- Built for the [Zotero](https://www.zotero.org) plugin developer community\n- Integrates with [zotero-plugin-scaffold](https://github.com/windingwind/zotero-plugin-scaffold) by [@windingwind](https://github.com/windingwind)\n- Leverages Firefox DevTools RDP for reliable communication\n",
  "bytes": 17295,
  "sha": "fcc316675fe6e105b21913134fb949e63a8f1e00426cdbd7edbf3d1202fa3eb7",
  "repo_slug": "introfini/mcp-server-zotero-dev",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_introfini_mcp_server_zotero_de_de0a38f5/readme"
}