lexomni-mcp
v0.2.0
Published
MCP server for local knowledge management with MD and PDF indexing
Maintainers
Readme
Lexomni MCP
MCP (Model Context Protocol) server for local knowledge management with Markdown and PDF indexing using SQLite FTS5.
Author: PagansDev (Paulo Gabriel Neves Santos) | Repository: github.com/PagansDev/lexomni-mcp
English
Usage
Requires Node.js 20.16 or newer.
As a local MCP server
- Configure your MCP client (e.g.,
.mcp.jsonfor Claude Code,.cursor/mcp.jsonfor Cursor). Pin an exact version:
"lexomni": {
"command": "npx",
"args": ["-y", "[email protected]"],
"env": { "LEXOMNI_WORKSPACE": "_lexomni" }
}A relative LEXOMNI_WORKSPACE keeps a versioned config file portable across machines. Projects set up with @satlab/protocol get this entry from satlab-protocol init, and satlab-protocol update keeps it current.
Add your documents:
_lexomni/user/- User markdown (guidelines, architecture, etc.)_lexomni/agent/- Agent notes (written bylexomni_writeNote)_lexomni/books/- PDFs (books, documentation, etc.)
Ask the agent to run
lexomni_buildIndex. Searches only return what has been indexed.
How the workspace is resolved
LEXOMNI_WORKSPACE, when set. An absolute path is used as is; a relative one is resolved against the project root.- The project root is
CLAUDE_PROJECT_DIR(set by Claude Code), otherwise the first root reported by the MCP client, otherwise the current directory. - Without
LEXOMNI_WORKSPACE, the server looks for a_lexomnifolder from the project root upwards and stops at the repository root (the first folder containing.git). If none is found, the workspace is<project root>/_lexomni.
Reading never creates folders: user/, agent/, books/ and index/ are created only when lexomni_writeNote or lexomni_buildIndex writes. lexomni_listSources and lexomni_searchDocs always report the workspace they used and return a warning when it is empty, when the index does not exist, or when it is out of date.
Available Tools
Agent handles parameters on its own
lexomni_listSources
Lists all documents (MD and PDF) in the workspace.
Parameters: none
Example:
{
"workspace": "/path/to/project/_lexomni",
"count": 5,
"docs": [...]
}lexomni_buildIndex
Indexes documents into SQLite FTS5 for fast search. This is the only tool that indexes, and it is incremental: documents whose size and modification time did not change are skipped, and documents removed from the workspace are dropped from the index.
Parameters:
sources(optional): array of["user", "agent", "books"]. Limits what is indexed and what can be removed.force(optional): reindex everything, changed or not.
Example:
{ "ok": true, "docsIndexed": 1, "indexed": 1, "skipped": 11, "removed": 0 }lexomni_searchDocs
Keyword search across indexed documents. It never indexes: new or changed files appear only after the next lexomni_buildIndex, and the response carries a warning until then.
The query is literal text. Each word is matched as typed, so hyphens, quotes and colons are safe (third-party, CVE-2024-4367); FTS5 operators such as OR, NEAR or * are not interpreted.
Parameters:
query(required): string, min 2 characterssources(optional): filter by sourcelimit(optional): max results (1-50, default 10)
Example:
{
"query": "clean architecture",
"workspace": "/path/to/project/_lexomni",
"hits": [
{
"docId": "user:user/guidelines.md",
"chunkIndex": 0,
"snippet": "...about [clean] [architecture]...",
"source": "user",
"relPath": "user/guidelines.md"
}
]
}lexomni_readDoc
- docId (required)
- Type: string Purpose: unique identifier of the document in the index.
Constraint: at least 3 characters. Typical source: taken from a hit returned by lexomni_searchDocs.
- chunkIndex (optional) Type: integer Minimum: 0 Purpose: which chunk (piece) of the document to read. If omitted: usually defaults to the first chunk (0), depending on implementation.
- maxChars (optional) Type: integer Range: 200–20000 Purpose: maximum number of characters of text to return for that chunk, useful to limit response size.
lexomni_writeNote
- filename (required) Type: string Purpose: name of the markdown file to create or update in the agent’s notes area.
Constraint: at least 1 character.
- content (required) Type: string Purpose: markdown content to write into the file.
Constraint: at least 1 character.
- mode (optional) Type: string Allowed values: "overwrite" – replaces the existing file content entirely. "append" – appends content to the end of the existing file. Default: "overwrite" if not specified.
Security
- Path traversal blocked (no
../, absolute paths or null bytes in note names) - Write access limited to
_lexomni/agent/, checked against the real path on disk - Symbolic links are ignored when indexing and refused when writing notes, so a symlink inside the workspace cannot expose or overwrite files outside it
- PDFs are parsed only by
lexomni_buildIndex, each one in a separate, sandboxed Node process (read-only access to the package and that PDF, no writes, no child processes, 100 MB / 512 MB / 60 s limits), with pdf.js string evaluation disabled - Notes are limited to 1 MiB
- Runtime dependencies are bundled and releases are published from CI with provenance
See SECURITY.md for the supply chain policy, risky components and how to report a vulnerability.
Architecture
_lexomni/ # In user's project
user/ # Guidelines, architecture (read-only)
agent/ # Agent notes (writable)
books/ # PDFs (read-only)
index/ # SQLite FTS5 (generated)
lexomni.sqliteMultilingual Strategy
Lexomni does not translate text internally. To find docs in PT and EN for e.g. :
Agent expands queries before searching:
- "arquitetura em camadas" → also searches "layered architecture"
- "fila" → also searches "message queue", "job queue"
Living glossary at
_lexomni/agent/glossary.md:- Agent learns new terms via web search
- Improves search quality over time
Development
npm run build # Bundle into dist/ (index.js, pdf.worker.mjs, sql-wasm.wasm)
npm run dev # Watch mode
npm start # Run built server
npm test # Tests
npm run lint # Lint
npm run typecheck # TypecheckTo run a local build from a clone, point the MCP client to it:
"lexomni-local": {
"command": "node",
"args": ["/path/to/lexomni-mcp/dist/index.js"],
"env": { "LEXOMNI_WORKSPACE": "_lexomni" }
}