LibreWriter
БесплатноНе проверенLocal stdio MCP server to read and edit open LibreOffice Writer documents through PyUNO. Built for Claude Code and Codex.
Описание
Local stdio MCP server to read and edit open LibreOffice Writer documents through PyUNO. Built for Claude Code and Codex.
README
Servidor MCP stdio local para ler e modificar documentos abertos no LibreOffice Writer através de PyUNO.
Requisitos validados
- Python 3.12.3.
- MCP SDK Python 2.3.0, com a API
mcp.server.mcpserver.MCPServerinspecionada neste ambiente. - PyUNO compatível com o LibreOffice de sistema.
- LibreOffice Writer 24.2.7.2, lançado por
/usr/bin/soffice. - Sessão gráfica X11 para o launcher e os testes GUI. O Writer não é iniciado em modo headless.
Estas são as versões efetivamente validadas. Não mistures PyUNO com outra instalação; o wrapper soffice no PATH pode apontar para LibreOfficeDev.
Instalação
O projeto já contém .venv. Só executa a primeira linha se o ambiente ainda não existir; --system-site-packages é necessário para expor o PyUNO de sistema:
cd /home/yberudev/Documentos/MCP_Project/LibreOffice/Writer/MCPProj
python3.12 -m venv --system-site-packages .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python -m pip install -e .
Para executar também a integração GUI, instala a dependência Python de teste: .venv/bin/python -m pip install -e '.[test]'. O wmctrl é uma dependência de sistema (por exemplo, sudo apt install wmctrl em Debian/Ubuntu).
PyUNO deve corresponder ao LibreOffice instalado. Em Debian/Ubuntu costuma ser fornecido por python3-uno; a exposição ao venv varia por distribuição. Verifica:
/usr/bin/soffice --version
.venv/bin/python -c 'import uno; from mcp.server.mcpserver import MCPServer; print(uno.__file__, MCPServer)'
Iniciar Writer com listener local (Modo B)
O launcher usa /usr/bin/soffice, cria uma sessão gráfica com perfil isolado e escuta apenas em 127.0.0.1. Sem --profile, usa ~/.local/share/yberu-writer-mcp/profile-PORTA.
cd /home/yberudev/Documentos/MCP_Project/LibreOffice/Writer/MCPProj
.venv/bin/python scripts/launch_writer.py --port 2002 --profile "$HOME/.local/share/yberu-writer-mcp/profile" --wait 25 --json
O comando devolve PID, porta e perfil. O Writer continua aberto quando o MCP termina; fecha esta sessão pela interface gráfica. Para uma segunda sessão, configura outra porta e perfil. O launcher recusa porta ocupada. Não usa --headless e não força SAL_USE_VCLPLUGIN=gen.
Uma janela Writer normal não aceita automaticamente ligações UNO externas.
Ligar a uma sessão existente (Modo A)
Só funciona se a instância já tiver sido iniciada com listener UNO local. Configura YBERU_WRITER_PORT para a porta desse listener. Acrescentar --accept depois de uma sessão normal estar aberta pode apenas encaminhar o pedido para a instância sem criar o listener. O servidor não encerra sessões externas.
Iniciar o servidor MCP
O stdout é reservado às mensagens MCP; os logs técnicos vão para stderr.
cd /home/yberudev/Documentos/MCP_Project/LibreOffice/Writer/MCPProj
PYTHONPATH=/home/yberudev/Documentos/MCP_Project/LibreOffice/Writer/MCPProj/src \
YBERU_WRITER_HOST=127.0.0.1 YBERU_WRITER_PORT=2002 \
.venv/bin/python -m yberu_writer_mcp.server
Normalmente o Codex inicia este processo. Terminar o processo MCP remove listeners quando possível, mas não fecha o Writer.
Registar no Codex
Neste ambiente, yberu_writer foi registado em ~/.codex/config.toml, com o ambiente virtual, caminhos absolutos, timeouts e política default_tools_approval_mode = "writes". Esse registro global permite descobrir as ferramentas também quando o workspace aberto no Codex é a pasta pai Writer. O arquivo local .codex/config.toml é específico desta máquina e fica fora do Git. Para instalar noutro checkout, adapta docs/codex-mcp-config.example.toml. As ferramentas de leitura/prévia declaram-se read-only; as mutações declaram-se mutáveis/destrutivas para que o Codex peça aprovação segundo essa política.
O Codex carrega configurações .codex/ locais somente para projetos confiáveis. Este repositório está marcado como confiável em ~/.codex/config.toml; a configuração global do servidor faz com que ele também seja carregado fora deste projeto. A documentação oficial do MCP no Codex descreve a configuração local e a condição de projeto confiável.
Confirma a descoberta com codex mcp list e, no Codex, chama writer_get_state, writer_list_documents e writer_read_document sobre um documento de teste. Para verificar escrita, lê writer_read_structure, gera uma prévia com writer_preview_change e confirma a operação com o token devolvido. O CLI já lista yberu_writer como habilitado neste ambiente.
Neste ambiente, o Codex usa pastas dedicadas: /home/yberudev/.local/share/yberu-writer-mcp/saves para gravação, /home/yberudev/.local/share/yberu-writer-mcp/images para imagens e /home/yberudev/.local/share/yberu-writer-mcp/templates para modelos. Para permitir gravação noutro ambiente, configura YBERU_WRITER_ALLOWED_SAVE_ROOTS com pastas locais existentes. writer_save_document grava um ficheiro existente; writer_save_as grava num destino novo, aceita ODT/DOCX/RTF/TXT e exige confirmação adicional para substituir um destino existente. Sem allowlist, ambas recusam a gravação.
Para inserir imagens, define YBERU_WRITER_ALLOWED_IMAGE_ROOTS com uma ou mais pastas locais autorizadas. Neste ambiente foi preparada /home/yberudev/.local/share/yberu-writer-mcp/images; cria a pasta e coloca nela a imagem que pretendes usar. O servidor aceita PNG, JPEG, GIF e BMP até YBERU_WRITER_MAX_IMAGE_BYTES. A imagem é incorporada no documento, não ligada ao caminho original.
Ferramentas disponíveis
| Ferramenta | Função |
|---|---|
writer_get_state |
Ligação, versão LibreOffice, documento ativo, contagem e capacidades. |
writer_list_documents |
IDs opacos, título, modificado, leitura/escrita e revisão. |
writer_read_document |
Texto em fatias limitadas sem montar outra cópia integral; revisão, hash e referência de conteúdo. |
writer_read_selection |
Seleção textual, múltiplos ranges, não textual ou nenhuma seleção. |
writer_read_structure |
Parágrafos, títulos, níveis, estilos, tabelas e referências separadas para frames, bookmarks, secções, cabeçalhos/rodapés, notas e campos quando expostos pelo UNO. |
writer_read_text_range |
Lê intervalo delimitado por âncoras de parágrafo e offsets Unicode. |
writer_preview_change |
Valida uma escrita sem mutar e emite token de confirmação válido por 120 segundos. |
writer_insert_text |
Insere no início/fim/offset de um parágrafo ancorado após confirmação da prévia. |
writer_replace_range |
Substitui exatamente um parágrafo ou intervalo lido após confirmação da prévia. |
writer_read_table |
Lê matriz e hashes das células de uma tabela ancorada. |
writer_replace_table_cell |
Substitui uma célula identificada, verificando revisão e conteúdo esperado. |
writer_apply_style |
Aplica estilo de parágrafo existente a um parágrafo ancorado. |
writer_save_document |
Guarda ficheiro local existente, alterado e sob raiz autorizada. |
writer_undo_last_change |
Desfaz a última ação MCP só se continuar no topo da pilha Writer. |
writer_preview_create_document |
Valida e mostra a prévia de um documento novo sem ainda o criar. |
writer_create_document |
Cria um documento Writer novo, inicialmente sem gravação em disco, com parágrafos opcionais. |
writer_preview_compose_document / writer_compose_document |
Pré-visualiza e cria um documento a partir de blocos de títulos, parágrafos, tabelas e imagens. |
writer_apply_formatting |
Aplica negrito, itálico, sublinhado, fonte, tamanho, cor e alinhamento a um parágrafo ancorado. |
writer_insert_table |
Insere tabela nativa após um parágrafo ancorado, com dimensões e valores de células opcionais. |
writer_insert_image |
Incorpora uma imagem local autorizada após um parágrafo, com texto alternativo e dimensões opcionais. |
writer_edit_table_structure |
Insere/remove linhas ou colunas após mostrar os valores afetados. |
writer_format_table_cell |
Formata uma célula específica sem alterar o texto ou as outras células. |
writer_update_image |
Atualiza texto alternativo, dimensões ou alinhamento de uma imagem identificada. |
writer_preview_create_from_template / writer_create_from_template |
Pré-visualiza e cria um documento novo a partir de um ODT/OTT autorizado. |
writer_save_as |
Grava um documento aberto num novo destino local dentro da allowlist. |
Eventos MCP
writer_list_documents inclui um event_uri por documento. Clientes que suportam subscriptions/listen podem subscrever esse URI e recebem uma notificação ResourceUpdated quando o Writer sinaliza alteração, seleção ou ciclo de vida. A notificação indica que o estado mudou; não contém texto antigo/novo. Depois da notificação, lê o recurso para obter a sequência, os tipos coalescidos e a revisão atual:
from mcp.client.subscriptions import listen
async with listen(session, resource_subscriptions=[document["event_uri"]]) as events:
event = await anext(events)
latest = await session.read_resource(event.uri)
O recurso yberu-writer://documents/{document_id}/events contém apenas metadados, sem o texto do documento. A fila coalesce eventos e não guarda histórico; após reconexão ou perda da subscrição, volta a ler a lista/estado. Clientes que não suportam subscriptions/listen podem continuar a ler as ferramentas normalmente, mas não recebem atualizações push.
Fluxo de edição
- Usa
writer_list_documentspara escolher o documento. - Usa
writer_read_structurepara obterrevision,anchore texto. - Chama
writer_preview_changecom a operação e argumentos exatos. A ferramenta não altera o documento; mostra o antes/depois e emite um token ligado ao payload, revisão e documento. - Chama a ferramenta de escrita correspondente com esse
confirmation_token, umoperation_idUUID novo e os mesmos argumentos. Todos os endpoints de escrita recusam chamadas sem token válido. - Para intervalos, obtém
range_anchorporwriter_read_text_range. Para tabelas, lê a estrutura/célula e passa a célula e conteúdo esperado à prévia. - Relê a estrutura para confirmar e obter âncoras novas.
Para reverter uma ação MCP, chama writer_preview_change com change_type="undo_last_change" e a revisão atual; confirma com writer_undo_last_change, usando target_operation_id e token devolvidos. O undo recusa-se a agir se houver uma ação do utilizador no topo da pilha Writer. Tokens expiram após 120 segundos, são de uso único e ficam apenas em memória do processo. Uma repetição com o mesmo operation_id continua idempotente.
Âncoras de parágrafo, intervalo e tabela são temporárias e não podem ser reutilizadas após edição/revisão. Escritas obsoletas retornam CONFLICT; o servidor nunca procura texto aproximado. Intervalos que atravessam estruturas Writer não suportadas são recusados com RANGE_UNSUPPORTED.
Criar e compor um documento
- Chama
writer_preview_create_documentcomtitlee, opcionalmente,initial_paragraphs. - Chama
writer_create_documentcom os mesmos valores, oconfirmation_tokenda prévia e umoperation_idUUID novo. A resposta contém odocument_id, a revisão inicial e o hash do snapshot. - Chama
writer_read_structurepara obter uma âncora de parágrafo e a revisão atual. - Para uma tabela, chama
writer_preview_changecomchange_type="insert_table", documento, âncora, revisão, número de linhas/colunas e, se desejado,cell_values; depois confirma comwriter_insert_tableusando os mesmos argumentos, token e UUID. - Para uma imagem, chama
writer_preview_changecomchange_type="insert_image",image_pathdentro da allowlist ealt_text; depois chamawriter_insert_imagecom o mesmo caminho, oimage_hashdevolvido pela prévia comoexpected_image_hash, além do token e UUID.width_mmeheight_mmsão opcionais, mas devem ser fornecidos juntos. - Relê a estrutura/tabela para confirmar o resultado e obter âncoras e revisão atualizadas.
Tabelas aceitam de 1 a 100 linhas/colunas, limitadas também por YBERU_WRITER_MAX_TABLE_CELLS (padrão 500 células). A criação do documento não escolhe um caminho nem grava automaticamente; o novo documento permanece aberto e sem nome de ficheiro até ser guardado manualmente no Writer.
Para criar uma composição completa, envia blocks como lista ordenada. Cada bloco tem type e campos específicos: paragraph usa text; heading usa text e level (1–10); table usa uma matriz rows; image usa image_path, opcionalmente alt_text, width_mm e height_mm. A mesma prévia confirma o documento inteiro. Se uma composição falhar, o servidor tenta fechar o documento parcial que acabou de criar.
Formatação e elementos estruturais
Para formatar um parágrafo ou célula, obtém texto, âncora e revisão atuais, gera writer_preview_change com change_type="apply_formatting" ou "format_table_cell" e confirma com a ferramenta correspondente. As propriedades aceites são bold, italic, underline, font_name, font_size_pt (6–96), font_color (#RRGGBB) e alignment (left, center, right, justify).
Para ajustar tabela, usa change_type="edit_table_structure", table_operation (insert_rows, delete_rows, insert_columns, delete_columns), index zero-based e count. A prévia mostra dimensões e conteúdo removido; a confirmação inclui o hash da tabela. A operação mantém pelo menos uma linha e uma coluna.
Para atualizar uma imagem, usa o object_ref e a revisão devolvidos por writer_read_structure. A prévia change_type="update_image" devolve image_record_hash; passa-o como expected_image_hash para confirmar a atualização. Imagens continuam incorporadas no documento.
Criar a partir de modelos
Configura YBERU_WRITER_ALLOWED_TEMPLATE_ROOTS com as pastas de modelos autorizadas. writer_preview_create_from_template valida o pacote, tamanho e hash; writer_create_from_template abre uma cópia editável sem gravar sobre o modelo. São aceites .odt e .ott, com execução de macros desativada durante o carregamento. O título pode ser definido na prévia.
Configuração do servidor
| Variável | Padrão | Descrição |
|---|---|---|
YBERU_WRITER_HOST |
127.0.0.1 |
Loopback apenas (127.0.0.1, localhost, ::1). |
YBERU_WRITER_PORT |
2002 |
Porta do listener UNO. |
YBERU_WRITER_SOFFICE |
/usr/bin/soffice |
Executável usado pelo launcher. |
YBERU_WRITER_ALLOWED_SAVE_ROOTS |
vazio | Raízes permitidas para guardar documentos existentes. |
YBERU_WRITER_ALLOWED_TEMPLATE_ROOTS |
vazio | Raízes permitidas para modelos ODT/OTT. |
YBERU_WRITER_ALLOWED_IMAGE_ROOTS |
vazio | Raízes locais permitidas para inserir imagens. |
YBERU_WRITER_MAX_IMAGE_BYTES |
10000000 |
Tamanho máximo de uma imagem de entrada. |
YBERU_WRITER_MAX_TEMPLATE_BYTES |
50000000 |
Tamanho máximo compactado do modelo. |
YBERU_WRITER_MAX_TABLE_CELLS |
500 |
Número máximo de células por tabela inserida. |
YBERU_WRITER_MAX_READ_CHARS |
20000 |
Máximo por fatia de leitura. |
YBERU_WRITER_MAX_SNAPSHOT_CHARS |
5000000 |
Limite de snapshot para revisão/escrita segura. |
YBERU_WRITER_MAX_STRUCTURE_ITEMS |
2000 |
Máximo de parágrafos na estrutura. |
YBERU_WRITER_MAX_TEXT_CHARS |
100000 |
Máximo para texto de entrada. |
YBERU_WRITER_LOG_LEVEL |
INFO |
Nível dos logs stderr. |
Segurança e erros
As respostas de erro têm código, mensagem, retryability e detalhes quando aplicável. Incluem NOT_CONNECTED, DOCUMENT_NOT_FOUND, INVALID_ANCHOR, CONFLICT, PERMISSION_DENIED, CONFIRMATION_REQUIRED, UNDO_NOT_AVAILABLE, UNKNOWN_OUTCOME, INVALID_ARGUMENT, SIZE_LIMIT e RANGE_UNSUPPORTED.
Um worker serializa UNO. Callbacks UNO só enfileiram notificações; eventos coalescidos invalidam snapshots e atualizam a revisão local. XModifyListener não representa deltas. IDs ficam inválidos após reconexão. Escritas exigem uma prévia correspondente, token de confirmação de uso único e UUID de idempotência; resultado incerto não é repetido automaticamente.
Não há ferramentas de macros, shell, dispatch arbitrário, código Python ou métodos UNO genéricos. Gravação aceita apenas caminhos locais dentro de raízes autorizadas; destinos remotos não são suportados.
Testes
Testes unitários:
cd /home/yberudev/Documentos/MCP_Project/LibreOffice/Writer/MCPProj
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests/unit -v
Integração com Writer gráfico isolado, cliente MCP stdio real, entrada de teclado X11 e reinício da sessão criada pelo teste:
cd /home/yberudev/Documentos/MCP_Project/LibreOffice/Writer/MCPProj
YBERU_RUN_LIVE_TESTS=1 PYTHONPATH=src .venv/bin/python -m unittest discover -s tests/integration -v
O teste GUI requer DISPLAY, wmctrl e Python Xlib. Usa documentos temporários e termina apenas o grupo de processos que ele iniciou.
Limitações conhecidas
- Edição de intervalo cobre texto do corpo delimitado por âncoras de parágrafo. Intervalos que cruzam estruturas internas Writer não suportadas são recusados. As operações de tabela cobrem células nomeadas de tabelas de primeiro nível; tabelas aninhadas e cabeçalhos/rodapés/frames ainda não são alvo de edição.
- Tabelas são representadas por referências e células; não são achatadas em texto corrido. Frames, bookmarks, secções, cabeçalhos/rodapés, notas e campos são descritos na estrutura, mas ainda não são alvos de edição.
- Revisões são fingerprints locais, não transações nativas. Snapshots são reutilizados até um evento de modificação invalidá-los; cada escrita força uma nova leitura completa imediatamente antes da mutação. Uma alteração externa seguida de restauração textual idêntica entre verificações pode não ser detetada. Não é prometida atomicidade ACID.
- Snapshots acima de
YBERU_WRITER_MAX_SNAPSHOT_CHARScontinuam disponíveis em leitura paginada, mas revisão completa e escritas seguras ficam desativadas para esse documento. - Eventos MCP são notificações coalescidas de recurso, sem histórico e sem deltas de texto. Clientes sem
subscriptions/listendependem de polling. writer_save_documentgrava ficheiros existentes;writer_save_asaceita apenas ODT, DOCX, RTF e TXT em raízes autorizadas. URLs remotas e gravação fora da allowlist não são suportados. A gravação não promete atomicidade ACID.writer_create_documentewriter_compose_documentdeixam o documento aberto e não guardado. Tabelas são de primeiro nível e limitadas a 100 linhas/colunas e ao limite total de células. Imagens locais devem estar numa raiz autorizada, ter até ao tamanho configurado e estar num formato PNG, JPEG, GIF ou BMP reconhecido.- Formatação cobre parágrafos inteiros e células de tabelas de primeiro nível; formatação parcial de texto dentro do mesmo parágrafo ainda não é exposta. Atualização de imagem cobre texto alternativo, dimensões e alinhamento do parágrafo; legendas dedicadas e edição de recorte ainda não estão disponíveis.
- Modelos aceites são pacotes
.odt/.ottválidos dentro deYBERU_WRITER_ALLOWED_TEMPLATE_ROOTS. A allowlist fica vazia por padrão. - Undo cobre só a última mutação MCP verificada e apenas enquanto ela continuar no topo da pilha nativa do Writer. Guardar ficheiro não é reversível pelo undo do Writer.
- Tokens de prévia expiram em 120 segundos e não sobrevivem ao reinício do MCP.
- Modo A depende de listener ativo; Writer aberto normalmente não basta.
Resolução de problemas
connected=false/NOT_CONNECTED: confirma listener e que host/porta coincidem.- Porta ocupada: seleciona outra porta no launcher e no Codex.
- Erro ao importar
uno: alinha PyUNO com/usr/bin/soffice24.2; não uses o wrapper LibreOfficeDev. - Ferramentas não aparecem: verifica caminhos absolutos,
PYTHONPATH, recarrega Codex e executacodex mcp list. CONFLICTouINVALID_ANCHOR: relêwriter_read_structuree usa revisão/âncora atuais.- Gravação recusada: verifica URL local existente e
YBERU_WRITER_ALLOWED_SAVE_ROOTS. - Falha de teste GUI: verifica X11,
wmctrl,DISPLAYe criação da janela com perfil de teste.
Relatório de implementação
Resultados, matriz de testes e limitações pendentes: docs/IMPLEMENTACAO_MVP.md. Os relatórios originais continuam em docs/audit/.
Установка LibreWriter
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/yberudev/LibreWriter-MCPFAQ
LibreWriter MCP бесплатный?
Да, LibreWriter MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для LibreWriter?
Нет, LibreWriter работает без API-ключей и переменных окружения.
LibreWriter — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить LibreWriter в Claude Desktop, Claude Code или Cursor?
Открой LibreWriter на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectServer Sequential Thinking
MCP server for sequential thinking and problem solving
автор: GitHub ActionsUnyly Deploy
Deploy sites and MCP servers to Unyly straight from your AI agent
автор: UnylyAmap Maps Mcp Server
MCP server for using the AMap Maps API
автор: duxiaohuiPayMCP
Lightweight payments layer for MCP servers: turn tools into paid endpoints with a two-line decorator. [PyPI](https://pypi.org/project/paymcp/) · [npm](https://w
автор: blustAIServer For Power BI
Enables exploring Microsoft Fabric / Power BI workspaces and semantic models, and executing ad-hoc DAX queries.
автор: Mitsubishi-FusoGpt Image 2 Mcp
RunAPI GPT Image 2 MCP server for image generation: create tasks, poll results, and check pricing across 1 model from Claude Code, Codex, Cursor, and VS Code.
автор: runapi-aiCompare LibreWriter with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
