mcp-logseq
Memory server
First committed by ergut
Published in ergut/mcp-logseq. Publisher page
351 GitHub stars
What it is
MCP server to interact with LogSeq via its Local HTTP API - enabling AI assistants like Claude to seamlessly read, write, and manage your LogSeq graph.
AutoGineer overview, from the brain’s own files
mcp-logseq is a Model Context Protocol server that bridges AI agents with your local Logseq knowledge base. By leveraging Logseq's local HTTP API, it allows agents to interact with your notes, journals, and project pages without manual exports. It supports standard CRUD operations on pages and blocks, advanced querying, and optional semantic vector search using LanceDB. The server includes robust privacy controls, allowing users to restrict AI access via tags or namespace allow-lists, ensuring sensitive information remains private.
How it works
Memory model: Vector store
AutoGineer overview, from the brain’s own files
The server acts as a bridge between an MCP-compatible AI client and your local Logseq application. It connects to the Logseq HTTP API to read and modify your graph files. It provides a suite of tools for managing pages and blocks, including support for hierarchical structures and markdown parsing. Optionally, it can maintain a local vector database to enable semantic search across your notes, allowing the AI to find information based on meaning rather than just keywords.
| Folder | Role | Files |
|---|---|---|
| assets | attachments | 4 |
| docs | docs | 12 |
| src | source-code | 27 |
| tests | tests | 30 |
The agent reads
- get_page_content evidence: README.md
- get_block evidence: README.md
- find_pages_by_property evidence: README.md
- list_pages evidence: README.md
The agent writes
- create_page evidence: README.md
- update_page evidence: README.md
- update_block evidence: README.md
- insert_nested_block evidence: README.md
- delete_page evidence: README.md
- delete_block evidence: README.md
Requirements
Runtimes: Python >=3.11
Databases: LanceDB
API keys (by name): LOGSEQ_API_TOKEN, MCP_HTTP_AUTH_TOKEN, YOUR_LOGSEQ_TOKEN
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Google Antigravity, Kiro, OpenCode, Amp, Roo Code, Cline, JetBrains Junie, Devin (ex-Windsurf)
Set it up
- Not scanned by AutoGineerIts setup steps could not be read from the brain’s own files. https://github.com/ergut/mcp-logseq/tree/0769877448a2be921c280689f7cf57694ed6b0a0
- Not scanned by AutoGineerIts dependencies are installed by pip or uv when you run it and were not scanned by AutoGineer (7 declared). https://pypi.org/project/mcp-logseq/
First committed by ergut. Published in ergut/mcp-logseq. Licence: MIT License.
Usage
AutoGineer overview, from the brain’s own files
- Connect Claude to your Logseq graph for intelligent knowledge management.
- Automate the creation of meeting notes and task pages.
- Perform semantic searches across your notes to find related concepts.
- Enforce privacy by restricting AI access to specific namespaces or tagged pages.
- “Analyze all my project notes from the past month and create a status summary.”
- The agent reads relevant pages from the Logseq graph and generates a consolidated summary.
- “Find everything I wrote about burnout, even if I didn't use that word.”
- The agent performs a semantic vector search to retrieve notes conceptually related to burnout.
- “Create a new page called 'Today's Standup' with my meeting notes.”
- The agent creates a new page in the Logseq graph with the specified content.
- “Search for 'Q4 planning' and organize all related content into a new overview page.”
- The agent identifies relevant blocks and aggregates them into a new structured page.
Documentation by ergut
<div align="center"> <img src="assets/images/logo.png" alt="MCP LogSeq" width="200" height="200"> <h1>MCP server for LogSeq</h1> <p>Connect Claude to your LogSeq knowledge base. Read, create, and manage pages — with optional semantic vector search and DB-mode graph support.</p> </div>
✨ What You Can Do
Transform your LogSeq knowledge base into an AI-powered workspace! This MCP server enables Claude to seamlessly interact with your LogSeq graphs.
🎯 Real-World Examples
📊 Intelligent Knowledge Management
"Analyze all my project notes from the past month and create a status summary"
"Find pages mentioning 'machine learning' and create a study roadmap"
"Search for incomplete tasks across all my pages"📝 Automated Content Creation
"Create a new page called 'Today's Standup' with my meeting notes"
"Add today's progress update to my existing project timeline page"
"Create a weekly review page from my recent notes"🔍 Smart Research & Analysis
"Compare my notes on React vs Vue and highlight key differences"
"Find all references to 'customer feedback' and summarize themes"
"Create a knowledge map connecting related topics across pages"🧠 Semantic Search (optional, requires vector setup)
"Find everything I wrote about burnout, even if I didn't use that word"
"What notes relate to my thoughts on deep work?"
"Search across my Dutch and English notes for ideas about productivity"🤝 Meeting & Documentation Workflow
"Read my meeting notes and create individual task pages for each action item"
"Get my journal entries from this week and create a summary page"
"Search for 'Q4 planning' and organize all related content into a new overview page"💡 Key Benefits
Zero Context Switching: Claude works directly with your LogSeq data
Preserve Your Workflow: No need to export or copy content manually
Intelligent Organization: AI-powered page creation, linking, and search
Enhanced Productivity: Automate repetitive knowledge work
Semantic Vector Search (optional): Find notes by meaning using local Ollama or hosted OpenAI-compatible embeddings
DB-mode Support (opt-in): Read and write class properties on Logseq DB-mode graphs
🚀 Quick Start
Step 1: Enable LogSeq API
Settings → Features → Check "Enable HTTP APIs server"
Click the API button (🔌) in LogSeq → "Start server"
Generate API token: API panel → "Authorization tokens" → Create new
Step 2: Add to your MCP client (No Installation Required!)
Claude Code
claude mcp add mcp-logseq \
--env LOGSEQ_API_TOKEN=your_token_here \
--env LOGSEQ_API_URL=http://localhost:12315 \
-- uv run --with mcp-logseq mcp-logseqClaude Desktop
Add to your config file (Settings → Developer → Edit Config):
{
"mcpServers": {
"mcp-logseq": {
"command": "uv",
"args": ["run", "--with", "mcp-logseq", "mcp-logseq"],
"env": {
"LOGSEQ_API_TOKEN": "your_token_here",
"LOGSEQ_API_URL": "http://localhost:12315"
}
}
}
}Codex CLI
With uv installed and Logseq's HTTP API running (Step 1), add this to ~/.codex/config.toml:
[mcp_servers.logseq]
command = "uv"
args = ["run", "--with", "mcp-logseq", "mcp-logseq"]
[mcp_servers.logseq.env]
LOGSEQ_API_TOKEN = "YOUR_LOGSEQ_TOKEN"
LOGSEQ_API_URL = "http://127.0.0.1:12315"Replace YOUR_LOGSEQ_TOKEN with your Logseq token. If Codex cannot find uv, run which uv in Terminal and use the full path for command. Keep your token private.
Use the API base address above, without /mcp. Codex runs this adapter through STDIO; the adapter connects to Logseq's regular HTTP API.
Restart Codex, open a new local task, and ask:
Use Logseq to list my journal pages, then read today's journal. Do not change anything.
Keep Logseq and its API server running. Codex starts the adapter automatically—no tunnel or separate Terminal window is needed.
Tested with a Logseq DB graph for page listing and journal retrieval. This setup is for local Codex tasks, not cloud-hosted ChatGPT Chat.
OpenCode
Add to ~/.config/opencode/opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"mcp-logseq": {
"type": "local",
"command": ["uv", "run", "--with", "mcp-logseq", "mcp-logseq"],
"enabled": true,
"environment": {
"LOGSEQ_API_URL": "http://localhost:12315",
"LOGSEQ_API_TOKEN": "your_token_here"
}
}
}
}Step 3: Start Using!
"Please help me organize my LogSeq notes. Show me what pages I have."🔬 Vector Search (Optional)
Semantic search over your Logseq graph using configurable embeddings — find notes by meaning, not just keywords. Searches across all your pages using vector similarity and full-text search combined, with cross-language support.
Use Ollama for fully local embeddings, OpenAI, or another OpenAI-compatible embeddings endpoint. LanceDB remains local in every configuration. Hosted providers receive the note text being embedded.
→ Full setup guide: VECTOR_SEARCH.md
🛠️ Available Tools
The server provides 17 tools with intelligent markdown parsing, plus 3 optional vector search tools:
| Tool | Purpose | Example Use |
|---|---|---|
list_pages | Browse your graph; sort: "updated" / updated_since find recently modified pages | "Which pages did I change this week?" |
get_page_content | Read page content | "Get my project notes" |
create_page | Add new pages with structured blocks | "Create a meeting notes page with agenda items" |
update_page | Modify pages (append/replace modes) | "Update my task list" |
delete_page | Remove pages | "Delete the old draft page" |
delete_block | Remove a block by UUID | "Delete this specific block" |
update_block | Edit block content by UUID | "Update this specific block text" |
get_block | Read a block by UUID with its properties and children | "Show me this specific block" |
search | Find content across graph | "Search for 'productivity tips'" |
query | Execute Logseq DSL queries (raw datalog not supported) | "Find all TODO tasks tagged #project" |
find_pages_by_property | Search pages by property | "Find all pages with status = active" |
get_pages_from_namespace | List pages in a namespace | "Show all pages under Customer/" |
get_pages_tree_from_namespace | Hierarchical namespace view | "Show Projects/ as a tree" |
rename_page | Rename with reference updates | "Rename 'Old Name' to 'New Name'" |
get_page_backlinks | Find pages linking to a page | "What links to this page?" |
insert_nested_block | Insert child/sibling blocks | "Add a child block under this task" |
set_block_properties | Set DB-mode class properties on a block | "Set the status of this block to active" (DB-mode only) |
vector_search ⚗️ | Semantic search by meaning | "Find notes about shadow work or Jung" |
sync_vector_db ⚗️ | Sync vector DB with graph files | "Update the search index" |
vector_db_status ⚗️ | Show vector DB health and staleness | "Is my search index up to date?" |
⚗️ Requires vector search setup — see VECTOR_SEARCH.md
🎨 Smart Markdown Parsing (v1.1.0+)
The create_page and update_page tools now automatically convert markdown into Logseq's native block structure:
Markdown Input:
---
tags: [project, active]
priority: high
---
# Project Overview
Introduction paragraph here.
## Tasks
- Task 1
- Subtask A
- Subtask B
- Task 2
## Code Example
```python
def hello():
print("Hello Logseq!")
```Result: Creates properly nested blocks with:
✅ Page properties from YAML frontmatter (
tags,priority)✅ Hierarchical sections from headings (
#,##,###)✅ Nested bullet lists with proper indentation
✅ Code blocks preserved as single blocks
✅ Checkbox support (
- [ ]→ TODO,- [x]→ DONE)
Update Modes:
append(default): Add new content after existing blocksreplace: Clear page and replace with new content
🔁 Safe Retries & Large Writes
create_page fails with a clear error if a page with the same title already exists, instead of letting Logseq silently create numbered duplicates (Page(1), Page 2, ...). This makes retries after a timeout safe: if a previous create_page call timed out but actually committed, the retry tells you the page exists rather than fragmenting your content across ghost pages.
For large writes, prefer this pattern over one giant create_page call:
Create the page with little or no content (
create_pagewith just the title and properties)Append content in smaller chunks with
update_page(mode: append)Read back with
get_page_contentto verify the result
If you hit the "already exists" error mid-ingest, use get_page_content to see what landed, then continue with update_page instead of re-creating.
⚙️ Prerequisites
LogSeq Setup
LogSeq installed and running
HTTP APIs server enabled (Settings → Features)
API server started (🔌 button → "Start server")
API token generated (API panel → Authorization tokens)
System Requirements
uv Python package manager
MCP-compatible client (Claude Code, Claude Desktop, etc.)
🔧 Configuration
Environment Variables
LOGSEQ_API_TOKEN(required): Your LogSeq API tokenLOGSEQ_API_URL(optional): Server URL (default:http://localhost:12315)LOGSEQ_VERIFY_SSL(optional): Whether to verify the TLS certificate of anhttps://LOGSEQ_API_URL. Defaults to verifying when the URL ishttps://; set to0,false, ornoto skip verification for self-signed certificates. Any other value enables verification.LOGSEQ_API_CONNECT_TIMEOUT(optional): HTTP connect timeout in seconds (default:3)LOGSEQ_API_READ_TIMEOUT(optional): HTTP read timeout in seconds (default:6)LOGSEQ_LOG_LEVEL(optional): Log verbosity —DEBUG,INFO,WARNING,ERROR, orCRITICAL(default:INFO). Logs go to stderr. AtDEBUG, the MCP SDK's own logger stays capped atINFOso full request payloads are not logged.LOGSEQ_LOG_FILE(optional): Path to a log file. When unset (the default), nothing is written to disk. Tool calls are logged with argument names and result sizes only, so page/block content does not appear in routine logs.LOGSEQ_DB_MODE(optional): Set totrueto enable DB-mode property support. Only for Logseq DB-mode graphs (beta). Markdown/file-based graph users should leave this unset.LOGSEQ_EXCLUDE_TAGS(optional): Comma-separated tags — pages with these tags are hidden from all tools. See Privacy & Access Control below.LOGSEQ_INCLUDE_NAMESPACES(optional): Comma-separated namespace allow-list (e.g.work,projects). When set, only pages in these namespaces and their sub-pages are accessible — everything else, including top-level pages without a namespace, is hidden from listings/search and denied on direct access. See Privacy & Access Control below.LOGSEQ_EXCLUDE_NAMESPACES(optional): Comma-separated namespace deny-list (e.g.finance,work/secret). These namespaces are always blocked, taking priority over the include list. See Privacy & Access Control below.LOGSEQ_WRITE_NAMESPACES(optional): Comma-separated write allow-list (e.g.Beren). When set, write tools may only target pages in these namespaces; everything else that is readable stays read-only. Applied on top of the include/exclude rules, never instead of them. See Privacy & Access Control below.LOGSEQ_CONFIG_FILE(optional): Path to a shared JSON config file holding the graph path, ACL defaults, and thevectorblock. Env vars (LOGSEQ_EXCLUDE_TAGS,LOGSEQ_INCLUDE_NAMESPACES,LOGSEQ_EXCLUDE_NAMESPACES,LOGSEQ_WRITE_NAMESPACES) override the matching keys in this file.MCP_HTTP_AUTH_TOKEN(required for--transport http): Bearer token clients must send asAuthorization: Bearer <token>. The server refuses to start in HTTP mode without it. See Serving over HTTP.
Privacy & Access Control
Pages tagged with excluded tags are completely hidden from AI — they won't appear in listings, searches, or queries, and attempting to read them directly returns an access-denied error.
Quick setup via env var:
LOGSEQ_EXCLUDE_TAGS=private,secretVia config file (also used for vector search):
{
"logseq_graph_path": "/path/to/your/logseq/pages",
"exclude_tags": ["private", "secret"]
}Point to it with LOGSEQ_CONFIG_FILE=/path/to/config.json.
In your Logseq pages, tag any page you want to protect:
tags:: privateThe exclusion applies to all tools: list_pages, get_page_content, search, query, and the optional vector search. If you also use vector search, exclude_tags at the root is automatically merged into the vector index exclusion list — private pages are never embedded.
Namespace access control
You can restrict access to specific namespaces using LOGSEQ_INCLUDE_NAMESPACES and LOGSEQ_EXCLUDE_NAMESPACES.
Include list (strict allow-list): Only the listed namespaces and their sub-pages are visible; everything else is hidden.
LOGSEQ_INCLUDE_NAMESPACES=work,projectsExclude list (deny-list): The listed namespaces are always blocked, even if they appear in the include list.
LOGSEQ_EXCLUDE_NAMESPACES=work/secret,financeVia config file:
{
"include_namespaces": ["work", "projects"],
"exclude_namespaces": ["work/secret", "finance"],
"write_namespaces": ["work/drafts"]
}Write list (write allow-list): Everything the read rules allow stays readable, but write tools (create_page, update_page, delete_page, rename_page, update_block, delete_block, insert_nested_block, set_block_properties) may only target pages in these namespaces. Useful when an assistant should read a wider area than it may edit:
LOGSEQ_INCLUDE_NAMESPACES=Family,Beren
LOGSEQ_WRITE_NAMESPACES=Beren # reads Family/* and Beren/*, writes only Beren/*rename_page needs both the old and the new name inside the write list; block tools are checked against the block's owning page (denied if it cannot be resolved). A write outside the list returns "page 'X' is read-only for this assistant". The write list never widens read access: a write namespace not covered by the include list is still denied (a warning is logged at startup). Unset means no extra restriction. Every allowed write is logged at INFO as Write: tool=<name> page=<page name> (names only, never content).
Matching is segment-based and case-insensitive: work matches work and work/projects but not workshop. The behavior mirrors LOGSEQ_EXCLUDE_TAGS: list/search results silently omit blocked pages; direct read, write, delete, and block operations return an access-denied error.
Access control is enforced at the page level and applied across every tool: list/search/query results omit blocked pages, direct page/block access and backlinks are denied, and vector search is filtered. Block-level results from search and query are resolved back to their owning page, so a block belonging to a restricted page is filtered out of those results too.
Index-time namespace scoping (vector DB only). The keys above are query-time: every page is embedded, and blocked ones are filtered out of each response. For the vector DB you can also scope at index time — decide which namespaces are embedded into the DB at all — with include_namespaces / exclude_namespaces inside the vector block of the config file:
{
"vector": {
"enabled": true,
"include_namespaces": ["work"],
"exclude_namespaces": ["work/secret"]
}
}This is global (it shapes the shared DB for every consumer), and it keeps unwanted content off disk entirely rather than filtering it on read — useful for secrets you never want embedded, or to keep the index small when everyone only cares about a subset. Matching is the same segment-based, case-insensitive rule. Because it changes what the index contains, it only takes effect after a full re-index: logseq-sync --rebuild.
🌐 Serving over HTTP, multi-profile & TLS
By default the server speaks stdio — your client spawns it as a subprocess, and most users need nothing more. To serve sandboxed or remote clients over the network, mcp-logseq can run as a long-lived HTTP service with bearer auth, per-profile isolation, and TLS:
mcp-logseq --transport http --host 127.0.0.1 --port 12320 # requires MCP_HTTP_AUTH_TOKENThe full deployment guide — the server-side security model, the per-profile multi-instance pattern, the separate logseq-sync writer, and native TLS / reverse-proxy setup — lives in docs/SERVING.md. Non-loopback binds over plain HTTP are refused unless you supply TLS or pass --insecure.
Alternative Setup Methods
Using .env file
# .env
LOGSEQ_API_TOKEN=your_token_here
LOGSEQ_API_URL=http://localhost:12315System environment variables
export LOGSEQ_API_TOKEN=your_token_here
export LOGSEQ_API_URL=http://localhost:12315🔍 Verification & Testing
Test LogSeq Connection
uv run --with mcp-logseq python -c "
from mcp_logseq.logseq import LogSeq
api = LogSeq(api_key='your_token')
print(f'Connected! Found {len(api.list_pages())} pages')
"Verify MCP Registration
claude mcp list # Should show mcp-logseqDebug with MCP Inspector
npx @modelcontextprotocol/inspector uv run --with mcp-logseq mcp-logseq🐛 Troubleshooting
Common Issues
"LOGSEQ_API_TOKEN environment variable required"
✅ Enable HTTP APIs in Settings → Features
✅ Click 🔌 button → "Start server" in LogSeq
✅ Generate token in API panel → Authorization tokens
✅ Verify token in your configuration
"spawn uv ENOENT" (Claude Desktop)
Claude Desktop can't find uv. Use the full path:
which uv # Find your uv locationUpdate config with full path:
{
"mcpServers": {
"mcp-logseq": {
"command": "/Users/username/.local/bin/uv",
"args": ["run", "--with", "mcp-logseq", "mcp-logseq"],
"env": { "LOGSEQ_API_TOKEN": "your_token_here" }
}
}
}Common uv locations:
Curl install:
~/.local/bin/uvHomebrew:
/opt/homebrew/bin/uvPip install: Check with
which uv
Connection Issues
✅ Confirm LogSeq is running
✅ Verify API server is started (not just enabled)
✅ Check port 12315 is accessible
✅ Test with verification command above
👩💻 Development
For local development, testing, and contributing, see DEVELOPMENT.md.
<div align="center"> <p><strong>Ready to supercharge your LogSeq workflow with AI?</strong></p> <p>⭐ <strong>Star this repo</strong> if you find it helpful!</p> </div>
VECTOR_SEARCH.md
Vector Search Setup Guide
Semantic search over your Logseq graph using local or hosted AI embeddings. Find notes by meaning rather than exact keywords — works across languages and concepts.
Architecture
How It Works
Your
.mdfiles are read directly from disk (not via the Logseq API)Each page is chunked into blocks and embedded using the configured provider
Embeddings are stored in a LanceDB database on your machine
vector_searchqueries combine vector similarity + full-text search with RRF rerankingWhen your notes change, an incremental sync re-embeds only the changed files
LanceDB always runs locally. With Ollama, note text also stays local. OpenAI and other hosted providers receive the chunks and search queries they embed; review the provider's data-handling policy before enabling a hosted service.
Prerequisites
1. Choose an embedding provider
Install Ollama from ollama.com and pull an embedding model:
ollama pull qwen3-embedding:8b # recommended — high quality, 4096 dims
# or
ollama pull nomic-embed-text # lighter alternativeConfirm it's running:
curl http://localhost:11434/api/embed -d '{"model":"qwen3-embedding:8b","input":["test"]}'For a hosted provider, obtain an API key and the provider's embedding model
name. OpenAI works with its default base URL. Other services must expose an
OpenAI-compatible POST /embeddings endpoint and provide the base URL ending in
/v1 (or the equivalent API root).
2. Vector extras
Install the optional vector dependencies. The [vector] extra pulls in LanceDB, PyArrow, and watchdog.
From PyPI (once released):
uv pip install "mcp-logseq[vector]"From source (development):
cd /path/to/mcp-logseq-server
uv pip install -e ".[vector]"Configuration
Create a directory for all vector search files and a config file inside it:
mkdir -p ~/.logseq-vector~/.logseq-vector/config.json (replace logseq_graph_path with the path to your own graph folder):
{
"logseq_graph_path": "~/Library/Mobile Documents/iCloud~com~logseq~logseq/Documents",
"exclude_tags": ["private"],
"vector": {
"enabled": true,
"db_path": "~/.logseq-vector/db",
"embedder": {
"provider": "ollama",
"model": "qwen3-embedding:8b",
"base_url": "http://localhost:11434"
},
"include_journals": true,
"exclude_tags": ["no-index"],
"min_chunk_length": 50
}
}The example above uses Ollama. To use OpenAI instead, replace the embedder
block with:
"embedder": {
"provider": "openai",
"model": "text-embedding-3-small",
"api_key_env": "OPENAI_API_KEY"
}api_key_env names an environment variable to read the API key from at
startup — the recommended way to supply a key, since it never touches disk.
Alternatively, set "api_key": "your-key" to embed the key in the config
file (see the file-permissions note below). When the named variable is set
to a non-blank value, it takes precedence over api_key; if the variable is
unset or blank and no api_key fallback is present, vector search is
disabled with a warning naming the missing variable.
OpenAI defaults to https://api.openai.com/v1. The optional dimensions
field requests a specific output size on models that support it:
"embedder": {
"provider": "openai",
"model": "text-embedding-3-small",
"api_key_env": "OPENAI_API_KEY",
"dimensions": 512
}For another service implementing the OpenAI embeddings contract:
"embedder": {
"provider": "openai-compatible",
"model": "provider-model-name",
"base_url": "https://embeddings.example.com/v1",
"api_key_env": "MY_EMBEDDING_API_KEY"
}A key (via api_key_env or api_key) is optional for openai-compatible,
which allows an unauthenticated local service — omit both fields for that. It
is required for openai. Note that naming a variable in api_key_env commits
to it: if the variable is unset and there is no api_key fallback, vector
search is disabled rather than proceeding unauthenticated.
This keeps everything in one place:
~/.logseq-vector/
config.json ← you edit this
db/ ← generated, do not edit| Field | Required | Description |
|---|---|---|
logseq_graph_path | ✅ | Path to your Logseq graph directory (contains pages/ and journals/) |
exclude_tags | no | Project-level privacy filter — pages with these tags are hidden from all tools (list, search, query, get content) and excluded from the vector index. Use this for pages with sensitive content (e.g. API keys, personal notes). |
vector.enabled | ✅ | Must be true to activate vector tools |
vector.db_path | ✅ | Where to store the vector DB — keep it local, not in iCloud |
vector.embedder.provider | no | ollama (default), openai, or openai-compatible |
vector.embedder.model | provider-dependent | Defaults to nomic-embed-text for Ollama and text-embedding-3-small for OpenAI; required for openai-compatible |
vector.embedder.base_url | provider-dependent | Defaults to local Ollama or OpenAI's API root; required for openai-compatible |
vector.embedder.api_key_env | no | Recommended for hosted providers — name of an environment variable holding the API key (e.g. OPENAI_API_KEY). Takes precedence over api_key when set |
vector.embedder.api_key | provider-dependent | Plaintext key; prefer api_key_env. Required for OpenAI (unless api_key_env is set); optional bearer token for openai-compatible; ignored by Ollama |
vector.embedder.dimensions | no | Positive integer requested from an OpenAI-compatible endpoint; changing it requires a rebuild |
vector.include_journals | no | Index journal pages (default: true) |
vector.exclude_tags | no | Additional tags to skip from the vector index only (additive with top-level exclude_tags). Use for noise filtering — e.g. large reference dumps that pollute semantic search but are fine to read directly. (default: []) |
vector.min_chunk_length | no | Minimum characters per chunk (default: 50) |
vector.max_chunk_length | no | Maximum characters per chunk. Longer blocks are skipped, matching Logseq's own handling of large blocks, since embedding providers reject them (default: 10000) |
Important: keep db_path outside your iCloud-synced Logseq folder. The DB is a generated binary artifact — syncing it to iCloud wastes bandwidth and can cause corruption.
Prefer api_key_env so no key is stored in config.json. If you do use a
plaintext api_key, do not commit or share the file, and restrict it to your
user account, for example with chmod 600 ~/.logseq-vector/config.json.
Multiple graphs
One config file describes one graph. To index several graphs, create one config file per graph, each with its own logseq_graph_path and its own db_path:
~/.logseq-vector/
work.json → "logseq_graph_path": "~/graphs/work", "db_path": "~/.logseq-vector/work-db"
personal.json → "logseq_graph_path": "~/graphs/personal", "db_path": "~/.logseq-vector/personal-db"Then run logseq-sync once per config file, and register one MCP server entry per graph (for example mcp-logseq-work and mcp-logseq-personal), each with LOGSEQ_CONFIG_FILE pointing at its own file. Never share a db_path between two graphs.
Note that only the vector index is per config file. The regular tools (list_pages, get_page_content, and so on) go through Logseq's HTTP API, which always serves whichever graph is currently open in Logseq.
MCP Server Setup
Point the MCP server at your config file via the LOGSEQ_CONFIG_FILE environment variable.
Claude Code
claude mcp add-json mcp-logseq '{
"command": "uv",
"args": ["run", "--with", ".[vector]", "python", "-c", "from mcp_logseq import main; main()"],
"cwd": "/path/to/mcp-logseq-server",
"env": {
"LOGSEQ_API_TOKEN": "your_token",
"LOGSEQ_API_URL": "http://localhost:12315",
"LOGSEQ_CONFIG_FILE": "/Users/you/.logseq-vector/config.json"
}
}' -s localClaude Desktop
{
"mcpServers": {
"mcp-logseq": {
"command": "uv",
"args": ["run", "--with", ".[vector]", "python", "-c", "from mcp_logseq import main; main()"],
"cwd": "/path/to/mcp-logseq-server",
"env": {
"LOGSEQ_API_TOKEN": "your_token",
"LOGSEQ_API_URL": "http://localhost:12315",
"LOGSEQ_CONFIG_FILE": "/Users/you/.logseq-vector/config.json"
}
}
}
}If LOGSEQ_CONFIG_FILE is not set or vector.enabled is false, the vector tools are silently not registered. All other tools work normally.
First Sync
Before using vector_search, you need to build the initial index. This can take several minutes depending on the size of your graph and your embedding model.
export LOGSEQ_CONFIG_FILE=~/.logseq-vector/config.json
uv run --with ".[vector]" python -m mcp_logseq.bin.logseq_sync --onceYou'll see progress as batches of pages are embedded. Check status when done:
uv run --with ".[vector]" python -m mcp_logseq.bin.logseq_sync --statusTalking to Claude
These tools are called by Claude on your behalf — you don't invoke them directly. Just talk naturally:
"Find my notes about shadow work or Jung"
"Search for meeting notes with action items from last week"
"What did I write about machine learning?"
"Is my search index up to date?"Syncing is done outside Claude with the logseq-sync CLI (see below).
MCP Tools Reference
Once the server is restarted with LOGSEQ_CONFIG_FILE set, three new tools are available to Claude.
vector_search
Semantic search across your notes. Claude calls this when you ask it to find notes by topic, concept, or meaning.
| Parameter | Type | Default | Description |
|---|---|---|---|
query | string | required | Natural language query |
top_k | integer | 5 | Number of results (max 20) |
search_mode | string | hybrid | hybrid, vector, or keyword |
filter_tags | array | — | Only return pages with ALL these tags |
filter_page | string | — | Restrict to a single page |
Reading scores: In hybrid (default) and keyword modes the score is a rank-fusion (RRF) or full-text (BM25) score — higher is more relevant, and no relevance label is shown. In vector mode the score is a distance — lower is more relevant — and each result gets a relevance label. If a hybrid or keyword search fails, the server falls back to vector-only and the distance note is shown instead.
Staleness note: vector_search never writes to the index. If files changed since the last sync, the results are prefixed with a note saying how many pages changed and reminding you to run logseq-sync --watch on the host that owns the DB.
sync_vector_db
Does not sync. The vector DB has a single writer, the logseq-sync CLI, so this tool only returns the commands to run on the host that owns the DB (--once, --watch, --rebuild). The rebuild parameter is accepted and ignored.
Run logseq-sync --rebuild if you change the embedding provider, model, or
configured dimensions.
The sync indexes .md files under the graph, except the graph's own logseq/ directory (which holds bak/ backups and .recycle/ deleted pages) and hidden directories. Entries indexed from those locations by older versions are removed on the next sync run.
vector_db_status
Shows the current state of the vector DB. Claude calls this when you ask whether the index is up to date.
Vector DB Status
Embedder: ollama/qwen3-embedding:8b
Dimensions: 4096
Total chunks: 1203
Total pages: 461
Last sync: 2026-03-21T11:21:18Z
Staleness: Up to dateCLI: logseq-sync
For syncing outside of the MCP server — useful for initial indexing, automation, or continuous watch mode.
export LOGSEQ_CONFIG_FILE=~/.logseq-vector/config.json
uv run --with ".[vector]" python -m mcp_logseq.bin.logseq_sync --once # incremental sync and exit
uv run --with ".[vector]" python -m mcp_logseq.bin.logseq_sync --watch # sync on file changes (runs until Ctrl+C)
uv run --with ".[vector]" python -m mcp_logseq.bin.logseq_sync --rebuild # drop DB and re-index from scratch
uv run --with ".[vector]" python -m mcp_logseq.bin.logseq_sync --status # staleness report, no syncFor continuous sync, --watch is the recommended approach. It debounces file system events and re-embeds only changed files.
Troubleshooting
Vector tools not appearing
Confirm
LOGSEQ_CONFIG_FILEis set in the MCP server envConfirm
vector.enabled: truein the config fileCheck the server log: logs go to stderr at
INFO. SetLOGSEQ_LOG_LEVEL=DEBUGfor more detail andLOGSEQ_LOG_FILE=/path/to/file.logto also write to a fileLook for:
Vector search tools registered (3 tools)
"Cannot connect to Ollama"
Confirm Ollama is running:
ollama listConfirm the model is downloaded:
ollama pull qwen3-embedding:8bCheck
base_urlin config matches your Ollama address
Hosted embedding request fails
Confirm
api_key,model, andbase_urlbelong to the same providerFor
openai-compatible, setbase_urlto the API root immediately before/embeddings; for example,https://embeddings.example.com/v1A
401or403usually means the API key is missing, invalid, or lacks access to the selected modelCheck provider rate limits if a sync succeeds for some batches and skips others
Embedder mismatch error on sync
If you change the provider, model, or configured dimensions after an initial sync:
logseq-sync --rebuildThis drops the existing DB and re-indexes from scratch with the new embedding
space. Rotating only api_key does not require a rebuild.
Slow first sync
First-sync time depends on graph size, model size, provider latency, and rate limits. Subsequent incremental syncs are much faster because only changed files are re-embedded.
Pages missing from results
Run vector_db_status to check chunk and page counts. If a page is missing, it may have been skipped due to:
All chunks being under
min_chunk_lengthThe page having a tag listed in
exclude_tags(top-level orvector.exclude_tags)A timeout during the initial sync (run
--onceagain to pick it up)
85 files · 75 not served here
- .gitignore (not served here)
- ATTRIBUTION.md
- CHANGELOG.md
- DEVELOPMENT.md
- LICENSE
- LOGSEQ_API_ARCHITECTURE.md
- README.md
- ROADMAP.md
- TESTING.md
- VECTOR_SEARCH.md
- assets/architecture.dot (not served here)
- assets/images/architecture.png (not served here)
- assets/images/architecture.svg (not served here)
- assets/images/logo.png (not served here)
- docs/SERVING.md
- docs/superpowers/plans/2026-06-14-http-transport-secure-serving.md (not served here)
- docs/superpowers/plans/2026-06-14-namespace-access-control.md (not served here)
- docs/superpowers/plans/2026-06-15-index-time-namespace-scoping.md (not served here)
- docs/superpowers/plans/2026-06-16-tls-serving-and-bind-guardrail.md (not served here)
- docs/superpowers/plans/2026-07-10-pluggable-embedding-providers.md (not served here)
- docs/superpowers/plans/2026-07-11-embedder-api-key-env.md (not served here)
- docs/superpowers/plans/2026-07-19-a5-logging.md (not served here)
- docs/superpowers/specs/2026-06-14-namespace-access-control-design.md (not served here)
- docs/superpowers/specs/2026-07-10-pluggable-embedding-providers-design.md (not served here)
- docs/superpowers/specs/2026-07-11-embedder-api-key-env-design.md (not served here)
- docs/superpowers/specs/2026-07-19-a5-logging-design.md (not served here)
- pyproject.toml (not served here)
- src/mcp_logseq/__init__.py (not served here)
- src/mcp_logseq/access.py (not served here)
- src/mcp_logseq/bin/__init__.py (not served here)
- src/mcp_logseq/bin/logseq_sync.py (not served here)
- src/mcp_logseq/config.py (not served here)
- src/mcp_logseq/logseq.py (not served here)
- src/mcp_logseq/namespace.py (not served here)
- src/mcp_logseq/parser.py (not served here)
- src/mcp_logseq/server.py (not served here)
- src/mcp_logseq/settings.py (not served here)
- src/mcp_logseq/tools/__init__.py (not served here)
- src/mcp_logseq/tools/base.py (not served here)
- src/mcp_logseq/tools/blocks.py (not served here)
- src/mcp_logseq/tools/namespace.py (not served here)
- src/mcp_logseq/tools/pages.py (not served here)
- src/mcp_logseq/tools/search.py (not served here)
- src/mcp_logseq/transport/__init__.py (not served here)
- src/mcp_logseq/transport/auth.py (not served here)
- src/mcp_logseq/transport/http.py (not served here)
- src/mcp_logseq/vector/__init__.py (not served here)
- src/mcp_logseq/vector/chunker.py (not served here)
- src/mcp_logseq/vector/db.py (not served here)
- src/mcp_logseq/vector/embedder.py (not served here)
- src/mcp_logseq/vector/index.py (not served here)
- src/mcp_logseq/vector/state.py (not served here)
- src/mcp_logseq/vector/sync.py (not served here)
- src/mcp_logseq/vector/types.py (not served here)
- tests/conftest.py (not served here)
- tests/integration/test_http_serving.py (not served here)
- tests/integration/test_mcp_protocol.py (not served here)
- tests/integration/test_mcp_server.py (not served here)
- tests/integration/vector/__init__.py (not served here)
- tests/unit/test_access.py (not served here)
- tests/unit/test_access_policy_coverage.py (not served here)
- tests/unit/test_block_id_preservation.py (not served here)
- tests/unit/test_cli.py (not served here)
- tests/unit/test_db_properties.py (not served here)
- tests/unit/test_exclude_tags.py (not served here)
- tests/unit/test_http_transport.py (not served here)
- tests/unit/test_logging.py (not served here)
- tests/unit/test_logseq_api.py (not served here)
- tests/unit/test_namespace_access.py (not served here)
- tests/unit/test_parser.py (not served here)
- tests/unit/test_property_persistence.py (not served here)
- tests/unit/test_server_info.py (not served here)
- tests/unit/test_settings.py (not served here)
- tests/unit/test_tool_handlers.py (not served here)
- tests/unit/test_write_namespaces.py (not served here)
- tests/unit/vector/__init__.py (not served here)
- tests/unit/vector/test_asyncio_regression.py (not served here)
- tests/unit/vector/test_chunker.py (not served here)
- tests/unit/vector/test_config.py (not served here)
- tests/unit/vector/test_embedder.py (not served here)
- tests/unit/vector/test_index.py (not served here)
- tests/unit/vector/test_logseq_sync.py (not served here)
- tests/unit/vector/test_state.py (not served here)
- tests/unit/vector/test_sync.py (not served here)
- uv.lock (not served here)
Advantages
- Enables direct interaction with Logseq data, eliminating the need for manual file exports or context switching. evidence: README.md
- Provides granular privacy and access control through tag-based exclusions and namespace allow-lists. evidence: README.md
- Supports semantic vector search, allowing for discovery of notes by meaning. evidence: README.md
Limitations
- Requires the Logseq HTTP API server to be manually started and configured within the Logseq application. evidence: README.md
- Vector search features require additional setup and local embedding resources. evidence: README.md
Security
Risk level: No risk found
This brain runs
MCP servers (2)
README.md(mcp-logseq):uv run --with mcp-logseq mcp-logseqREADME.md(mcp-logseq):/Users/username/.local/bin/uv run --with mcp-logseq mcp-logseq
Attribution and licence
- First committed by
ergut
- Declared authors
- Salih Ergüt (declared in pyproject.toml)
- Publisher
- Salih Ergut (Community)
- Source
- ergut/mcp-logseq · commit 0769877
- Licence
- MIT License (files served here)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Contributors
- ergut, RobertoGongora, arndjan, ericfitz, lfnovo
AutoGineer is not affiliated with or endorsed by ergut.
Install from source
75 of its files are not served here, so there is no ZIP. ergut/mcp-logseq at 0769877