MCP Bridge for Zotero
Servidor MCP que permite que assistentes de IA criem, testem e depurem plugins do Zotero por meio de 26 ferramentas para inspeção de interface, execução de JavaScript, registro de logs e muito mais.
Documentação
MCP Server Zotero Dev
Dê superpoderes ao seu assistente de IA para desenvolvimento de plugins do Zotero
Arquitetura · Começando · Ferramentas Disponíveis
Um servidor Model Context Protocol (MCP) que permite que assistentes de IA como Claude, Cursor e Windsurf criem, testem e depurem plugins do Zotero 7, 8, 9 e 10. Capturas de tela, estado do DOM, logs de depuração e execução de JavaScript dão ao assistente de IA um contexto rico para entender o que está acontecendo — e ferramentas para ajudá-lo a corrigir.
✨ Recursos
| Categoria | Capacidades |
|---|---|
| 🎯 Inspeção de UI | Capturas de tela, árvore DOM, localização de elementos, estilos computados |
| 🖱️ Interação com UI | Clicar em elementos e digitar texto (ciente de shadow DOM) |
| 💻 Execução de JS | Executar código no contexto do Zotero, inspecionar APIs, testar trechos |
| 🔧 Ferramentas de Build | Integração de scaffold para build, serve, hot reload |
| 📋 Logs e Erros | Transmitir saída de depuração, console de erros, monitorar problemas |
| 🗃️ Banco de Dados | Acesso somente leitura ao zotero.sqlite para depuração |
| 🔌 Gerenciamento de Plugins | Instalar, recarregar, listar plugins |
🚀 Início Rápido
Pré-requisitos
- Node.js 20+ e npm
- Zotero 7+ — Funciona em todas as versões do Zotero 7, 8, 9 e 10 (release, beta, dev)
- Para desenvolvimento de plugins: zotero-plugin-scaffold
1. Instalar o Servidor MCP
Use install-mcp para adicionar o servidor ao seu assistente de IA:
npx -y install-mcp @introfini/mcp-server-zotero-dev --client claude-code
Clientes suportados: 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
Configuração Manual
Adicione à configuração do seu cliente MCP:
{
"mcpServers": {
"zotero-dev": {
"command": "npx",
"args": ["-y", "@introfini/mcp-server-zotero-dev@1.1.1"],
"env": {
"ZOTERO_RDP_PORT": "6100"
}
}
}
}
Versão e atualizações: fixe uma versão exata como mostrado acima. Um
npx <pkg>simples (sem versão) continua executando o que onpxarmazenou em cache e não receberá novos lançamentos, então sempre inclua uma versão e-y(sem-y, onpxfica pendurado aguardando um prompt de instalação). Aumente a versão fixada para atualizar, ou use@latestpara sempre buscar a mais recente na inicialização (atualiza automaticamente, mas uma versão ruim seria executada automaticamente e adiciona uma verificação de registro a cada início). Observe que oinstall-mcppode gravar uma configuração sem-you uma versão, então a configuração manual acima é o caminho mais robusto.
Reinicie seu assistente de IA após adicionar a configuração.
2. Instalar o Plugin MCP Bridge no Zotero
Baixe zotero-mcp-bridge.xpi e instale:
- No Zotero: Ferramentas → Plugins
- Clique em ⚙️ → Instalar Plugin a partir de Arquivo
- Selecione o arquivo
.xpibaixado - Reinicie o Zotero
Este plugin leve habilita o Remote Debugging Protocol quando o Zotero inicia. Ele só precisa ser instalado uma vez e funciona em todas as versões do Zotero 7+ (release, beta e dev).
3. Comece a Desenvolver!
Basta abrir o Zotero normalmente e perguntar ao seu assistente de IA:
"Tire uma captura de tela do Zotero e liste os plugins instalados"
É isso! Sem flags especiais de inicialização, sem configuração. 🎉
🧰 Ferramentas Disponíveis (28 no total)
Inspeção de UI — Capturas de tela, DOM, estilos
| Ferramenta | Descrição |
|---|---|
zotero_screenshot | Capturar capturas de tela de janela, elemento ou região |
zotero_inspect_element | Encontrar elementos por seletor CSS |
zotero_get_dom_tree | Obter estrutura DOM de uma janela/painel |
zotero_get_styles | Obter estilos CSS computados para elemento |
zotero_list_windows | Listar todas as janelas abertas do Zotero |
Alvos de Captura de Tela: Janela principal, preferências, leitor de PDF, diálogos ou qualquer elemento por seletor. Use
highlightSelectorpara adicionar uma borda vermelha antes da captura.
Interação com UI — Clicar e digitar na interface do Zotero
| Ferramenta | Descrição |
|---|---|
zotero_click_element | Clicar em um elemento por seletor CSS (botão de barra de ferramentas/menu, controle de preferência, linha de lista). Atravessa shadow DOM; index escolhe entre múltiplas correspondências; mouseEvents sintetiza uma sequência completa de mouse. |
zotero_send_keys | Digitar texto em um input/textarea/contenteditable (foca primeiro, dispara input/change). clear e pressEnter opcionais. |
A resolução tenta o DOM claro primeiro, depois atravessa shadow roots abertos (os elementos personalizados XUL do Zotero mantêm internos em shadow DOM). Limitação: não pode dispensar um diálogo modal nativo bloqueante (
Services.prompt.confirmEx) — seu loop modal aninhado bloqueia o thread de eval no qual essas ferramentas rodam.
Execução de JavaScript — Executar código no contexto do Zotero
| Ferramenta | Descrição |
|---|---|
zotero_execute_js | Executar JavaScript no contexto privilegiado do Zotero. Auto-encapsula código com declarações return de nível superior em IIFE. |
zotero_inspect_object | Explorar APIs do Zotero — listar métodos e propriedades de qualquer objeto (ex.: Zotero.Items) |
zotero_open_preferences | Abrir a janela de configurações do Zotero, opcionalmente em um painel específico (integrado ou plugin) |
zotero_search_prefs | Pesquisar/descobrir preferências por padrão (ex.: encontrar todas as prefs contendo "debug") |
zotero_get_pref | Obter um valor de preferência |
zotero_set_pref | Definir um valor de preferência |
Exemplos:
Zotero.Items.getAll(1),Zotero.Prefs.get('export.quickCopy.setting'),ZoteroPane.getSelectedItems()Dica: Use
zotero_inspect_objectpara explorar APIs antes de escrever código. Usezotero_search_prefspara descobrir chaves de preferência.
Build e Scaffold — Integração com zotero-plugin-scaffold
| Ferramenta | Descrição |
|---|---|
zotero_scaffold_build | Compilar plugin (modo dev ou produção) |
zotero_scaffold_serve | Iniciar servidor de desenvolvimento com hot reload |
zotero_scaffold_lint | Executar ESLint no código-fonte do plugin |
zotero_scaffold_typecheck | Executar verificação de tipos TypeScript |
Logs e Depuração — Console de erros e saída de depuração
| Ferramenta | Descrição |
|---|---|
zotero_read_logs | Ler saída de depuração (Zotero.debug) |
zotero_read_errors | Ler entradas do console de erros |
zotero_watch_logs | Transmitir logs em tempo real |
zotero_clear_logs | Limpar buffer de log |
Gerenciamento de Plugins — Instalar, recarregar, inspecionar
| Ferramenta | Descrição |
|---|---|
zotero_plugin_reload | Recarregar a quente seu plugin de desenvolvimento |
zotero_plugin_install | Instalar plugin a partir do caminho XPI |
zotero_plugin_list | Listar plugins instalados com versão/status |
Acesso ao Banco de Dados — Acesso SQLite somente leitura
| Ferramenta | Descrição |
|---|---|
zotero_db_query | Executar consulta SELECT no zotero.sqlite |
zotero_db_schema | Obter informações de esquema de tabela |
zotero_db_stats | Obter estatísticas do banco de dados (itens, anexos, coleções, tamanho) |
Nota: O acesso ao banco de dados é somente leitura e requer que o Zotero esteja fechado, ou usa uma cópia do banco de dados.
🏗️ Arquitetura
┌─────────────────────────────────────────────────────────────────┐
│ 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 que essa abordagem?
- ✅ Plugin leve — Apenas habilita RDP, o Firefox DevTools faz o resto
- ✅ Zero configuração após instalação — Basta abrir o Zotero normalmente, sem flags especiais
- ✅ Contexto rico para IA — Capturas de tela, DOM e logs ajudam a IA a entender o estado do seu plugin
- ✅ Hot reload — Integra-se com zotero-plugin-scaffold para feedback instantâneo
- ✅ Acesso total ao Zotero — Execute qualquer API do Zotero no contexto privilegiado
- ✅ Multiplataforma — Funciona em Linux, Windows, macOS
🔧 Variáveis de Ambiente
| Variável | Descrição | Padrão |
|---|---|---|
ZOTERO_RDP_PORT | Porta de depuração remota | 6100 |
ZOTERO_RDP_HOST | Host de depuração | 127.0.0.1 |
ZOTERO_DATA_DIR | Caminho para o diretório de dados do Zotero | Detecção automática |
ZOTERO_PROFILE_PATH | Caminho para o perfil do Zotero | Detecção automática |
🔌 Alterando a Porta RDP
A ponte escuta na porta 6100 por padrão. Você só precisa alterá-la se executar duas instâncias do Zotero ao mesmo tempo (um perfil normal e um de desenvolvimento, por exemplo), ou se outro processo já estiver usando a 6100.
A porta existe em ambos os lados da ponte, e ambos precisam concordar com ela.
1. Lado do Zotero — defina a preferência do plugin:
- Configurações → Avançado → Editor de Configuração, e aceite o aviso
- Pesquise por
extensions.mcp-rdp.port - Se não existir, crie: selecione Número, nomeie como
extensions.mcp-rdp.porte insira sua porta - Reinicie o Zotero — o listener só abre na inicialização
Cuidado com o tipo. O Editor de Configuração pré-seleciona Booleano. Criar a preferência sem alternar para Número armazena
trueem vez de uma porta, e o Zotero então abre a ponte em um pipe local em vez de uma porta TCP — o log de depuração relata sucesso enquanto nenhum cliente MCP consegue conectar.
2. Lado do cliente — defina ZOTERO_RDP_PORT com o mesmo valor na configuração do seu cliente MCP:
{
"mcpServers": {
"zotero-dev": {
"command": "npx",
"args": ["-y", "@introfini/mcp-server-zotero-dev@1.1.2"],
"env": {
"ZOTERO_RDP_PORT": "6101"
}
}
}
}
Altere ambos ou nenhum. Mover apenas um lado desconecta a ponte: o Zotero escuta em uma porta enquanto o cliente continua discando a outra.
Executando duas instâncias de fato
Iniciar o Zotero uma segunda vez entrega a janela que você já tem — como o Firefox, ele encaminha para a instância em execução em vez de iniciar outra. Uma segunda instância precisa de seu próprio perfil e -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
Dê a esse perfil seu próprio extensions.mcp-rdp.port e as duas pontes ficarão fora do caminho uma da outra. Verificado com 9.0.6 na 6100 e 10.0-beta.22 na 6101 ao mesmo tempo.
Requer plugin MCP Bridge 1.0.5 ou posterior. Em 1.0.4 e anteriores,
extensions.mcp-rdp.portera lido sob o branch de preferência errado e silenciosamente ignorado, então a ponte permanecia na 6100 independentemente do que você definisse. Se você configurou uma porta personalizada contra uma versão mais antiga, ela está armazenada comoextensions.zotero.extensions.mcp-rdp.port— esse nome ainda funciona, mas prefira o acima.
Desabilitando a ponte
Defina extensions.mcp-rdp.enabled como false (Booleano) no Editor de Configuração e reinicie o Zotero. O plugin permanece instalado, mas não abre listener, e nenhum cliente MCP consegue alcançar o Zotero até que você o defina de volta para true.
Verificando o que a ponte fez
O plugin acrescenta uma linha por transição de ciclo de vida em mcp-rdp-events.log no diretório do perfil do seu Zotero: inicialização, listener aberto, listener fechado, listener recuperado, listener oscilando, desligamento. Ele sobrevive a reinicializações e é legível sem o Zotero em execução, o que o torna o primeiro lugar para olhar quando um cliente MCP relata 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
O que ler dele:
listener DOWN … failed to open at startup— outra coisa está ocupando a porta: outra instância do Zotero, uma anterior que não a liberou, ou um processo que responde na porta sem falar RDP. O motivo após os dois pontos indica qual das duas últimas opções é.listener DOWN … stopped answering— o listener estava ativo e depois caiu. A verificação de saúde o reabre; a próxima linha informa quando isso funcionou e por quanto tempo foi a lacuna.listener RECOVERED … after N failed checks— a ponte voltou sozinha. Um N grande significa que a porta ficou ocupada por muito tempo; nada é registrado por tentativa, então o arquivo permanece curto, não importa a duração da interrupção.listener FLAPPING, depois fechado porlistener STEADY … after N flaps— o listener continua caindo e voltando imediatamente na primeira reabertura. Isso é uma falha diferente de uma interrupção: a porta é sua, algo está derrubando o listener. A execução inteira custa essas duas linhas, não importa quanto tempo dure, então N é o número a relatar se você abrir um problema.- Um
startupsemshutdownantes — o Zotero foi encerrado ou travou em vez de sair corretamente. Geralmente, a resposta para "a ponte parou de funcionar" é simplesmente que o Zotero não está em execução. - Nenhuma linha nova — o plugin nunca iniciou: desativado por preferência ou não instalado no perfil que você está realmente executando.
A saída de log() vai para dump() (perdida, a menos que o Zotero tenha sido iniciado a partir de um console) e Zotero.debug() (um no-op, a menos que a saída de depuração esteja habilitada), então este arquivo é o único registro durável de uma falha na inicialização. Uma sessão saudável adiciona três linhas (inicialização, abertura, encerramento); uma interrupção adiciona mais duas, e uma sequência de flutuações mais duas, independentemente da duração. Nenhum modo de falha escreve por tick.
📸 Exemplos de Capturas de Tela
// 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"]' });
🧑💻 Desenvolvimento
# 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
Estrutura do Projeto
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
- Arquitetura e Aprendizados Técnicos — Aprofundamento no protocolo RDP, hierarquia de atores e armadilhas comuns
- Desenvolvimento de Plugins para Zotero — Documentação oficial
- Zotero 10 para Desenvolvedores — Guia de migração para a versão principal mais recente
- Zotero 7 para Desenvolvedores — Guia de migração
- zotero-plugin-scaffold — Ferramentas de build
- zotero-plugin-template — Modelo inicial
- zotero-plugin-toolkit — Auxiliares de API
- Protocolo RDP do Firefox — Documentação do protocolo
🤝 Contribuindo
Contribuições são bem-vindas. Veja CONTRIBUTING.md para configuração, convenções de teste e as regras específicas do código que vale a pena conhecer antes de começar.
A versão resumida:
- Siga os padrões de código existentes
- Adicione testes para novos recursos e pule em vez de falhar quando o Zotero não estiver em execução
- Atualize a documentação
- Não há CI, então execute
npm run build,npm run typecheck,npm run lintenpm testvocê mesmo e informe no PR qual versão do Zotero você verificou
📄 Licença
MIT © introfini
Agradecimentos
- Construído para a comunidade de desenvolvedores de plugins do Zotero
- Integra-se com zotero-plugin-scaffold por @windingwind
- Utiliza o Firefox DevTools RDP para comunicação confiável