Sutra
Code-aware retrieval for your repositories. Sutra parses a Git repo into a
structured graph of symbols + relationships + embeddings, then serves it over
an MCP server that an AI agent (Claude Code, Claude Desktop, Cursor, …)
queries as a RAG over your codebase — "which function handles auth?", "who
calls upload_voice_note?", "show me the Meeting model".
The defining principle is pure code-based analysis with zero LLM enrichment in indexing: the graph + embeddings are rich enough that a downstream agent understands the repo without anything being pre-summarized.
Contents
- Mental model: two sides
- Prerequisites
- Install
- Configuration
- Quick start (the 3 surfaces)
- Connecting an agent
- The MCP tools
- Key concepts
- What Sutra does and does not do
- Project layout
- Testing
- Troubleshooting
- Roadmap
Mental model: two sides
Sutra is two programs that meet through files on disk, not one app. The shape is a bowtie: many sources fan in through the indexer to one central artifacts directory (the knot), which fans out to every consumer agent. That directory is the entire contract between the two sides.
flowchart LR
src1["Local repo path"]:::in
src2["Public git URL"]:::in
src1 --> IDX
src2 --> IDX
subgraph IDX["Indexer side — writes (sutra index / web frontend :8000)"]
direction TB
parse["tree-sitter parse<br/>symbols · relationships · monikers"]
resolve["resolve CALLS<br/>heuristic → optional LSP (pyright)"]
embed["embed symbols<br/>openai · local · compatible endpoint"]
parse --> resolve --> embed
end
embed --> KNOT
KNOT["📦 $SUTRA_ARTIFACTS_DIR<br/>one bundle per repo:<br/>graph.json · embeddings.npy<br/>embeddings_index.json · .ready"]:::knot
KNOT --> MCP
subgraph OUT["Consumer side — the product"]
direction TB
MCP["MCP server :8765 (sutra serve)<br/>loads every repo in-memory · no DB<br/>hot-reloads the instant .ready changes"]:::out
MCP --> a1["Claude Code"]:::leaf
MCP --> a2["Claude Desktop"]:::leaf
MCP --> a3["Cursor / any MCP client"]:::leaf
end
classDef in fill:#e8f0fe,stroke:#4285f4,color:#0b1324;
classDef out fill:#e6f4ea,stroke:#34a853,color:#0b1324;
classDef knot fill:#fef7e0,stroke:#f9ab00,color:#0b1324,font-weight:bold;
classDef leaf fill:#f1f3f4,stroke:#9aa0a6,color:#0b1324;
Remote teammates connect their MCP clients over HTTP + bearer token to
:8765; browsers hit the indexing UI at:8000.
- Indexer (
pipelines.full_index, wrapped by the web frontend): clones a repo, parses it, resolves calls, embeds, and writes a per-repo artifact bundle to$SUTRA_ARTIFACTS_DIR/<owner__repo>/. - Consumer (
sutra serve, a.k.a.python -m sutra.mcp): loads that directory entirely into memory and serves it. No database at query time —pip install+ a folder of artifacts is the whole deployment. It hot-reloads a repo the moment its.readysentinel changes, so re-indexing is picked up live.
The two share one local directory, $SUTRA_ARTIFACTS_DIR (default
~/.sutra/artifacts). That directory is the entire contract between them.
Prerequisites
sutra init(see Install) detects and provisions all of these for you — this list is what it configures.
- Python 3.11 (3.11.14 is the tested version) and a virtualenv.
- Node.js + npm — only to build the web frontend.
- pyright — required for LSP-grade call resolution, which the frontend uses
by default (
pip install pyright). The frontend refuses to start without it. - An embedder — one of:
- OpenAI (default config): set
OPENAI_API_KEY. Network required. - local (sentence-transformers, offline): install the ML extras below.
- fixture (deterministic fake vectors): no key, used for tests/demos.
- OpenAI (default config): set
- PostgreSQL is NOT required. The MVP runs JSON-only; Postgres only returns if/when incremental indexing is added (see Roadmap).
Install
Sutra is a pip-installable package with a sutra console command. Create a
Python 3.11 venv, install it, then run the guided setup wizard:
git clone <your sutra remote> && cd sutra
python3.11 -m venv .venv && source .venv/bin/activate
pip install -e . # editable install from a clone (use `pip install .` for a plain install)
sutra init # guided setup wizard — configures everything below
sutra init is interactive and idempotent (re-run it any time; it offers your
current values as defaults). Each step is skippable, shows the exact command
before running anything, and writes config only at the end. It guides you
through:
- Embedder choice — local sentence-transformers (
all-MiniLM-L6-v2, free / offline), OpenAI (text-embedding-3-small, needsOPENAI_API_KEY), or any OpenAI-compatible endpoint (Ollama, LM Studio, vLLM, Together, Azure, …) via abase_url. For local it does the correct CPU-only torch two-step install so pip doesn't pull the ~5GB CUDA build. - Artifacts directory — where indexed repos land (
SUTRA_ARTIFACTS_DIR, default~/.sutra/artifacts). - Postgres (optional) — only enables incremental re-indexing bookkeeping; Sutra runs fully JSON-only without it.
- Resolver / pyright — installs
pyrightfor LSP-grade call resolution (the frontend/UI default). - MCP registration (optional) — registers the server with Claude Code, or prints a JSON snippet for other MCP clients.
Then re-validate your environment any time with:
sutra doctor # non-interactive ✓/✗ checks + fix hints
Build the web frontend (only if you'll use the UI):
make ui-install # cd frontend/web && npm install
make ui-build # cd frontend/web && npm run build
Advanced / still-supported: manual install without the wizard
The pre-wizard flow keeps working — install dependencies and hand-edit
config/sutra.yaml yourself:
pip install -r requirements.txt
# Required for --resolver lsp (the frontend default):
pip install pyright
# OPTIONAL — only for the local embedder or the cross-encoder reranker.
# Install CPU-only torch FIRST or pip pulls the ~5GB CUDA build:
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install -r requirements-ml.txt
Configuration
config/sutra.yaml — chooses the embedder:
embedder:
provider: openai # openai | local | fixture
model: text-embedding-3-small
dimensions: 1536
batch_size: 100
api_key_env: OPENAI_API_KEY
# local-only:
# model: all-MiniLM-L6-v2
# dimensions: 384
Environment variables
| Variable | Used by | Meaning |
|---|---|---|
SUTRA_ARTIFACTS_DIR |
frontend, MCP server | Where per-repo artifacts live (default ~/.sutra/artifacts). Both sides must point at the same dir. |
OPENAI_API_KEY |
indexer (and MCP server, if artifacts were embedded with OpenAI) | Required when provider: openai. |
SUTRA_MCP_TOKEN |
MCP server | Bearer token required on every HTTP request (unset = no auth). |
The embedding model is recorded in each artifact. The MCP server rebuilds the same model at query time from that metadata — so an OpenAI-embedded repo needs
OPENAI_API_KEYon the query side too; alocal-embedded repo needs the ML extras; afixturerepo needs nothing.
Quick start (the 3 surfaces)
Once sutra init has configured your environment, these are the everyday
commands:
sutra index <path-or-url> # index a repo (local path or a git URL)
sutra serve # run the MCP server (the product)
sutra ui # launch the web frontend on :8000
sutra doctor # re-validate the environment (✓/✗ + fix hints)
Each wraps an existing entrypoint (sutra index → pipelines.full_index,
sutra serve → python -m sutra.mcp, sutra ui → uvicorn on
frontend.api.main:app). The three surfaces below show each in full, with the
underlying python -m … invocation documented as the still-supported advanced
path.
1. Web frontend (easiest)
A single-port local app: FastAPI API + a job queue + live SSE logs, with the React UI served as static files.
source .venv/bin/activate
export SUTRA_ARTIFACTS_DIR=~/.sutra/artifacts # where indexed repos land
export OPENAI_API_KEY=sk-... # if config uses openai
sutra ui # serves on :8000
# open http://127.0.0.1:8000
Advanced / still-supported:
make ui-run(oruvicorn frontend.api.main:app --host 127.0.0.1 --port 8000) does the same thing.
In the UI: paste a public Git URL, choose "Replace existing index", click
Start Indexing, and watch the logs stream. When it finishes you'll see
symbol/file counts, the embedding model, token usage and estimated cost, and
download links for the raw artifacts. The indexed repo is now live in any MCP
server pointed at the same $SUTRA_ARTIFACTS_DIR.
What the frontend does under the hood, per job: git clone → run
pipelines.full_index --replace --resolver lsp writing to
$SUTRA_ARTIFACTS_DIR/<owner__repo>/ → delete the clone (structure-only). It
runs JSON-only (no Postgres) and one job at a time.
Private repos (username + PAT) are not yet supported in the UI — public URLs only for now. See Roadmap.
2. CLI indexer
The same indexing the frontend wraps, run directly. The simplest form takes a local path or a git URL:
source .venv/bin/activate
sutra index /path/to/your-repo # a repo already on disk
sutra index https://github.com/org/your-repo # or clone + index a URL
Advanced / still-supported: the underlying python -m pipelines.full_index
sutra index wraps pipelines.full_index. To drive it directly with full
control over resolver, output dir, and re-index mode:
source .venv/bin/activate
python -m pipelines.full_index \
--root /path/to/your-repo \
--repo-url https://github.com/org/your-repo \
--output-dir "$SUTRA_ARTIFACTS_DIR/org__your-repo" \
--config config/sutra.yaml \
--resolver lsp \
--replace
| Flag | Meaning |
|---|---|
--root |
Local path to the repo to index (read-only; not cloned). |
--repo-url |
Canonical remote URL — its owner/repo becomes the repo's identity. |
--output-dir |
Where to write the artifact bundle. Use $SUTRA_ARTIFACTS_DIR/<owner__repo> so the MCP server finds it. |
--config |
Path to sutra.yaml (default config/sutra.yaml). |
--resolver |
lsp (pyright type inference, best, Python) → heuristic (default; local/import/unique rules, all langs) → none. |
--replace |
Re-index: overwrite this repo's artifact in place (the normal mode). |
--pg-url |
Optional Postgres URL for incremental bookkeeping; omit for JSON-only (the supported MVP path). |
Output: graph.json + embeddings.npy + embeddings_index.json, committed
atomically with a .ready sentinel written last.
3. MCP server (the product)
Point it at the artifacts directory and it serves every repo inside. With the
package installed, sutra serve runs it from anywhere — it wraps
python -m sutra.mcp and takes the same flags.
Two things that trip people up — read before you run it:
- OpenAI-embedded artifacts need
OPENAI_API_KEYat query time too. The server re-embeds your query with the same model the repo was indexed with. Without the key that repo is skipped (you'll seeskipping <repo>: … set OPENAI_API_KEY, thenNo loadable artifacts). Export the key, or re-index that repo withprovider: local/fixtureinconfig/sutra.yamlfor key-free querying.- For another machine to connect you need BOTH
--host 0.0.0.0andSUTRA_MCP_TOKEN. The default--hostis127.0.0.1(this machine only). On a0.0.0.0bind the bearer token is the only thing guarding your code — never expose0.0.0.0without a token.
source .venv/bin/activate
export SUTRA_ARTIFACTS_DIR=~/.sutra/artifacts
export OPENAI_API_KEY=sk-... # if any artifact is OpenAI-embedded
# Local stdio — for an agent on THIS machine:
sutra serve --artifacts-dir "$SUTRA_ARTIFACTS_DIR"
# Shared team server over HTTP (for other machines) — token REQUIRED:
export SUTRA_MCP_TOKEN=$(openssl rand -hex 32); echo "$SUTRA_MCP_TOKEN"
sutra serve --artifacts-dir "$SUTRA_ARTIFACTS_DIR" --http --host 0.0.0.0 --port 8765
# endpoint: http://<your-LAN-IP>:8765/mcp (find your IP with: hostname -I)
Advanced / still-supported:
python -m sutra.mcp …(same flags) works too. When invoking it directly rather than via thesutracommand, run it from the repo root with the repo's.venvactive (or setPYTHONPATH=/path/to/sutra) sosutra/mcpare importable —ModuleNotFoundError: No module named 'sutra'/'mcp'means you got that wrong.
| Flag / env | Meaning |
|---|---|
--artifacts-dir / SUTRA_ARTIFACTS_DIR |
Root holding one artifact subdir per repo. |
--http --host --port |
Streamable-HTTP transport instead of stdio (default port 8765). |
SUTRA_MCP_TOKEN |
Bearer token required on every HTTP request (unset = no auth). |
--no-watch |
Disable .ready hot-reload. |
--audit-db |
SQLite audit log path (default ~/.sutra/mcp_audit.db); every tool call is recorded. |
At boot the server validates every artifact (schema version, torn-artifact cross-checks, embedding-model identity) and skips bad ones individually — one broken repo never takes the server down.
Smoke-test it without wiring an agent — spawns the real server over stdio and walks every tool:
python scripts/verify_mcp.py --artifacts-dir "$SUTRA_ARTIFACTS_DIR" \
--query "which function creates a user" --repo org/your-repo
Connecting an agent
Claude Code — same machine (stdio)
sutra init offers to register the server for you (wizard step 6). To do it by
hand, point Claude at the absolute sutra console script in your venv and an
absolute artifacts path (~ is not expanded when the command is exec'd):
claude mcp add sutra -s user \
-e OPENAI_API_KEY=sk-... # omit for local/fixture artifacts \
-- /path/to/sutra/.venv/bin/sutra serve \
--artifacts-dir /home/you/.sutra/artifacts
-s userregisters it for every project (default scope is per-directorylocal).- Already added a broken one?
claude mcp remove sutrafirst (from the dir you added it in). /mcpfailing with-32000means the spawned server died — see Troubleshooting.
Advanced / still-supported: registering the raw python -m sutra.mcp
A bare claude mcp add sutra -- python -m sutra.mcp … will fail — Claude
spawns the server from its working directory (not the repo) with whatever
python is on PATH, so it can't import sutra/mcp. If you skip the console
script, pin the absolute venv python and pass the repo on PYTHONPATH:
claude mcp add sutra -s user \
-e PYTHONPATH=/path/to/sutra \
-e OPENAI_API_KEY=sk-... # omit for local/fixture artifacts \
-- /path/to/sutra/.venv/bin/python -m sutra.mcp \
--artifacts-dir /home/you/.sutra/artifacts
Claude Code — another machine on your LAN (HTTP, recommended for sharing)
Start the HTTP server on the host (see §3) with
--host 0.0.0.0 and a SUTRA_MCP_TOKEN, then on the other machine
register the host's LAN IP (run hostname -I on the host) with the same
token:
# on the CLIENT machine:
claude mcp add --transport http sutra -s user http://<HOST-LAN-IP>:8765/mcp \
--header "Authorization: Bearer <the SUTRA_MCP_TOKEN printed by the host>"
HTTP avoids every stdio pitfall (cwd, interpreter, env) — the server runs in a
shell you control; clients just hit a URL. For the client to reach it: the host
must bind 0.0.0.0, the host firewall must allow the port
(sudo ufw allow 8765/tcp), and the Wi-Fi must not isolate clients (common on
guest/corporate networks — home Wi-Fi is usually fine).
Claude Desktop / Cursor (claude_desktop_config.json / .cursor/mcp.json)
Same rule as stdio above — use the absolute sutra console script in your
venv and absolute paths:
{
"mcpServers": {
"sutra": {
"command": "/abs/path/sutra/.venv/bin/sutra",
"args": ["serve", "--artifacts-dir", "/home/you/.sutra/artifacts"],
"env": {
"OPENAI_API_KEY": "sk-..."
}
}
}
}
Advanced / still-supported: the raw form is
"command": "/abs/path/sutra/.venv/bin/python","args": ["-m", "sutra.mcp", "--artifacts-dir", "…"]with"PYTHONPATH": "/abs/path/sutra"added toenv.
The MCP tools
| Tool | Arguments | Returns |
|---|---|---|
sutra_list_repos |
— | indexed repos + symbol counts + commit SHAs + embedding model |
sutra_search |
query, repo?, top_k=10, rerank=False, include_provenance=False |
ranked symbols with file/line, signature, one-line docstring summary (full docstring via sutra_get_symbol; per-channel provenance when include_provenance=True) |
sutra_get_symbol |
moniker |
full metadata for one symbol + its callers/callees |
sutra_get_callers |
moniker |
symbols with a resolved CALLS edge into it |
sutra_get_callees |
moniker |
symbols it calls |
sutra_expand_neighbors |
moniker, depth=1, kinds? |
BFS over the relationship graph (calls/extends/implements/references/contains/imports/returns_type/parameter_type) |
Agent workflow: sutra_search to find an entry point → sutra_get_symbol
/ sutra_get_callers / sutra_expand_neighbors to walk the call/type graph
outward. Pass repo="owner/repo" to scope to one repo, or omit it to search
across all indexed repos.
When to reach for Sutra — recommended agent guidance. Sutra does two things
a per-repo file search cannot: one call that searches every indexed repo, and a
resolved call/type graph. Drop this into your agent's CLAUDE.md / system
prompt (adjust the repo list):
You have a Sutra MCP server indexing our repositories. Reach for it — over a plain file search — when:
- The question spans multiple repos ("where is this implemented anywhere across our services", "which service defines the payments client") — call
sutra_searchwith norepoto search every indexed repo in one call; a local grep only sees the repo you are in.- You need the call graph — use
sutra_get_callers/sutra_get_callees/sutra_expand_neighborsto get callers, callees, or a call chain as resolved edges in one call, instead of repeated grep-and-read. The graph holds only resolved edges, so treat it as a lower bound, not a complete impact set.
sutra_searchalso locates code by concept — ranked symbols with exact file:line, useful when you can't guess the keyword. On a single repo it and a plain grep are comparable today; use whichever is faster.
Each sutra_search is itself a butterfly: the query fans out across three
independent retrieval channels, then fans back in through Reciprocal Rank Fusion
into one ranked list — all in memory:
flowchart LR
Q["Natural-language query"]:::q
Q --> V["Vector channel<br/>embedding similarity"]:::ch
Q --> B["BM25 channel<br/>lexical (also reaches<br/>non-embedded modules)"]:::ch
Q --> M["Moniker channel<br/>exact identifier match"]:::ch
V --> F["Reciprocal Rank Fusion<br/>+ kind filter"]:::knot
B --> F
M --> F
F --> RR{"rerank?"}
RR -->|"no (default)"| OUT["Ranked symbols<br/>file · line · signature · docstring"]:::out
RR -->|"yes"| CE["cross-encoder rerank<br/>bge-reranker-v2-m3"]:::ch
CE --> OUT
classDef q fill:#e8f0fe,stroke:#4285f4,color:#0b1324,font-weight:bold;
classDef ch fill:#f1f3f4,stroke:#9aa0a6,color:#0b1324;
classDef knot fill:#fef7e0,stroke:#f9ab00,color:#0b1324,font-weight:bold;
classDef out fill:#e6f4ea,stroke:#34a853,color:#0b1324;
rerank=True adds a cross-encoder pass (BAAI/bge-reranker-v2-m3) — ~60s+
per query on CPU; leave it off unless you're on GPU.
See MCP_USAGE.md for the full tool reference and hot-reload/sync details.
Key concepts
- Moniker (symbol identity) — every symbol gets a stable SCIP-style id:
sutra <language> <owner/repo> <file_path> <descriptor>. Theowner/repois baked in, so the same function name in two different repos never collides. - Repo identity — derived once, canonically, from the URL:
https://github.com/Acme/Widget→acme/widget(lowercased, host-stripped). The artifact folder is the filesystem-safe slugacme__widget. Two repos namedwidgetfrom different owners coexist cleanly. - Artifact bundle — per repo:
graph.json(symbols, relationships, files, metadata),embeddings.npy(one row per embeddable symbol), andembeddings_index.json(row ↔ moniker). A.readysentinel is written last and is the commit point the MCP watcher fires on. - Resolvers — turn unresolved CALLS into real edges.
heuristic(local/import/unique rules, all languages, no types) → optionally chained withlsp(pyright type inference for Python, resolves what the heuristic can't). LSP runs at index time, against the clone, before it's deleted. - Retrieval channels —
sutra_searchfuses three: vector (embedding similarity), BM25 (lexical, also reaches modules that aren't embedded), and moniker (exact identifier match), combined with Reciprocal Rank Fusion. Everything is in-memory. - Languages — Python, TypeScript, Go (tree-sitter).
What Sutra does and does not do
Does
- Index Python / TypeScript / Go repos into a queryable symbol + call graph.
- Resolve intra-repo calls (heuristic ~92% on real repos; LSP pushes Python toward ~99%).
- Serve many repos from one in-memory MCP server; trace call chains within a
repo via
get_callers/get_callees/expand_neighbors.
Does not (by design / current scope)
- No cross-repo or cross-service call resolution. Microservices talk over HTTP/RPC, not source-level function calls, so there are no AST edges to resolve between them. "Token flow across the whole app" stops at repo boundaries — the agent bridges services by searching, not by graph edges.
- No dataflow / taint analysis. "How does the token flow" is approximated by walking the call graph + reading signatures/docstrings, not by tracking a variable through parameters.
- Structure-only at query time. Clones are deleted after indexing; the agent gets symbols, signatures, docstrings, and call edges — not raw source bytes. (It can open files itself if it has the repo checked out.)
- JSON-only MVP — no Postgres, no incremental indexing yet; re-index a repo to refresh it.
Project layout
sutra/
├── core/
│ ├── extractor/ tree-sitter parsing → symbols/relationships; monikers
│ │ └── adapters/ python.py · typescript.py · go.py
│ ├── resolver/ CALLS resolution: heuristic.py, lsp_resolver.py (pyright)
│ ├── embedder/ openai · local (sentence-transformers) · fixture + factory
│ ├── retrieval/ channels (vector/bm25/moniker), fusion, reranker, pipeline
│ ├── graph/ SQL writer/reader (indexer-side), rustworkx traversal (query-side)
│ ├── artifact/ AtomicArtifactWriter (.ready), loader, ArtifactSink
│ ├── output/ json_graph_exporter.py (the bundle serializer)
│ ├── vector_store/ in-memory vector index
│ └── indexer.py orchestrates a full index → publishes the artifact
├── mcp/ server.py (6 tools), registry, watcher, audit, __main__.py
pipelines/
├── full_index.py CLI entry point for indexing
└── incremental_update.py (deferred path; needs Postgres)
frontend/
├── api/ FastAPI: job queue, SSE logs, SQLite job db (main.py, jobs.py)
└── web/ React + Vite UI
config/sutra.yaml embedder configuration
scripts/verify_mcp.py spawn the real MCP server over stdio and exercise every tool
docs/superpowers/ design specs & implementation plans
tests/ pytest suite (real instances, no mocks); fixtures/
Further reading: DESIGN.md (architecture & data model — note it predates
the JSON-only/owner-identity changes in places), MCP_USAGE.md (MCP
deployment & tools), ENV.md (environment specifics).
Testing
Real instances, real artifacts, real subprocesses — no mocks.
source .venv/bin/activate
python -m pytest -q -k "not pgvector and not sql" # the JSON-only suite (~700 tests)
The pgvector/sql tests need a live Postgres and are outside the JSON-only
MVP. Adapters, indexer, exporter, resolvers, retrieval, and the MCP
loader/server/watcher all have dedicated tests; tests/fixtures/ holds a small
checked-in Python repo used for hermetic end-to-end runs.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
| Frontend won't start: "pyright-langserver not found" | pip install pyright — LSP is the frontend's default resolver. |
| Frontend won't start: "OPENAI_API_KEY is required" | Config uses provider: openai. Set the key, or switch to local/fixture in config/sutra.yaml. |
MCP server: ModuleNotFoundError: No module named 'sutra' (or 'mcp') |
Wrong cwd or interpreter. Run from the repo root with its .venv active, or use the absolute …/sutra/.venv/bin/python and set PYTHONPATH=/path/to/sutra. |
MCP server prints skipping <repo>: … set OPENAI_API_KEY then exits No loadable artifacts |
The repo is present but skipped, not missing — it was OpenAI-embedded, so the server needs OPENAI_API_KEY to embed queries with the same model. Export the key used to index it, or re-index with a local/fixture embedder. |
MCP server: No loadable artifacts and the dir is empty/wrong |
--artifacts-dir must hold subdirectories, one per repo, each with graph.json + embeddings.npy + embeddings_index.json. Index something first. |
Agent: Failed to reconnect: -32000 |
The stdio server died on launch. Reproduce the exact spawn from a neutral dir; usual causes: wrong cwd/venv (→ absolute python + PYTHONPATH), missing OPENAI_API_KEY, or a literal ~ in --artifacts-dir (use an absolute path). |
| Remote client: connection refused / hangs | Server bound to 127.0.0.1. Restart with --host 0.0.0.0. Then verify the IP (hostname -I), host firewall (sudo ufw allow 8765/tcp), and Wi-Fi client isolation. |
Remote client: 421 Misdirected Request / "Invalid Host header" |
Old build — update to a version where the HTTP team server relaxes the SDK's localhost-only Host allowlist (the bearer token is the auth boundary). |
Remote client: 401 unauthorized |
Missing/wrong Authorization: Bearer <token> — it must equal the server's SUTRA_MCP_TOKEN. |
| MCP server: "Embedding model mismatch" | The artifact was embedded with a model the query side can't build. For OpenAI artifacts set OPENAI_API_KEY; for local artifacts install the ML extras. |
| "Torn artifact: …" | A half-written/half-copied bundle. Re-index; when syncing remotely, copy data files first and the .ready sentinel last. |
| First query is slow | sentence-transformers / reranker models load lazily on first use, then cache. |
| Indexed repo not showing up in the agent | Frontend and MCP server must share the same $SUTRA_ARTIFACTS_DIR, and the server needs .ready (written automatically by indexing). |
Roadmap
- Private-repo support in the frontend — public/private toggle, username + PAT (held in memory only, never logged or persisted, scrubbed from the log stream).
- Incremental indexing — re-index only changed files via
git diff(re-introduces Postgres for bookkeeping). - Cross-service awareness (later) — HTTP route ↔ client-call matching so an agent can follow flows across microservices, which call resolution can't.
Release files for sutra-engine 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| sutra_engine-0.1.0.tar.gz | 271.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| sutra_engine-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 465.5 kB
Release files / sutra_engine-0.1.0.tar.gz
| Download URL | sutra_engine-0.1.0.tar.gz |
|---|---|
| Size | 271.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6e1e3f9852c6e6e2a76f5259dde032c1dfa12ca7eb72d024061c7aaf63b45fc4
|
|
BLAKE2b-256 checksum How to use checksums |
738e386e3c38273ee7844027eff8e8a0a86f1609dc2f527d430a4157f0a011c2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / sutra_engine-0.1.0-py3-none-any.whl
| Download URL | sutra_engine-0.1.0-py3-none-any.whl |
|---|---|
| Size | 194.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
644fc9d4bbcb1405b7d49bc34237725585bc2bdbac299a19bc0c7a9361099504
|
|
BLAKE2b-256 checksum How to use checksums |
1c095cd3d48f894406ea6303655c15ea28de685bee024b836a39940452fc419a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|