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

License: MIT Zotero 7+

Arquitetura · Começando · Ferramentas Disponíveis

MCP Server Zotero Dev in action

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

CategoriaCapacidades
🎯 Inspeção de UICapturas de tela, árvore DOM, localização de elementos, estilos computados
🖱️ Interação com UIClicar em elementos e digitar texto (ciente de shadow DOM)
💻 Execução de JSExecutar código no contexto do Zotero, inspecionar APIs, testar trechos
🔧 Ferramentas de BuildIntegração de scaffold para build, serve, hot reload
📋 Logs e ErrosTransmitir saída de depuração, console de erros, monitorar problemas
🗃️ Banco de DadosAcesso somente leitura ao zotero.sqlite para depuração
🔌 Gerenciamento de PluginsInstalar, 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 o npx armazenou em cache e não receberá novos lançamentos, então sempre inclua uma versão e -y (sem -y, o npx fica pendurado aguardando um prompt de instalação). Aumente a versão fixada para atualizar, ou use @latest para 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 o install-mcp pode gravar uma configuração sem -y ou 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:

  1. No Zotero: Ferramentas → Plugins
  2. Clique em ⚙️ → Instalar Plugin a partir de Arquivo
  3. Selecione o arquivo .xpi baixado
  4. 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
FerramentaDescrição
zotero_screenshotCapturar capturas de tela de janela, elemento ou região
zotero_inspect_elementEncontrar elementos por seletor CSS
zotero_get_dom_treeObter estrutura DOM de uma janela/painel
zotero_get_stylesObter estilos CSS computados para elemento
zotero_list_windowsListar 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 highlightSelector para adicionar uma borda vermelha antes da captura.

Interação com UI — Clicar e digitar na interface do Zotero
FerramentaDescrição
zotero_click_elementClicar 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_keysDigitar 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
FerramentaDescrição
zotero_execute_jsExecutar JavaScript no contexto privilegiado do Zotero. Auto-encapsula código com declarações return de nível superior em IIFE.
zotero_inspect_objectExplorar APIs do Zotero — listar métodos e propriedades de qualquer objeto (ex.: Zotero.Items)
zotero_open_preferencesAbrir a janela de configurações do Zotero, opcionalmente em um painel específico (integrado ou plugin)
zotero_search_prefsPesquisar/descobrir preferências por padrão (ex.: encontrar todas as prefs contendo "debug")
zotero_get_prefObter um valor de preferência
zotero_set_prefDefinir um valor de preferência

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

Dica: Use zotero_inspect_object para explorar APIs antes de escrever código. Use zotero_search_prefs para descobrir chaves de preferência.

Build e Scaffold — Integração com zotero-plugin-scaffold
FerramentaDescrição
zotero_scaffold_buildCompilar plugin (modo dev ou produção)
zotero_scaffold_serveIniciar servidor de desenvolvimento com hot reload
zotero_scaffold_lintExecutar ESLint no código-fonte do plugin
zotero_scaffold_typecheckExecutar verificação de tipos TypeScript
Logs e Depuração — Console de erros e saída de depuração
FerramentaDescrição
zotero_read_logsLer saída de depuração (Zotero.debug)
zotero_read_errorsLer entradas do console de erros
zotero_watch_logsTransmitir logs em tempo real
zotero_clear_logsLimpar buffer de log
Gerenciamento de Plugins — Instalar, recarregar, inspecionar
FerramentaDescrição
zotero_plugin_reloadRecarregar a quente seu plugin de desenvolvimento
zotero_plugin_installInstalar plugin a partir do caminho XPI
zotero_plugin_listListar plugins instalados com versão/status
Acesso ao Banco de Dados — Acesso SQLite somente leitura
FerramentaDescrição
zotero_db_queryExecutar consulta SELECT no zotero.sqlite
zotero_db_schemaObter informações de esquema de tabela
zotero_db_statsObter 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ávelDescriçãoPadrão
ZOTERO_RDP_PORTPorta de depuração remota6100
ZOTERO_RDP_HOSTHost de depuração127.0.0.1
ZOTERO_DATA_DIRCaminho para o diretório de dados do ZoteroDetecção automática
ZOTERO_PROFILE_PATHCaminho para o perfil do ZoteroDetecçã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:

  1. Configurações → Avançado → Editor de Configuração, e aceite o aviso
  2. Pesquise por extensions.mcp-rdp.port
  3. Se não existir, crie: selecione Número, nomeie como extensions.mcp-rdp.port e insira sua porta
  4. 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 true em 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.port era 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 como extensions.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 por listener 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 startup sem shutdown antes — 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


🤝 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:

  1. Siga os padrões de código existentes
  2. Adicione testes para novos recursos e pule em vez de falhar quando o Zotero não estiver em execução
  3. Atualize a documentação
  4. Não há CI, então execute npm run build, npm run typecheck, npm run lint e npm test você mesmo e informe no PR qual versão do Zotero você verificou

📄 Licença

MIT © introfini


Agradecimentos