使用说明
Sextant
Sextant is an MCP server that provides hybrid semantic and keyword search over a local folder of markdown files. It indexes your docs, chunks them by heading, embeds them through a local Ollama model, and exposes search and retrieval tools over the Model Context Protocol (MCP).
Claude Code (or any MCP client) can then search your documentation using natural language queries, exact keyword lookups, or a combination of both.
How it works
- Sextant scans a folder of markdown files and splits them into chunks at each heading boundary.
- Each chunk is embedded locally using Ollama (nomic-embed-text).
- Chunks and their embeddings are stored in Orama, which handles full-text, vector, and hybrid search in a single library.
- File metadata is tracked in SQLite (via bun:sqlite) so unchanged files are skipped on restart.
- Each search request checks for stale files and triggers a background reindex if needed.
- The MCP server exposes five tools over stdio:
search_docs,list_docs,get_doc,reindex_docs, andsextant_status.
The entire stack runs locally with no external services. There are no native modules; everything is pure JavaScript/TypeScript.
Shared daemon
The process an MCP client spawns is a thin stdio shim, not the full server. The shim attaches to a shared per-project daemon (starting one automatically if none is running) and proxies requests to it over localhost HTTP. This means any number of concurrent sessions on the same project share a single in-memory index instead of each holding their own copy.
Lifecycle is automatic in both directions: the first session starts the daemon, and shortly after the last session ends the daemon flushes its index to disk and exits. An idle timeout also stops the daemon after a period with no requests; it restarts transparently on the next search. The daemon binds to 127.0.0.1 only, rejects requests from browsers, and requires a per-run token that shims read from DATA_PATH/daemon.lock. Its log is written to DATA_PATH/daemon.log.
Two escape hatches exist: sextant serve runs the daemon in the foreground explicitly, and sextant standalone runs the old single-process stdio server with no daemon involved.
Index freshness
Sextant keeps its index up to date automatically:
- On startup, Sextant compares every file's modification time against what was previously indexed. New and changed files are re-indexed; deleted files are removed from the index. This covers cases where docs were updated while the server was not running (for example, after a
git pull). - On each search, a freshness check detects new, modified, or deleted files and triggers a background reindex without blocking the query. If files have changed, the response includes a note and results update on the next search.
- If another Sextant process has persisted a newer index to disk, it is picked up automatically before searching.
Prerequisites
Bun
Sextant runs on Bun, which is used as the runtime, package manager, and bundler.
Windows (PowerShell):
powershell -c "irm bun.sh/install.ps1 | iex"
macOS / Linux:
curl -fsSL https://bun.sh/install | bash
Verify the installation with bun --version.
Ollama
Ollama must be installed and running locally. Pull the embedding model before first use:
ollama pull nomic-embed-text
Ollama runs on http://localhost:11434 by default. If Ollama is not running, keyword search will still work, but semantic and hybrid search will be unavailable.
Usage with Claude Code
Add the following to your Claude Code MCP configuration (.claude/mcp.json in your project):
{
"mcpServers": {
"sextant": {
"type": "stdio",
"command": "bunx",
"args": ["@tideshift/sextant"],
"env": {
"DOCS_PATH": "/absolute/path/to/your/docs"
}
}
}
}
Set DOCS_PATH to the absolute path of the markdown folder you want to index.
Once configured, Claude Code will have access to the following tools:
- search_docs - Search documentation using hybrid semantic + keyword search. Supports three modes:
hybrid(default, combines both),semantic(vector similarity only), andkeyword(exact text matching only). Accepts an optional category filter. - list_docs - List all indexed documents with their categories, titles, and chunk counts.
- get_doc - Retrieve the full content of a specific document by file path.
- reindex_docs - Force a full re-index of all documents.
- sextant_status - Check server health, indexing progress, Ollama connectivity, and index statistics.
Configuration
All settings can be configured through environment variables or a .env file:
| Variable | Default | Description |
|---|---|---|
DOCS_PATH |
./docs |
Path to the markdown folder to index |
IGNORE_GLOBS |
**/node_modules/** |
Comma-separated glob patterns (relative to DOCS_PATH, posix separators) to skip. Empty value indexes everything |
OLLAMA_URL |
http://localhost:11434 |
Ollama API endpoint |
EMBEDDING_MODEL |
nomic-embed-text |
Ollama embedding model name |
EMBEDDING_DIMS |
768 |
Embedding vector dimensions (must match model) |
DATA_PATH |
.sextant |
Where to store the index and metadata |
MAX_CHUNK_TOKENS |
512 |
Maximum chunk size (estimated as chars / 4) |
DEFAULT_TOP_K |
10 |
Default number of search results |
HYBRID_WEIGHT_TEXT |
0.5 |
Weight for keyword matching in hybrid mode |
HYBRID_WEIGHT_VECTOR |
0.5 |
Weight for semantic matching in hybrid mode |
SEXTANT_PORT |
0 |
Daemon port (0 = OS-assigned; recorded in DATA_PATH/daemon.lock) |
SEXTANT_GRACE_MS |
60000 |
How long the daemon waits after the last client disconnects before exiting |
SEXTANT_IDLE_TIMEOUT_MS |
600000 |
Daemon exits after this long with no requests (restarts on next use) |
SEXTANT_LOG_FILE |
DATA_PATH/daemon.log |
Daemon log file |
SEXTANT_SPAWN_TIMEOUT_MS |
30000 |
How long the shim waits for a spawned daemon to become healthy |
SEXTANT_FRESHNESS_TTL_MS |
5000 |
Minimum interval between per-search freshness scans |
SEXTANT_OLLAMA_HEALTH_TTL_MS |
5000 |
Cache duration for Ollama health checks |
Contributing
See docs/contributing.md for local development setup, building, and diagnostics.
Technical details
See docs/technical_details.md for architecture, project structure, chunking strategy, persistence model, index freshness logic, and edge cases.
License
Made with ❤️ in Vancouver, BC by Tideshift Labs, developed using Claude Code.