Logseq MCP Server

Interaja com sua base de conhecimento do Logseq para criar páginas, gerenciar blocos e organizar informações de forma programática.

Documentação

Servidor MCP do Logseq

Transforme seu grafo do Logseq em memória e espaço de trabalho para agentes de IA. Um servidor Model Context Protocol para Logseq com gravações com escopo de segurança, trilha de auditoria no seu diário diário e consultas verificadas expostas como ferramentas. Construído sobre FastMCP (a API de alto nível do pacote oficial mcp).

PyPI Python 3.11+ License: MIT

Logseq Server MCP server

Tem como alvo a versão arquivo/Markdown ("OG") do Logseq — e arquivos de texto simples fazem parte do motivo pelo qual um grafo é uma boa memória para agentes: sincronizável com git, pesquisável, durável, sem aprisionamento. A versão mais nova com banco de dados (SQLite) mudou o esquema subjacente; alguns métodos podem se comportar de forma diferente lá.

Por quê

Agentes precisam de memória durável, e você já mantém uma — seu grafo. A peça que falta é um acesso em que você possa confiar: um agente deve ler amplamente e gravar de forma útil, mas nunca tocar no que não deveria — e nunca fazer nada que você não possa ver. Três escolhas de design tornam isso possível:

  • Gravações com escopo de namespace. Agentes gravam apenas sob seu próprio prefixo (byAgent/ por padrão), além de um canal deliberadamente estreito entre namespaces que não pode mudar nada além do marcador TODO/DOING/DONE de uma tarefa. Páginas na lista negra ficam ocultas e são redigidas em todas as leituras.
  • Trilha de auditoria no seu diário diário. Toda gravação bem-sucedida acrescenta uma linha como 22:30 [[byAgent]] wrote [[byAgent/readingList/...]] ao diário de hoje — revisar o trabalho dos seus agentes vira parte de uma rotina matinal que você já tem.
  • Consultas verificadas como ferramentas. Envie Datalog conhecidamente bom a partir da configuração como ferramentas nomeadas (query_week_plan, …), para que agentes não componham datascript manualmente e modelos mais baratos continuem confiáveis.

Como eu uso

Eu executo uma pequena frota de agentes do Claude Code com este servidor em um Mac mini sempre ligado, contra meu grafo pessoal ativo:

  • Pesquisa noturna. Um link é deixado na lista de leitura pelo celular; à noite um agente o reivindica (status:: researching), lê o artigo — ou faz um clone superficial e lê o repositório — grava um resumo estruturado na página e o muda para read.
  • Briefing matinal. Às 08:30 um modelo pequeno monta um painel de uma página — o que foi lido durante a noite, progresso do plano semanal, tarefas atuais NOW/DOING — e envia uma única notificação push.
  • Um diário para todos. As tarefas do humano e as linhas de auditoria dos agentes se intercalam na mesma nota diária:

A daily note: human tasks and agent audit lines side by side

As páginas que o pesquisador grava — propriedades, resumo, relevância — conectam-se diretamente ao restante do grafo:

A research page written by the nightly agent

flowchart LR
    A[AI agents] -- MCP tools --> S[logseq-mcp]
    S -- HTTP API --> L[Logseq graph]
    S -. audit line per write .-> J[daily journal]
    Y((you)) --> L
    Y -- morning review --> J

Requisitos

  • Um Logseq em execução com o servidor de API HTTP local habilitado (Configurações → Recursos → Servidor de APIs HTTP, depois inicie-o no menu 🔌).
  • Um token de autorização criado nas configurações do servidor de API HTTP.

Uso

Claude Code

Local (stdio), token a partir do ambiente:

claude mcp add logseq --scope user --env LOGSEQ_API_TOKEN=<YOUR_TOKEN> -- uvx mcp-server-logseq

Ou aponte para uma instância remota via Streamable HTTP (como sessões do celular e remotas alcançam um host sem cabeça — veja Transports):

claude mcp add logseq --scope user --transport http http://<host>:8000/mcp \
  --header "Authorization: Bearer <LOGSEQ_MCP_HTTP_TOKEN>"

Claude Desktop

{
  "mcpServers": {
    "logseq": {
      "command": "uvx",
      "args": ["mcp-server-logseq"],
      "env": {
        "LOGSEQ_API_TOKEN": "<YOUR_TOKEN>",
        "LOGSEQ_API_URL": "http://127.0.0.1:12315"
      }
    }
  }
}

Configuração

FonteTokenURL
AmbienteLOGSEQ_API_TOKENLOGSEQ_API_URL (padrão http://localhost:12315)
Sinalizador de CLI--api-key--url

O token é lido do ambiente ou de --api-key; ele nunca é armazenado em código. Um arquivo .env é suportado (veja .env.example).

Arquivo de configuração (opcional)

O comportamento além dos padrões é definido em um arquivo TOML — caminho a partir de LOGSEQ_MCP_CONFIG (padrão ~/.config/logseq-mcp/config.toml). Consultas personalizadas ficam em arquivos EDN ao lado dele. O servidor funciona bem sem arquivo de configuração (padrões seguros, principalmente de leitura); veja examples/config.toml para um exemplo completo anotado.

SeçãoOpções principais
[read]resolve_depth — quão profundo expandir ((block refs))
[write]agent_write_prefix (padrão byAgent), allow_agents_write_any
[search]files_path — pasta do grafo; defina-a para usar o backend ripgrep
[blacklist]pages — páginas (e subpáginas) para ocultar e redigir em todos os lugares
[tasks]allow_status_change — portão para set_task_status
[audit_log]enabled — registra gravações no diário de hoje
[worklog]enabled, namespace, root_block, exclude, agent_namespace, agent_exclude — o canal de registro de trabalho
[queries.<name>]uma consulta nomeada: file/inline query, register_as_tool, …

Segredos e a URL da API permanecem no ambiente, nunca neste arquivo.

Transports

Por padrão, o servidor roda sobre stdio (para Claude Desktop e outros clientes locais). Um transport Streamable HTTP também está disponível para uso remoto/em rede (por exemplo, um cliente de celular):

LOGSEQ_MCP_HTTP_TOKEN=<client-secret> \
  mcp-server-logseq --transport streamable-http --host 0.0.0.0 --port 8000
# MCP endpoint: http://<host>:8000/mcp

Variáveis de ambiente: LOGSEQ_MCP_TRANSPORT, LOGSEQ_MCP_HOST, LOGSEQ_MCP_PORT, LOGSEQ_MCP_HTTP_TOKEN (ou --http-token).

Autenticação

O transport Streamable HTTP exige um token de portador: toda solicitação deve enviar Authorization: Bearer <LOGSEQ_MCP_HTTP_TOKEN>, ou recebe 401. O servidor se recusa a iniciar neste modo sem um token definido. Observe que este é um segredo distinto de LOGSEQ_API_TOKEN:

SegredoDireção
LOGSEQ_API_TOKENeste servidor → Logseq
LOGSEQ_MCP_HTTP_TOKENcliente (celular) → este servidor

⚠️ Um token de portador sobre HTTP simples só é seguro em um canal já criptografado. Não exponha a porta bruta à internet aberta. O caminho fácil para um host doméstico/sem cabeça é Tailscale: instale-o no host e no cliente, e alcance http://<host>.<tailnet>.ts.net:8000/mcp pelo túnel criptografado — sem domínios, nginx ou certificados. (tailscale serve pode adicionar TLS se você quiser https://.)

Docker

Compile uma vez:

docker build -t logseq-mcp .

Teste rápido (efêmero — --rm remove o contêiner ao parar):

docker run --rm -p 8000:8000 \
  -e LOGSEQ_API_TOKEN=<logseq-token> \
  -e LOGSEQ_MCP_HTTP_TOKEN=<client-secret> \
  -e TZ=Europe/Moscow \
  logseq-mcp

Implantação persistente (por exemplo, um Mac mini sem cabeça) — execute uma vez; --restart o traz de volta após reinicializações:

docker run -d --name logseq-mcp --restart unless-stopped -p 8000:8000 \
  -e LOGSEQ_API_TOKEN=<logseq-token> \
  -e LOGSEQ_MCP_HTTP_TOKEN=<client-secret> \
  -e TZ=Europe/Moscow \
  -e LOGSEQ_MCP_CONFIG=/cfg/config.toml \
  -v /path/to/config-dir:/cfg:ro \
  -v "/path/to/your/graph:/graph:ro" \
  logseq-mcp
  • -v .../config-dir:/cfg — pasta que contém seu config.toml (+ queries/, rules/); defina files_path = "/graph" nela para habilitar a busca de arquivos. Omita tanto a montagem quanto LOGSEQ_MCP_CONFIG para executar com os padrões.
  • -v .../graph:/graph — sua pasta do grafo do Logseq (somente leitura), para busca de arquivos.
  • -e TZ=<zone> — hora local para carimbos de data/hora do registro de auditoria (a imagem inclui tzdata; o relógio é UTC caso contrário).

O contêiner serve Streamable HTTP na porta 8000 e fala com um Logseq em execução no host. No Docker Desktop (macOS/Windows), o padrão LOGSEQ_API_URL=http://host.docker.internal:12315 já aponta para o host; no Linux, adicione --add-host=host.docker.internal:host-gateway (ou defina LOGSEQ_API_URL para o IP do host). Certifique-se de que o servidor de API HTTP do Logseq esteja em execução e ouvindo.

Ferramentas

Toda saída de leitura é normalizada para uma forma JSON plana e passa pela lista negra. Leituras resolvem ((block refs)) sem perda (o bloco resolvido mantém uuid/status para que você possa agir sobre ele). Os resultados saem como JSON compacto, e um bloco carrega apenas os campos que possui: os vazios são omitidos, e raw_content aparece apenas quando difere de text — em um diário movimentado, isso é um terço da forma indentada e totalmente chaveada.

Encontrar

  • search — busca de texto completo sobre o conteúdo dos blocos (query, regex?, limit?, case_sensitive?, exclude_journals?). Usa ripgrep sobre files_path quando definido; caso contrário, uma correspondência de conteúdo datascript.
  • find_tasks — blocos de tarefas por markers?, tag?, under_tag? (descendente), page?, priority?, limit?.
  • list_pages — nomes de páginas sob um namespace prefix? (depth? limita níveis). Descobre as páginas filhas de um namespace, que são páginas separadas que o read_page de um pai não mostrará. Apenas estrutura, não conteúdo de blocos.
  • custom_query — executa uma consulta nomeada da configuração (name, inputs?).
  • list_custom_queries — lista as consultas configuradas.
  • datascript_query — executa uma consulta Datalog bruta (query, inputs?, rules?).

Guia

  • get_logseq_guide — retorna o guia autoritativo para consultar/gravar neste grafo (pegadinhas verificadas de Datalog: nomes em minúsculas, descendentes de prefixo, marcador e tipos de dia de diário, tags vs refs, escopo de leitura/gravação). Uma única fonte de verdade localizada junto ao servidor, para que agentes não rederivem (e derivem errado) o comportamento.

Ler

  • read_page — uma página como uma árvore de blocos normalizada (page, depth?). Uma data YYYY-MM-DD lê o diário daquele dia, qualquer que seja o formato de título do grafo; uma página que não existe é um erro, não uma árvore vazia.
  • read_block — um bloco e seus filhos (uuid, depth?).

Gravar (somente namespace do agente)

  • write_note — cria/acrescenta/substitui uma página sob agent_write_prefix (subpath, content?, mode?, properties?).
  • set_page_properties — define/remove propriedades de página (subpath, properties; um valor null remove uma).
  • edit_block — substitui o conteúdo de um bloco (uuid, old_content, new_content). Ler antes de gravar é aplicado: a edição é rejeitada a menos que old_content corresponda ao conteúdo atual exato do bloco. Somente namespace do agente.

Tarefas

  • create_task — cria um bloco de tarefa no namespace do agente (title, agent, project?, marker?, priority?, tags?, plan_page?, blocks_on?, on_page?). A única maneira de criar tarefas — write_note rejeita conteúdo que começa com um marcador de tarefa.
  • set_task_status — muda apenas o marcador de uma tarefa (uuid, status); controlado por [tasks].allow_status_change.

Registro de trabalho (diário de hoje; [worklog].enabled)

Um agente que faz trabalho deve poder dizer isso onde o restante do trabalho é registrado — o diário — na mesma forma que um humano mantém manualmente:

#_worklog
  #_work/dynamo
    ((6a9eb940-758e-4966-a31d-f91e79c35f42))
      17:50 #_agents/claude/work-scout told how to update
  • list_work_projects — o conjunto fechado de projetos sob os quais uma nota pode ser arquivada (os filhos diretos de [worklog].namespace, menos exclude).
  • list_agents — o conjunto fechado de nomes com os quais uma nota pode ser assinada, como <runtime>/<name>: as páginas exatamente dois níveis abaixo do registro de agentes [worklog].agent_namespace (padrão _agents), de qualquer tempo de execução — um novo (_agents/codex/...) não precisa de configuração.
  • add_journal_note — acrescenta HH:MM #<agent> <text> ao diário de hoje sob um projeto (text, work, agent, task?), aninhado sob um ((ref)) quando uma tarefa é fornecida.
  • get_worklog_setup_template — a seção de registro de trabalho para o arquivo de instruções de um agente (CLAUDE.md, AGENTS.md): qual tarefa registrar, quando mudar seu status, como é uma entrada. Chamado apenas quando o usuário pede para configurar isso — "adicione o registro de trabalho ao CLAUDE.md" em qualquer sessão é suficiente. O modelo é worklog_setup.md.

A assinatura fica inline na nota, não como um nível de agrupamento: vários agentes registrando contra um projeto a dividiriam em subárvores paralelas, cada uma com sua própria cronologia. Observe que o servidor não pode autenticar o chamador — toda sessão apresenta o mesmo token de portador — então agent é uma convenção de honestidade validada contra uma lista, não uma identidade. Ela detecta um erro de digitação, não uma farsa. O que a lista PODE garantir é que agentes não podem se adicionar a ela. Duas regras sustentam essa linha. O registro vive fora do prefixo de escrita dos agentes, então write_note não pode criar uma página lá — o servidor se recusa a iniciar se estiver configurado dentro. E apenas páginas que têm um arquivo contam: escrever [[_agents/claude/x]] em qualquer nota faz o Logseq criar uma página apenas de referência, o que de outra forma seria suficiente para registrar um nome. Registrar um agente, portanto, significa criar sua página, manualmente, no Logseq.

Cada cabeçalho é reutilizado apenas enquanto ainda for o último bloco no seu nível: o root_block entre os blocos de nível superior do diário, um grupo de projeto dentro da raiz, uma âncora de tarefa dentro do seu grupo. Um diário é cronológico, e um cabeçalho reutilizado onde quer que esteja continua coletando notas posteriores: uma raiz aberta pela manhã renderizaria uma nota da noite acima das linhas da tarde que a precederam, e com dois agentes em dois projetos uma nota se juntaria ao grupo anterior do seu projeto, acima da linha posterior do outro projeto. Assim que qualquer outra coisa cair após um cabeçalho, a próxima nota abre um novo — então o dia é lido na ordem em que as coisas aconteceram, ao custo de cabeçalhos repetidos quando o trabalho se intercala.

Este é o único canal que escreve fora de agent_write_prefix, então ele troca o confinamento de caminho por um contrato estreito: somente anexação, somente diário de hoje, tudo o que ele cria vive sob um root_block, work deve vir do enum, task deve ser um bloco de tarefa existente, e o servidor carimba a hora (um chamador não pode passar uma, então um agente retomado não pode registrar um relógio lembrado). Texto começando com um marcador de tarefa é rejeitado — use create_task.

Dinâmico

  • query_<name> — cada consulta de configuração com register_as_tool = true é exposta como sua própria ferramenta.

Desenvolvimento

git clone https://github.com/dailydaniel/logseq-mcp.git
cd logseq-mcp
cp .env.example .env   # fill in LOGSEQ_API_TOKEN
uv sync
uv run mcp-server-logseq

Inspecione com o MCP Inspector:

npx @modelcontextprotocol/inspector uv --directory . run mcp-server-logseq

Licença

MIT