Skip to main content

context-server

context-server

CI PyPI

Semantic search over a folder of markdown, served as an MCP server for coding agents.

Index once into a SQLite DB (embeddings + BM25). Point Claude Code, Cursor, or any MCP client at serve, and the agent can search that corpus instead of guessing from memory.

One Rust binary. ONNX Runtime is linked in via ort / fastembed — no separate libonnxruntime to ship. SQLite is bundled.

Quick start

pip install context-server
# or: uvx context-server@latest …

context-server index --input ./docs --db context.db
context-server search --db context.db "how do we handle backports"
context-server serve --db context.db

Wheels: Linux x86_64/aarch64 (manylinux_2_39 / glibc 2.39+, e.g. Ubuntu 24.04+) and macOS Apple Silicon.

The first embedding run downloads BGE-small-en-v1.5 into $XDG_CACHE_HOME/context-server/fastembed/ (or ~/.cache/...; once, tens of MB). Override with FASTEMBED_CACHE_DIR or HF_HOME.

Optional: tell the agent when to use this corpus

context-server index --input ./docs --db context.db \
  --instructions-file ./mcp-instructions.txt
# or: --instructions 'Use semantic_search for questions about …'

That text is stored in the DB and exposed as MCP ServerInfo.instructions when you serve.

Claude Code

claude mcp add --transport stdio --scope user context-server \
  -- uvx --refresh context-server@latest \
  serve --db /absolute/path/to/context.db

--refresh + @latest rechecks PyPI on each start. If Claude rarely surfaces the tools, set "alwaysLoad": true on the server entry in your Claude MCP config.

Cursor

~/.cursor/mcp.json (or project .cursor/mcp.json):

{
  "mcpServers": {
    "context-server": {
      "command": "uvx",
      "args": [
        "--refresh",
        "context-server@latest",
        "serve",
        "--db",
        "/absolute/path/to/context.db"
      ]
    }
  }
}

Reload MCP after editing. Re-index when content changes, then restart the MCP session so serve reloads the DB.

What it indexes

Only .md / .markdown. Chunks on # / ## / ###, keeps the heading path on each chunk, and splits long sections with overlap.

Convert structured sources (YAML, etc.) to prose before indexing. Fenced YAML searches poorly; a short paragraph that keeps names, roles, and relationships together works much better.

Try the sample set:

cargo build --release
./target/release/context-server index --input examples/sample-docs --dry-run
./target/release/context-server index --input examples/sample-docs --db /tmp/sample.db
./target/release/context-server search --db /tmp/sample.db "password reset"

Search

Default mode is hybrid: dense cosine (BGE-small-en-v1.5) plus BM25, fused with reciprocal rank fusion. Dense catches paraphrase; BM25 catches exact tokens (usernames, acronyms, IDs).

context-server search --db context.db --mode hybrid "query"   # default
context-server search --db context.db --mode dense "query"
context-server search --db context.db --mode lexical "query"

# Scope to a subtree / heading / metadata tag
context-server search --db context.db --path-prefix teams/ "who owns storage"
context-server search --db context.db --heading Backport "z-stream"
context-server get --db context.db --path teams/storage.md --chunk 0

MCP tools

Tool Role
semantic_search Ranked passages + scores; optional path_prefix / heading / tag filters
list_documents Indexed chunks; optional path_prefix
answer_question Best matching passage(s) — retrieval only; same filters as search
get_document Full chunk by citation (source_path + chunk_index), or all chunks for a path

Search hits cite chunks as source_path#chunk_index. Call get_document to pull the full text for quoting.

Remote database (GCS)

serve and search accept a gs:// URI. The object is cached under $XDG_CACHE_HOME/context-server/dbs/ (or ~/.cache/...). index still writes a local path only.

context-server serve --db 'gs://my-bucket/latest/context.db'

# Project-qualified form also works (gs:// required; stripped for the Storage API)
context-server serve --db \
  'gs://projects/my-gcp-project/buckets/my-bucket/objects/latest/context.db'

Uses Application Default Credentials. If a sibling {object}.sha256 exists (sha256sum format), a matching local cache is reused; otherwise the DB is re-fetched and verified.

CLI

context-server index  --input <path> [--db FILE] [--dry-run] [--batch N]
                      [--full] [--update]
                      [--instructions TEXT | --instructions-file FILE]
context-server serve  --db <local path | gs://…>
context-server search --db <local path | gs://…> [--limit N] [--mode hybrid|dense|lexical]
                      [--path-prefix P] [--heading H] [--tag T] <query>
context-server get    --db <local path | gs://…> --path FILE [--chunk N]
context-server embed  <query>         # smoke-test query embedding (BGE instruction)

Build from source

cargo build --release
cargo test

Rust 1.75+, Linux x86_64 is the primary target. You need a C++ stdlib for the linker (libstdc++) and whatever OpenSSL/native-tls needs on your platform.

On Fedora/RHEL, if the linker wants -lstdc++ but only libstdc++.so.6 exists:

mkdir -p .linker && ln -sfn /usr/lib64/libstdc++.so.6 .linker/libstdc++.so
export RUSTFLAGS="-L native=$(pwd)/.linker"

Linux wheels (same image CI uses — Ubuntu 24.04 / glibc 2.39):

./scripts/build-wheel.sh
VERSION=2026.716.1 ./scripts/build-wheel.sh   # optional override

Releasing

CalVer YYYY.MMDD.N (e.g. 2026.716.1) so versions work for both Cargo and PyPI. Run the Release workflow on main (Actions UI or CLI); it picks the next version, builds wheels, publishes to PyPI, then creates the matching git tag and GitHub Release (with wheels attached).

gh workflow run release.yml --repo context-server/context-server

Design notes

Under the hood: fastembed BGE-small-en-v1.5 (384-d, L2-normalized; query instruction applied at search time), rusqlite with float32 blobs, rmcp over stdio. index is incremental by file: unchanged files (same post-chunk content hash) are skipped, so the embedding model is not loaded. Files missing from --input are removed. Pass --full to re-embed everything collected, or --update to upsert without deleting other paths. Re-run index after upgrading if MODEL_ID or the chunker version changed (that forces a full re-embed).

More detail and roadmap: PLAN.md.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

context_server-2026.820.1.tar.gz (275.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

context_server-2026.820.1-py3-none-manylinux_2_39_x86_64.whl (18.7 MB view details)

Uploaded Python 3manylinux: glibc 2.39+ x86-64

context_server-2026.820.1-py3-none-manylinux_2_39_aarch64.whl (18.8 MB view details)

Uploaded Python 3manylinux: glibc 2.39+ ARM64

context_server-2026.820.1-py3-none-macosx_11_0_arm64.whl (14.3 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file context_server-2026.820.1.tar.gz.

File metadata

  • Download URL: context_server-2026.820.1.tar.gz
  • Upload date:
  • Size: 275.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for context_server-2026.820.1.tar.gz
Algorithm Hash digest
SHA256 7d5c7ea046c3866a4169c7a7caa2d2d370cafadc7282f0b64e44df11c5165bb3
MD5 d33ee6ab3e265858535563ebb843a637
BLAKE2b-256 124026151138e42b71afde7c8841163f99f5581e643fc43e26b136aa33c9208a

See more details on using hashes here.

File details

Details for the file context_server-2026.820.1-py3-none-manylinux_2_39_x86_64.whl.

File metadata

  • Download URL: context_server-2026.820.1-py3-none-manylinux_2_39_x86_64.whl
  • Upload date:
  • Size: 18.7 MB
  • Tags: Python 3, manylinux: glibc 2.39+ x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for context_server-2026.820.1-py3-none-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 c9c192243065a6aa9f5d93220f55eb97aa44d7d192617f2f9c0415be0445d2ef
MD5 20b34b8f14ecd31c45e1a83370f42644
BLAKE2b-256 a61ed1e11256ad8e8c46b61ba4fc4fb29e06a80f8ba0806e00894d2c43dc6444

See more details on using hashes here.

File details

Details for the file context_server-2026.820.1-py3-none-manylinux_2_39_aarch64.whl.

File metadata

  • Download URL: context_server-2026.820.1-py3-none-manylinux_2_39_aarch64.whl
  • Upload date:
  • Size: 18.8 MB
  • Tags: Python 3, manylinux: glibc 2.39+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for context_server-2026.820.1-py3-none-manylinux_2_39_aarch64.whl
Algorithm Hash digest
SHA256 fe357c3ffb193b0810fe4d3277ba4fdba70f3f83fdb51c64e49ca125e7c229f8
MD5 fba2bd0e81fba87064e13e5d7b7035e4
BLAKE2b-256 1cb4e24caf7485b14827b75ae4a8750f83e058884fa0a7befd814c0e4fc9a0ae

See more details on using hashes here.

File details

Details for the file context_server-2026.820.1-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: context_server-2026.820.1-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 14.3 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for context_server-2026.820.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 d262fa4da466535c4d9a27e2377a45a2d793a18d5027b0ee63630bb29c96cc15
MD5 648040f1dd0bce2a95f53cee8fe937eb
BLAKE2b-256 ee0f4ccc208cce16a31134dc272949457cacfd6933dd471b7883f71cf573ef81

See more details on using hashes here.

Release history Release notifications | RSS feed

2026.823.1

4 files

2026.822.1

4 files

This release

2026.820.1 This release

4 files

2026.718.4

4 files

2026.718.3

4 files

2026.718.2

4 files

2026.718.1

4 files

2026.717.3

4 files

2026.717.2

4 files

2026.717.1

4 files

2026.716.3

4 files

2026.716.2

4 files

2026.716.1

4 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page