logseq-graph-mcp
v0.2.0
Published
Local-only stdio MCP server for safe agent access to any Logseq markdown graph.
Maintainers
Readme
Logseq Graph MCP
Local-only stdio MCP server for safe agent access to Logseq markdown graphs.
The graph root must contain pages/ and may contain journals/. The server
does not bind a network port and does not require a Logseq API, cloud account,
or browser session.
Requirements
- Node.js 20.17.0+ on Node 20, Node.js 22.9.0+ on Node 22, or Node.js 23-26, plus npm for source installs or
npxusage. - A local Logseq graph directory containing
pages/. - Git installed when
LOGSEQ_GIT_GUARD=strictis used for write-capable sessions.
Install From Source
npm install
npm run build
node dist/cli.js --root /path/to/logseq-graphFor local setup validation, set LOGSEQ_ROOT and run:
LOGSEQ_ROOT=/path/to/logseq-graph ./install.shInstall From npm
After publication, the intended one-shot form is:
npx logseq-graph-mcp --root /path/to/logseq-graphMaintenance Commands
The MCP CLI and Living Atlas CLI share the same maintenance shape:
logseq-graph-mcp doctor [--root /path/to/logseq-graph] [--json]
logseq-graph-mcp update [--check|--dry-run|--apply] [--channel latest] [--json]doctor validates the local runtime, package metadata, install mode, built CLI, and optional graph root.
update checks npm release metadata for the selected channel and prints install-mode-aware guidance:
- source checkout:
git pull && npm install && npm run check - npx execution:
npx logseq-graph-mcp@<channel> - npm package install:
npm install -g logseq-graph-mcp@<channel>
Actual mutation requires update --apply plus LOGSEQ_UPDATE_ALLOW_APPLY=1. Source checkouts and npx runs refuse in-place mutation.
Client Configuration
Ready-to-edit examples are available under examples/ for Codex, ChatGPT, and
Claude Desktop.
Claude Desktop configuration:
{
"mcpServers": {
"logseq": {
"command": "npx",
"args": ["logseq-graph-mcp", "--root", "/path/to/logseq-graph"]
}
}
}For local development from a cloned repository:
{
"mcpServers": {
"logseq": {
"command": "node",
"args": ["/path/to/logseq-graph-mcp/dist/cli.js", "--root", "/path/to/logseq-graph"]
}
}
}Tool Surface
Read tools:
list_pagesread_pageread_pagesread_journalsearchbacklinksquery_pagesgraph_status
Safe write tools (default write-capable surface):
submit_write_intentflush_write_intentsget_write_intentlist_write_intentscancel_write_intent
Raw write tools (LOGSEQ_WRITE_MODE=admin_raw only):
update_propertybatch_update_propertydelete_propertyappend_contact_logappend_journal_bulletcreate_stubrename_pagedelete_pageupdate_body_section
Analysis and meta tools:
find_orphansfind_low_degreefind_hubsnode_degreegraph_statsfind_componentsfind_dangling_linksregenerate_index(raw/admin only; submit it as a safe-write intent in default mode)
All tool payloads use { "ok": true, ... } or { "ok": false, "error": "..." }.
MCP clients that negotiate protocol 2025-06-18 or newer receive both structuredContent and a JSON text item in content; older clients receive the JSON text item only.
Safety Model
The server is designed for local subprocess execution under the current user. It should not be exposed as a remote service without a separate authentication and authorization layer.
LOGSEQ_READONLY=1orLOGSEQ_WRITE_MODE=readonlyexposes read tools only.LOGSEQ_WRITE_MODE=intentis the default write-capable mode. Agents submit durable write intents and flush explicit intent IDs; raw mutating tools are hidden.LOGSEQ_WRITE_MODE=admin_rawexposes raw mutating tools for local admin/debug use.- Safe writes persist an operation ledger outside the graph, enforce idempotency keys, revalidate preconditions before mutation, and record git checkpoint metadata.
LOGSEQ_VALIDATE_SCHEMA=block|warn|offcontrols property-key validation.LOGSEQ_DISALLOW_FORCE=1rejects forced schema bypasses.LOGSEQ_VALIDATE_LINKS=block|warn|offcontrols dangling wikilink validation.LOGSEQ_GIT_GUARD=strict|warn|offcontrols clean-tree checks, blast-radius enforcement, and checkpoint commits.- Writes use metadata lockfiles plus atomic temp-file replacement.
- Writes re-read target files inside the lock before mutating.
- Mutations are append-style or property-level where possible.
delete_pagemoves pages intoarchive/YYYY/MM/instead of deleting content.rename_pageleaves a redirect stub by default.- Successful writes audit to today's journal under
Agent activity. - Path traversal and symlink escape protections are enforced.
- Read responses are capped by
LOGSEQ_MAX_RESPONSE_BYTES. - The server writes diagnostics only to local stderr.
- A persistent cache stores frontmatter and graph adjacency outside the graph directory, and file watchers invalidate in-process state after external edits.
- Search uses the optional
re2package when installed, falling back to native JavaScriptRegExpwith length, line, and time caps. regenerate_indexuses the built-in TypeScript index writer by default; graph-provided Python regenerators requireLOGSEQ_ALLOW_EXTERNAL_REGEN=1.
Recommended first call for write-capable sessions:
{ "tool": "graph_status", "arguments": {} }Proceed only when the reported Git state and generated-index state are expected.
Environment
| Variable | Default | Purpose |
| --- | --- | --- |
| LOGSEQ_ROOT | package directory fallback | Graph root containing pages/ |
| LOGSEQ_READONLY | unset | Set 1 to refuse all writes |
| LOGSEQ_WRITE_MODE | intent | readonly, intent, or admin_raw; raw mutating tools are hidden unless admin_raw |
| LOGSEQ_VALIDATE_SCHEMA | block | block, warn, or off |
| LOGSEQ_DISALLOW_FORCE | unset | Set 1 to reject force bypass |
| LOGSEQ_VALIDATE_LINKS | block | block, warn, or off |
| LOGSEQ_GIT_GUARD | strict | strict blocks dirty or oversized writes before checkpoint commits; warn logs violations and still checkpoints; off disables the guard |
| LOGSEQ_GIT_MAX_CHANGED_FILES | 25 | Maximum changed files allowed per guarded write; strict blocks, warn logs and checkpoints |
| LOGSEQ_GIT_MAX_DELETED_FILES | 0 | Maximum deleted files allowed per guarded write; strict blocks, warn logs and checkpoints |
| LOGSEQ_GIT_COMMIT_AUTHOR | local MCP guard author | Author for checkpoint commits |
| LOGSEQ_GIT_GUARD_IGNORE_DIRS | unset | Comma-separated top-level guard ignores |
| LOGSEQ_CACHE_DIR | ~/.cache/logseq-mcp | Persistent frontmatter, adjacency cache, and durable write-intent ledger directory |
| LOGSEQ_WATCH | 1 | Set 0 to disable filesystem watcher invalidation |
| LOGSEQ_LOCK_TIMEOUT_MS | 5000 | Lock acquisition timeout for writes |
| LOGSEQ_MAX_RESPONSE_BYTES | 500000 | Maximum JSON response size |
| LOGSEQ_MAX_REGEX_LEN | 500 | Maximum user regex length |
| LOGSEQ_REGEX_TIMEOUT_S | 2 | Search wall-clock budget |
| LOGSEQ_MAX_SEARCH_LINE | 10000 | Per-line search input cap |
| LOGSEQ_REGEX_ENGINE | auto | auto uses optional re2 when installed; native forces JavaScript RegExp |
| LOGSEQ_ALLOW_EXTERNAL_REGEN | unset | Set 1 to allow a graph-provided scripts/regenerate_graph_index.py |
| LOGSEQ_PYTHON | python3 | Optional executable used by regenerate_index only when a graph ships scripts/regenerate_graph_index.py |
Undoing a Write
Every successful write guarded by Git creates a checkpoint commit with a subject
like mcp-logseq: update_property <txn_id>. To inspect recent MCP writes:
git -C /path/to/logseq-graph log --grep=mcp-logseq --oneline -20To undo one checkpoint safely:
git -C /path/to/logseq-graph revert <commit>Prefer git revert for normal recovery because it preserves history. When a
strict-mode guard violation is reported, the response includes before_head,
commit: null, changed_files, txn_id, and a rollback_hint for emergency
reset workflows. In warn mode, oversized writes still create a checkpoint commit
and record the warning in the commit metadata.
Development
npm install
npm run check
npm run sbomTests use temporary Git-backed Logseq fixture graphs. They do not read or mutate a real graph.
Release
GitHub Actions runs CI, SBOM generation, CodeQL, and dependency review.
Dependabot is configured for npm and GitHub Actions updates. Publishing is
handled by the Release workflow after npm trusted publishing is configured;
see docs/RELEASE.md.
Architecture
The runtime is split into:
src/cli.ts: CLI argument parsing and process entrypoint.src/index.ts: package library exports.src/server.ts: local stdio JSON-RPC/MCP transport.src/logseq.ts: parity-sensitive graph, tool, write-guard, and Git transaction implementation.src/graph/properties.ts: Logseq frontmatter parsing and emission.src/graph/links.ts: wikilink extraction and code-span filtering.src/graph/write-guards.ts: lockfile and atomic-write primitives.src/graph/cache.ts: persistent frontmatter and adjacency cache.src/graph/watch.ts: filesystem watcher invalidation.src/tools/search.ts: optional RE2-backed search regex compilation.src/tool-schemas.ts: strict MCP input schemas for every tool.
The current core keeps compatibility-sensitive graph behavior in one auditable implementation while schemas, graph helpers, search behavior, cache handling, watching, and public module entrypoints live in narrower modules.
Troubleshooting
- Tools list but writes fail with
readonly: removeLOGSEQ_READONLY=1. - Writes fail with a dirty Git error: commit or stash existing graph edits, then retry.
- Unknown property keys fail: add the key to
pages/schema___properties.md, useforce, or changeLOGSEQ_VALIDATE_SCHEMA. - Dangling wikilinks fail: create target stubs first, pass
allow_dangling, or changeLOGSEQ_VALIDATE_LINKS. regenerate_indexfails: by default it uses the built-in TypeScript index writer. If you intentionally enable a graph-providedscripts/regenerate_graph_index.py, setLOGSEQ_ALLOW_EXTERNAL_REGEN=1and ensureLOGSEQ_PYTHONcan run it.
