English · 한국어
Use with an agent¶
vecscope ships an MCP server with four read-only tools: audit_embeddings, sweep_index,
compare_embeddings and describe_findings. Register it with any MCP client:
pip install vecscope
claude mcp add vecscope -- vecscope-mcp --allow-dir /data/embeddings # Claude Code
claude mcp add vecscope -- uvx vecscope mcp --allow-dir /data/embeddings # or without installing
vecscope mcp and vecscope-mcp are the same server with the same options. It is listed in
the MCP Registry
as io.github.076923/vecscope.
{ "mcpServers": { "vecscope": { "command": "vecscope-mcp", "args": ["--allow-dir", "/data/embeddings"] } } }
The JSON form goes in .cursor/mcp.json for Cursor and in .mcp.json for a Claude Code
project. Codex reads TOML from ~/.codex/config.toml:
[mcp_servers.vecscope]
command = "vecscope-mcp"
args = ["--allow-dir", "/data/embeddings"]
VS Code reads .vscode/mcp.json in the workspace, under servers instead of mcpServers.
Use the full path of vecscope-mcp (where vecscope-mcp on Windows, which vecscope-mcp
elsewhere), since VS Code may not see the PATH of your shell:
{
"servers": {
"vecscope": {
"type": "stdio",
"command": "/path/to/vecscope-mcp",
"args": ["--allow-dir", "${workspaceFolder}/data"]
}
}
}
Start it from the Start link above the entry or with MCP: List Servers, and use the
tools in the Chat view in Agent mode.
Then ask:
Audit the embeddings in data/chunks.npy before we tune the retriever, and tell me
which finding to fix first.
Tools and responses¶
audit_embeddingsruns the audit, with the same inputs as the CLI.sweep_indexruns the index sweep.compare_embeddingsruns the comparison.describe_findingslists every finding with its thresholds, causes and actions.
Responses start with a one-line summary and an audit_id. The summary names the non-ok
findings, retrieval nDCG, the first plan step and, on a re-audit, the comparison with the
baseline.
Pass that id as baseline when re-auditing after a change. The response then carries
baseline_diff (verdict and value changes, regressions, improvements, retrieval
changes), as --baseline does in the CLI, without the agent saving the earlier response.
The server keeps its last 32 audits in memory; a saved response or --json file works too.
verbose=false drops the details, explanations and actions of findings that are ok. Agents
without MCP can run the CLI with --json and read the same evidence.
The agent skill in .agents/skills/vecscope/SKILL.md
tells the agent when to run the audit and what to do about each verdict: center or swap the
model, deduplicate, re-rank, or rebuild the index. The server also carries those
instructions, so an agent that only has the MCP connection follows the same loop.
What the server may read¶
The tools are read-only, but they read whatever path the agent names, so the server limits
where that can be. A path outside the allowed directories (after resolving .. and
symlinks) is refused before it is opened.
- By default, only the directory it was started in and below.
--allow-dir DIRnames the directories instead, as in the setup above. It can be repeated; the environment variableVECSCOPE_ALLOWED_DIRS(paths separated by:on Unix,;on Windows) does the same.--allow-any(orVECSCOPE_ALLOW_ANY=1) lifts the restriction, so every file the server process can read is reachable. Use it only on your own machine.- Network vector stores need
--allow-networkon top. Read-only does not make reaching them harmless, so grant it only where the server's network access is what you intend.
Each file is read through one handle that is checked after opening: it must be a regular file, and the same file the path resolves to inside the allowed directories. A symlink swapped between the check and the read, a FIFO or a directory is refused.
Local database directories (qdrant+local:// and the like) are checked by path only,
because their client opens the files itself.
One request cannot exhaust the server's memory:
- A file larger than
--max-read-mb(default 4096;VECSCOPE_MAX_READ_MB; 0 for no limit) is refused before it is read. - A store stops being read once its vectors pass the same size.
--max-rowsand--max-dim(VECSCOPE_MAX_ROWS,VECSCOPE_MAX_DIM; default 0 for no limit) refuse a matrix with more rows or columns than that, whatever its byte size; the queries file is checked the same way, and a store stops being read at--max-rows.- Files are parsed straight from the checked handle, never copied into memory first. On a
500,000 x 384
.npyfile (0.72 GiB) an MCP read peaks at 0.79 GiB, as the CLI does. - A
MemoryErrorwhile reading or auditing is returned to the agent as a tool error that names the ways out (a sample, a smaller input, the limits above) instead of ending the call silently.
Calls in parallel, or with expensive settings, are bounded too:
- The server runs each tool call in its own thread. Audits, sweeps and compares take one of
--max-concurrentslots (default 1;VECSCOPE_MAX_CONCURRENT), and further calls wait. An agent that fires three audits at once therefore holds one corpus in memory, not three. - Settings that multiply a call's cost are capped per call:
kandclustersat 1,000,sample_repeatsandtiming_repeatsat 10,n_queriesat 100,000 andlatency_queriesat 10,000. The CLI has no caps.
Each audit, sweep and compare writes one line to the server's stderr, which MCP clients keep in their logs. It names the tool and every file or store it read (credentials redacted), the verdict or error, and the time taken, including any wait for a slot:
vecscope-mcp: audit_embeddings path=/data/run/corpus.npy qrels_path=/data/run/qrels.tsv: fail in 2.1 s
The recent audits that baseline refers to are kept behind a lock. A stdio server serves the
one client that started it; agents that run in parallel each start their own server.
Tested clients¶
The diagnose, change and re-verify loop is tested over the MCP stdio protocol
(tests/test_agent_workflow.py), and was run end to end by Claude Code in headless mode
(claude -p with the server above).
It audited a corpus with a shared offset, normalized, centered and re-audited as the plan said, and stopped at the remaining step it was not asked to fix.
GitHub Copilot in VS Code (Agent mode, .vscode/mcp.json above) was run by hand on the
example matrices from examples/make_examples.py:
healthy.npy,anisotropic.npyandcollapsed.npycame back ok, warn and fail with the values ofvecscope audit, and the agent recommended the first step ofplan.- After centering and re-normalizing
anisotropic.npy, it re-audited with the firstaudit_idasbaselineand reported anisotropy and antihubs as improvements. - A file outside
--allow-dirwas refused by the server, and the agent did not try to work around the refusal. - Copilot moves a response of this size (about 13,000 to 15,000 characters with
verboseon) to a file and reads it in parts, which costs a few extra tool calls per audit but did not change any answer.
Cursor and Codex use the same protocol and were not run.
docs/agent_case.md records two cases on real SciFact embeddings, each run twice:
- Two ingestion faults: a batch ingested twice and a worker that skipped normalization.
From the symptom alone, the agent found both, fixed the corpus and re-audited against its
first
audit_id. Production nDCG@10 went from 0.100 to 0.713. - An IVF index searched with nprobe=1: the audit found the embeddings healthy and the production ranking 0.29 nDCG below exact search. The agent swept the index, chose nprobe, and production nDCG@10 went from 0.422 to 0.700 and 0.711.
If the server stops connecting¶
"vecscope-mcp not found" usually means the Python environment it was installed into has been replaced. This happens on hosted notebooks and clusters that rebuild their environment.
Check with pip show vecscope in the interpreter the client uses and reinstall there. Then
register the server through that interpreter, so the error names the right environment:
{ "mcpServers": { "vecscope": { "command": "/path/to/env/bin/python", "args": ["-m", "vecscope.mcp_server"] } } }