MCP Bridge for Zotero
Servidor MCP que permite a asistentes de IA construir, probar y depurar plugins de Zotero mediante 26 herramientas para inspección de interfaz, ejecución de JS, registro y más.
Documentación
Servidor MCP Zotero Dev
Dale a tu asistente de IA superpoderes para el desarrollo de plugins de Zotero
Arquitectura · Primeros pasos · Herramientas disponibles
Un servidor de Protocolo de Contexto de Modelo (MCP) que permite a asistentes de IA como Claude, Cursor y Windsurf crear, probar y depurar plugins de Zotero 7, 8, 9 y 10. Capturas de pantalla, estado del DOM, registros de depuración y ejecución de JavaScript le dan a la IA un contexto rico para entender lo que está sucediendo, además de herramientas para ayudarte a solucionarlo.
✨ Características
| Categoría | Capacidades |
|---|---|
| 🎯 Inspección de UI | Capturas de pantalla, árbol DOM, búsqueda de elementos, estilos calculados |
| 🖱️ Interacción con UI | Hacer clic en elementos y escribir texto (compatible con shadow DOM) |
| 💻 Ejecución de JS | Ejecutar código en el contexto de Zotero, inspeccionar APIs, probar fragmentos |
| 🔧 Herramientas de compilación | Integración de andamiaje para compilar, servir, recarga en caliente |
| 📋 Registros y errores | Transmitir salida de depuración, consola de errores, monitorear problemas |
| 🗃️ Base de datos | Acceso de solo lectura a zotero.sqlite para depuración |
| 🔌 Gestión de plugins | Instalar, recargar, listar plugins |
🚀 Inicio rápido
Requisitos previos
- Node.js 20+ y npm
- Zotero 7+ — Funciona en todas las compilaciones de Zotero 7, 8, 9 y 10 (release, beta, dev)
- Para desarrollo de plugins: zotero-plugin-scaffold
1. Instalar el servidor MCP
Usa install-mcp para agregar el servidor a tu asistente de IA:
npx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code
Clientes compatibles: claude-code, cursor, windsurf, vscode, cline, roo-cline, claude, zed, goose, warp, codex
Claude Code
npx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code
Cursor
npx -y install-mcp @introfini/mcp-server-zotero-dev --client cursor
VS Code / Copilot
npx -y install-mcp @introfini/mcp-server-zotero-dev --client vscode
Windsurf
npx -y install-mcp @introfini/mcp-server-zotero-dev --client windsurf
Configuración manual
Agrega a la configuración de tu cliente MCP:
{
"mcpServers": {
"zotero-dev": {
"command": "npx",
"args": ["-y", "@introfini/mcp-server-zotero-dev@1.1.1"],
"env": {
"ZOTERO_RDP_PORT": "6100"
}
}
}
}
Versión y actualizaciones: fija una versión exacta como se muestra arriba. Un
npx <pkg>sin versión (sin número de versión) sigue ejecutando lo quenpxtenga en caché y no recogerá nuevas versiones, así que siempre incluye una versión y-y(sin-y,npxse queda esperando un aviso de instalación). Aumenta la versión fijada para actualizar, o usa@latestpara obtener siempre la más reciente al iniciar (actualizaciones automáticas, pero una versión defectuosa se ejecutaría automáticamente y agrega una verificación de registro en cada inicio). Ten en cuenta queinstall-mcppuede escribir una configuración sin-yo una versión, por lo que la configuración manual anterior es la ruta más robusta.
Reinicia tu asistente de IA después de agregar la configuración.
2. Instalar el plugin MCP Bridge en Zotero
Descarga zotero-mcp-bridge.xpi e instálalo:
- En Zotero: Herramientas → Plugins
- Haz clic en ⚙️ → Instalar plugin desde archivo
- Selecciona el archivo
.xpidescargado - Reinicia Zotero
Este plugin ligero habilita el Protocolo de Depuración Remota cuando Zotero se inicia. Solo necesita instalarse una vez y funciona en todas las compilaciones de Zotero 7+ (release, beta y dev).
3. ¡Comienza a desarrollar!
Simplemente abre Zotero normalmente y pregúntale a tu asistente de IA:
"Toma una captura de pantalla de Zotero y lista los plugins instalados"
¡Eso es todo! Sin banderas de inicio especiales, sin configuración. 🎉
🧰 Herramientas disponibles (28 en total)
Inspección de UI — Capturas de pantalla, DOM, estilos
| Herramienta | Descripción |
|---|---|
zotero_screenshot | Capturar capturas de pantalla de ventana, elemento o región |
zotero_inspect_element | Encontrar elementos por selector CSS |
zotero_get_dom_tree | Obtener estructura DOM de una ventana/panel |
zotero_get_styles | Obtener estilos CSS calculados para un elemento |
zotero_list_windows | Listar todas las ventanas abiertas de Zotero |
Objetivos de captura: Ventana principal, preferencias, lector de PDF, diálogos o cualquier elemento por selector. Usa
highlightSelectorpara agregar un borde rojo antes de la captura.
Interacción con UI — Hacer clic y escribir en la interfaz de Zotero
| Herramienta | Descripción |
|---|---|
zotero_click_element | Hacer clic en un elemento por selector CSS (botón de barra/menú, control de preferencias, fila de lista). Atraviesa shadow DOM; index elige entre múltiples coincidencias; mouseEvents sintetiza una secuencia completa de mouse. |
zotero_send_keys | Escribir texto en un input/textarea/contenteditable (lo enfoca primero, dispara input/change). Opcional clear y pressEnter. |
La resolución intenta primero con el DOM claro, luego atraviesa raíces shadow abiertas (los elementos personalizados XUL de Zotero mantienen los internos en shadow DOM). Limitación: no puede descartar un diálogo modal nativo bloqueante (
Services.prompt.confirmEx) — su bucle modal anidado bloquea el hilo de evaluación en el que se ejecutan estas herramientas.
Ejecución de JavaScript — Ejecutar código en el contexto de Zotero
| Herramienta | Descripción |
|---|---|
zotero_execute_js | Ejecutar JavaScript en el contexto privilegiado de Zotero. Envuelve automáticamente el código con declaraciones return de nivel superior en IIFE. |
zotero_inspect_object | Explorar APIs de Zotero — listar métodos y propiedades de cualquier objeto (por ejemplo, Zotero.Items) |
zotero_open_preferences | Abrir la ventana de configuración de Zotero, opcionalmente en un panel específico (integrado o de plugin) |
zotero_search_prefs | Buscar/descubrir preferencias por patrón (por ejemplo, encontrar todas las preferencias que contengan "debug") |
zotero_get_pref | Obtener un valor de preferencia |
zotero_set_pref | Establecer un valor de preferencia |
Ejemplos:
Zotero.Items.getAll(1),Zotero.Prefs.get('export.quickCopy.setting'),ZoteroPane.getSelectedItems()Consejo: Usa
zotero_inspect_objectpara explorar APIs antes de escribir código. Usazotero_search_prefspara descubrir claves de preferencias.
Compilación y andamiaje — Integración con zotero-plugin-scaffold
| Herramienta | Descripción |
|---|---|
zotero_scaffold_build | Compilar plugin (modo dev o producción) |
zotero_scaffold_serve | Iniciar servidor de desarrollo con recarga en caliente |
zotero_scaffold_lint | Ejecutar ESLint en el código fuente del plugin |
zotero_scaffold_typecheck | Ejecutar verificación de tipos de TypeScript |
Registros y depuración — Consola de errores y salida de depuración
| Herramienta | Descripción |
|---|---|
zotero_read_logs | Leer salida de depuración (Zotero.debug) |
zotero_read_errors | Leer entradas de la consola de errores |
zotero_watch_logs | Transmitir registros en tiempo real |
zotero_clear_logs | Limpiar el búfer de registros |
Gestión de plugins — Instalar, recargar, inspeccionar
| Herramienta | Descripción |
|---|---|
zotero_plugin_reload | Recargar en caliente tu plugin de desarrollo |
zotero_plugin_install | Instalar plugin desde ruta XPI |
zotero_plugin_list | Listar plugins instalados con versión/estado |
Acceso a base de datos — Acceso SQLite de solo lectura
| Herramienta | Descripción |
|---|---|
zotero_db_query | Ejecutar consulta SELECT en zotero.sqlite |
zotero_db_schema | Obtener información del esquema de tablas |
zotero_db_stats | Obtener estadísticas de la base de datos (elementos, adjuntos, colecciones, tamaño) |
Nota: El acceso a la base de datos es de solo lectura y requiere que Zotero esté cerrado, o usa una copia de la base de datos.
🏗️ Arquitectura
┌─────────────────────────────────────────────────────────────────┐
│ 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) │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
¿Por qué este enfoque?
- ✅ Plugin ligero — Solo habilita RDP, Firefox DevTools hace el resto
- ✅ Cero configuración después de instalar — Solo abre Zotero normalmente, sin banderas especiales
- ✅ Contexto rico para IA — Capturas de pantalla, DOM y registros ayudan a la IA a entender el estado de tu plugin
- ✅ Recarga en caliente — Se integra con zotero-plugin-scaffold para retroalimentación instantánea
- ✅ Acceso completo a Zotero — Ejecuta cualquier API de Zotero en el contexto privilegiado
- ✅ Multiplataforma — Funciona en Linux, Windows, macOS
🔧 Variables de entorno
| Variable | Descripción | Predeterminado |
|---|---|---|
ZOTERO_RDP_PORT | Puerto de depuración remota | 6100 |
ZOTERO_RDP_HOST | Host de depuración | 127.0.0.1 |
ZOTERO_DATA_DIR | Ruta al directorio de datos de Zotero | Detección automática |
ZOTERO_PROFILE_PATH | Ruta al perfil de Zotero | Detección automática |
🔌 Cambiar el puerto RDP
El puente escucha en el puerto 6100 por defecto. Solo necesitas cambiarlo si ejecutas dos instancias de Zotero al mismo tiempo (un perfil normal y uno de desarrollo, por ejemplo), o si otro proceso ya tiene el 6100.
El puerto vive en ambos lados del puente, y ambos deben estar de acuerdo.
1. Lado de Zotero — establece la preferencia del plugin:
- Configuración → Avanzado → Editor de configuración, y acepta la advertencia
- Busca
extensions.mcp-rdp.port - Si no existe, créala: selecciona Número, nómbrala
extensions.mcp-rdp.port, e ingresa tu puerto - Reinicia Zotero — el listener solo se abre al inicio
Cuidado con el tipo. El Editor de configuración preselecciona Booleano. Crear la preferencia sin cambiar a Número almacena
trueen lugar de un puerto, y Zotero entonces abre el puente en una tubería local en lugar de un puerto TCP — el registro de depuración informa éxito mientras ningún cliente MCP puede conectarse.
2. Lado del cliente — establece ZOTERO_RDP_PORT al mismo valor en la configuración de tu cliente MCP:
{
"mcpServers": {
"zotero-dev": {
"command": "npx",
"args": ["-y", "@introfini/mcp-server-zotero-dev@1.1.2"],
"env": {
"ZOTERO_RDP_PORT": "6101"
}
}
}
}
Cambia ambos o ninguno. Mover solo un lado desconecta el puente: Zotero escucha en un puerto mientras el cliente sigue marcando el otro.
Ejecutar dos instancias realmente
Iniciar Zotero por segunda vez te entrega la ventana que ya tienes — como Firefox, reenvía a la instancia en ejecución en lugar de iniciar otra. Una segunda instancia necesita su propio perfil y -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
Dale a ese perfil su propio extensions.mcp-rdp.port y los dos puentes no se interpondrán entre sí. Verificado con 9.0.6 en 6100 y 10.0-beta.22 en 6101 al mismo tiempo.
Requiere el plugin MCP Bridge 1.0.5 o posterior. En 1.0.4 y anteriores,
extensions.mcp-rdp.portse leía bajo la rama de preferencias incorrecta y se ignoraba silenciosamente, por lo que el puente permanecía en 6100 sin importar lo que configuraras. Si configuraste un puerto personalizado contra una compilación anterior, se almacena comoextensions.zotero.extensions.mcp-rdp.port— ese nombre aún funciona, pero prefiere el anterior.
Deshabilitar el puente
Establece extensions.mcp-rdp.enabled a false (Booleano) en el Editor de configuración y reinicia Zotero. El plugin permanece instalado pero no abre ningún listener, y ningún cliente MCP puede alcanzar Zotero hasta que lo vuelvas a establecer en true.
Verificar qué hizo el puente
El plugin agrega una línea por cada transición del ciclo de vida a mcp-rdp-events.log en tu directorio de perfil de Zotero: inicio, listener abierto, listener caído, listener recuperado, listener fluctuante, apagado. Sobrevive a los reinicios y es legible sin que Zotero esté ejecutándose, lo que lo convierte en el primer lugar para mirar cuando un cliente MCP reporta 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
Qué leer de él:
listener DOWN … failed to open at startup— algo más mantiene el puerto: otra instancia de Zotero, una anterior que no lo ha liberado, o un proceso que responde en el puerto sin hablar RDP. La razón después de los dos puntos indica cuál de las dos últimas es.listener DOWN … stopped answering— el listener estaba activo y luego murió. La comprobación de salud lo reabre; la siguiente línea te dice cuándo funcionó y cuánto duró la brecha.listener RECOVERED … after N failed checks— el puente volvió por sí solo. Una N grande significa que el puerto estuvo ocupado durante mucho tiempo; no se registra nada por intento, por lo que el archivo permanece corto sin importar cuánto dure la interrupción.listener FLAPPING, luego cerrado porlistener STEADY … after N flaps— el listener sigue muriendo y volviendo directamente en la primera reapertura. Eso es una falla diferente a una interrupción: el puerto es tuyo, algo está derribando el listener. Toda la ejecución cuesta estas dos líneas sin importar cuánto continúe, así que N es el número a reportar si abres un problema.- Un
startupsinshutdownantes — Zotero fue eliminado o se bloqueó en lugar de salir limpiamente. Generalmente, la respuesta a "el puente dejó de funcionar" es simplemente que Zotero no está en ejecución. - Sin líneas nuevas en absoluto — el plugin nunca se inició: deshabilitado por preferencia, o no instalado en el perfil que realmente estás ejecutando.
La salida de log() va a dump() (se pierde a menos que Zotero se inicie desde una consola) y Zotero.debug() (una operación no operativa a menos que la salida de depuración esté habilitada), por lo que este archivo es el único registro duradero de una falla al arrancar. Una sesión saludable agrega tres líneas (inicio, apertura, cierre); una interrupción agrega dos más, y una serie de aleteos dos más, sin importar su duración. Ningún modo de falla escribe por tick.
📸 Ejemplos de capturas de pantalla
// 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"]' });
🧑💻 Desarrollo
# 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
Estructura del proyecto
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
📚 Recursos
- Arquitectura y aprendizajes técnicos — Inmersión profunda en el protocolo RDP, la jerarquía de actores y los errores comunes
- Desarrollo de plugins de Zotero — Documentación oficial
- Zotero 10 para desarrolladores — Guía de migración para la última versión principal
- Zotero 7 para desarrolladores — Guía de migración
- zotero-plugin-scaffold — Herramientas de compilación
- zotero-plugin-template — Plantilla de inicio
- zotero-plugin-toolkit — Ayudantes de API
- Protocolo RDP de Firefox — Documentación del protocolo
🤝 Contribuciones
Las contribuciones son bienvenidas. Consulta CONTRIBUTING.md para la configuración, las convenciones de prueba y las reglas específicas del código que vale la pena conocer antes de comenzar.
La versión corta:
- Sigue los patrones de código existentes
- Agrega pruebas para nuevas funciones, y omite en lugar de fallar cuando Zotero no está en ejecución
- Actualiza la documentación
- No hay CI, así que ejecuta
npm run build,npm run typecheck,npm run lintynpm testtú mismo, y menciona en el PR qué versión de Zotero verificaste
📄 Licencia
MIT © introfini
Agradecimientos
- Construido para la comunidad de desarrolladores de plugins de Zotero
- Se integra con zotero-plugin-scaffold por @windingwind
- Aprovecha Firefox DevTools RDP para una comunicación confiable