Reaching Vaultspec from your agentLink to Reaching Vaultspec from your agent

Connect your agent through Model Context Protocol (MCP) to call vault operations as tools. The MCP server uses the same validation and identifier rules as the command-line interface (CLI). See the MCP reference for tools and parameters.

Point your agent at itLink to Point your agent at it

Run vaultspec-core install to configure supported agents. The installer writes the server entry in each provider’s format. A default .mcp.json entry is:

File contents

{
  "mcpServers": {
    "vaultspec-core": {
      "command": "uvx",
      "args": [
        "--from",
        "vaultspec-core",
        "python",
        "-m",
        "vaultspec_core.mcp_server.app"
      ]
    }
  }
}

The launch command depends on the installation mode. With both core and vaultspec-rag installed as project dependencies, the entries use the project environment:

File contents

{
  "mcpServers": {
    "vaultspec-core": {
      "command": "uv",
      "args": [
        "run",
        "--no-sync",
        "python",
        "-m",
        "vaultspec_core.mcp_server.app"
      ]
    },
    "vaultspec-rag": {
      "command": "uv",
      "args": [
        "run",
        "--no-sync",
        "python",
        "-m",
        "vaultspec_rag.server"
      ]
    }
  }
}

Check install mode in vaultspec-core doctor before comparing your generated configuration with an example. See installation modes for setup details and combined server entries for core and vaultspec-rag in the default mode.

In .codex/config.toml, find the installer-managed mcps region:

File contents

# <vaultspec type="mcps">
[mcp_servers."vaultspec-core"]
args = ["--from", "vaultspec-core", "python", "-m", "vaultspec_core.mcp_server.app"]
command = "uvx"
# </vaultspec>

Your agent launches the core MCP server over standard input and output; no separate core service or network port is needed for this configuration.

For vaultspec-rag, start its background service before using its search tools. Follow vaultspec-rag MCP setup for the startup sequence.

If your agent requests approval for the configured server, review and approve it in the agent’s interface before using its tools.

Two products, one fileLink to Two products, one file

The search component answers to two names here, and only one of them belongs in a project file. The package and the .mcp.json key are both vaultspec-rag, which is what the entries below use. vaultspec-search-mcp is a console script the base install registers, and it is one of two ways to launch the same server rather than a second server.

vaultspec-rag declares its own server in the same .mcp.json, and its installer writes that entry the same way core writes its own. Running vaultspec-rag install in a project that already has the harness leaves you this, which is the file a reader who installed both as tools ends up holding:

File contents

{
  "mcpServers": {
    "vaultspec-core": {
      "command": "uvx",
      "args": [
        "--from",
        "vaultspec-core",
        "python",
        "-m",
        "vaultspec_core.mcp_server.app"
      ]
    },
    "vaultspec-rag": {
      "command": "uvx",
      "args": [
        "--from",
        "vaultspec-rag[gpu,mcp]",
        "python",
        "-m",
        "vaultspec_rag.server"
      ]
    }
  }
}

core and vaultspec-rag use separate keys in the same configuration. The vaultspec-rag entry requests the gpu,mcp extras at launch. To skip MCP enrollment during vaultspec-rag installation, use vaultspec-rag install --no-mcp.

Keep installer-managed entries in their generated form. Use the manual vaultspec-search-mcp configuration only for clients the installer does not manage; see vaultspec-rag MCP setup.

When the two components are in different modesLink to When the two components are in different modes

The file above is the tool route: both components installed as tools, both launched with uvx. The quickstarts on this site do not take it. The front page installs core with uv tool install vaultspec-core, and vaultspec-rag’s tutorial installs it with uv add "vaultspec-rag[gpu]", which is one of each. A workspace records the mode per package rather than for itself, so that combination is a supported state and not a mistake.

It does not arrive tidy. Because vaultspec-rag depends on core, adding vaultspec-rag to a project also brings core into the project environment, and the entries written at that point launch both out of the project - which is no longer the tool mode core is declared in. The mode check reports the mismatch rather than the mode (showing only the two install-mode lines of a longer report):

Command

vaultspec-core doctor

Captured output

  install mode (vaultspec-core) warn declared tool; hook entries or MCP command do not match; run vaultspec-core install --upgrade, or install --mode to re-provision
  install mode (vaultspec-rag) ok declared dependency; artifacts match

Of the two remedies that message offers, --mode is not the one to reach for on a project that is already installed: it stops on Error: vaultspec is already installed at <path>. Reconcile with the other:

Command

vaultspec-core install --upgrade

Running the check again reports the declared modes instead of the mismatch, and core stays a tool:

Command

vaultspec-core doctor

Captured output

  install mode (vaultspec-core) ok declared tool; artifacts match
  install mode (vaultspec-rag) ok declared dependency; artifacts match

The reconciled file is the one this combination ends up holding. Core launches as a tool and vaultspec-rag out of the project, in the same .mcp.json:

File contents

{
  "mcpServers": {
    "vaultspec-core": {
      "command": "uvx",
      "args": [
        "--from",
        "vaultspec-core",
        "python",
        "-m",
        "vaultspec_core.mcp_server.app"
      ]
    },
    "vaultspec-rag": {
      "command": "uv",
      "args": [
        "run",
        "--no-sync",
        "python",
        "-m",
        "vaultspec_rag.server"
      ]
    }
  }
}

Compare the command of each entry against the mode the check reports for that package, not against the file a single-mode route would leave. uvx --from is a tool; uv run --no-sync is a project dependency. An entry in the other package’s form is the mismatch above, and vaultspec-core install --upgrade is what settles it.

A hand-edited managed entry can cause sync to skip it:

Command

vaultspec-core spec mcps sync

Captured output

Scoped sync: native MCP targets only. Run vaultspec-core sync for the full provider refresh.
MCPs sync
  claude
    s vaultspec-rag
  = antigravity  up to date
  = codex  up to date
  5 unchanged  1 skipped
  - MCP server 'vaultspec-rag' in .mcp.json differs from its definition
    (use --force to overwrite).

The counts refer to server entries, not files. Do not treat a skipped entry as a durable override; see managed-entry ownership. To replace it with the managed definition, use --force:

Command

vaultspec-core spec mcps sync --force

Captured output

Scoped sync: native MCP targets only. Run vaultspec-core sync for the full provider refresh.
MCPs sync
  claude
    ~ vaultspec-rag
  = antigravity  up to date
  = codex  up to date
  1 updated  5 unchanged

Check the generated entries:

Command

vaultspec-core spec mcps status

Captured output

mcps status
  claude project ok .mcp.json vaultspec-core, vaultspec-rag none none none
  antigravity project ok .agents\mcp_config.json vaultspec-core, vaultspec-rag none none none
  codex project ok .codex\config.toml vaultspec-core, vaultspec-rag none none none
  ok: 3 provider target(s)

This reports native MCP configuration targets, not every enabled agent, and the two counts differ on an ordinary install. Setup enables four providers - .vaultspec/providers.json lists antigravity, claude, codex and gemini - while the report above names three. Gemini is the one missing, because on 0.1.73 it has no MCP configuration file for the installer to own: it receives the harness through .gemini/SYSTEM.md and .gemini/agents/ instead, and a search of .gemini/ turns up no MCP config at all. So three targets on a four-provider install is the expected reading rather than a row that fell out, and the same asymmetry is why the provider table in the MCP reference has three rows. These Windows captures have both components installed; absolute paths are shortened to their final file.

For an unmanaged client, such as a desktop application with its own configuration, install the vaultspec-rag mcp extra in the environment that provides vaultspec-search-mcp. Set an explicit project root:

File contents

{
  "mcpServers": {
    "vaultspec-rag": {
      "command": "vaultspec-search-mcp",
      "args": ["--read-only"],
      "env": {
        "VAULTSPEC_RAG_ROOT": "/absolute/path/to/your/project"
      }
    }
  }
}

Use an absolute path for VAULTSPEC_RAG_ROOT. In JSON, write Windows paths with forward slashes, such as C:/Users/me/project, or escape each backslash. Do not replace an installer-managed .mcp.json entry with this manual configuration.

Hand-editing the fileLink to Hand-editing the file

vaultspec-core records a fingerprint of every entry it wrote. An entry whose bytes no longer match its fingerprint is treated as yours for one run: that sync skips it with a warning rather than repairing it, and records what you wrote as the bytes it now tracks. The run after that finds a fingerprint that matches, reads the entry as its own, and refreshes the launch shape to the current standard. vaultspec-core spec mcps sync --force reaches the same end in one run rather than two. An entry core never wrote at all is never adopted or modified without that flag.

What a hand-edited entry goes through on the next two syncs Four states in order. First the entry core wrote, whose bytes match the fingerprint it recorded. Then your edit, after which the bytes no longer match. The next sync skips that entry with a warning and adopts what you wrote as the bytes it now tracks. The sync after that finds a fingerprint that matches, reads the entry as its own, and refreshes it to the current launch shape, at which point your edit is gone. Passing --force reaches the same end in one run instead of two. An entry core never wrote is never adopted or modified without that flag. core wrote it you edit it first sync second sync the bytes match the fingerprint it recorded the bytes no longer match skips it with a warning, and adopts what you wrote the fingerprint matches now, so it refreshes the entry your edit survives your edit is gone sync --force reaches the last box in one run; an entry core never wrote is never adopted or modified without it
  1. core wrote itthe bytes match the fingerprint it recorded
  2. you edit itthe bytes no longer match
  3. first syncskips it with a warning, and adopts what you wrote - your edit survives
  4. second syncthe fingerprint matches now, so it refreshes the entry - your edit is gone

sync --force reaches the last box in one run; an entry core never wrote is never adopted or modified without it.

An edit does not survive. It buys one sync, and the run that takes it away is an ordinary one with no flags.

If you would rather core never touched the file at all, pass --skip mcp to the first install. vaultspec-core install --skip mcp leaves a workspace with no recorded enrolment, and a workspace with no enrolment is one sync leaves alone entirely - there is no fingerprint to compare against, so nothing to adopt or refresh. On a project that is already installed the same command refuses, and the section on withholding the destructive tools has the route that works there.

The Model Context Protocol (MCP) reference sets out the ownership rules in full.

Withholding the destructive toolsLink to Withholding the destructive tools

Warning

Do not rely on a hand-added --read-only flag in an installer-managed entry. Two ordinary vaultspec-core spec mcps sync runs can remove it: the first skips the edited entry; the second refreshes it and drops the flag. This restores mutating tools, including index deletion for vaultspec-rag. Recheck the launch arguments after sync, even if its message says hand-edited entries are never refreshed.

Launch vaultspec-rag with --read-only to expose only search and read tools over MCP.

The server advertises twelve tools and the flag halves them. Six stay: search_codebase, search_vault, search_documents, search_combined, get_code_file and get_index_status. Six go: reindex_all, reindex_codebase, reindex_vault, reindex_documents, clean_documents and clean_all. Check your client’s available-tool list after reconnecting.

Append the flag to the existing launch arguments:

File contents

{
  "mcpServers": {
    "vaultspec-rag": {
      "command": "uvx",
      "args": [
        "--from",
        "vaultspec-rag[gpu,mcp]",
        "python",
        "-m",
        "vaultspec_rag.server",
        "--read-only"
      ]
    }
  }
}

Core’s server takes the same flag, and its surface is smaller than the rag one. Probed over stdio with tools/list on 0.1.73, the default launch advertises nine tools - find, create, edit, status, check, plan_progress, plan_edit, discover and invoke - of which six carry readOnlyHint: false. With --read-only four are advertised: find, status, check and discover. The five that go are create, edit, plan_progress, plan_edit and invoke, and they go from the listing rather than being refused when called, so a client is never handed the schema of something it cannot use. check stays but narrows: its fix parameter is gone and its description changes from “Run the vault health-check suite, optionally repairing.” to “Run the vault health-check suite without repair.” That is why six of the nine count as mutating while only five are withdrawn.

Whichever server you run, the mutating tools write straight into the working tree and never commit: calling create on a clean checkout leaves the new records as untracked changes and adds no commit. Run them on a clean tree if you want the diff reviewable.

This Core example demonstrates the overwrite risk after appending --read-only to a managed entry. The first sync skips it:

Command

vaultspec-core spec mcps sync

Captured output

Scoped sync: native MCP targets only. Run vaultspec-core sync for the full provider refresh.
MCPs sync
  claude
    s vaultspec-core
  = antigravity  up to date
  = codex  up to date
  2 unchanged  1 skipped
  - MCP server 'vaultspec-core' in <project>/.mcp.json differs from its definition (use --force to overwrite).

The second run, identical, takes it back:

Command

vaultspec-core spec mcps sync

Captured output

MCPs sync
  claude
    ~ vaultspec-core
  = antigravity  up to date
  = codex  up to date
  1 updated  2 unchanged
  - MCP server 'vaultspec-core' launch refreshed to the current standard: 'uvx --from vaultspec-core python -m vaultspec_core.mcp_server.app --read-only' -> 'uvx --from vaultspec-core python -m vaultspec_core.mcp_server.app' (managed entry was unchanged since vaultspec wrote it; hand-edited entries are never refreshed automatically).

The refreshed launch no longer contains --read-only, despite the message’s claim that hand-edited entries are never refreshed automatically.

This behavior was also reproduced on Core 0.1.73 with a second managed server added through spec mcps add: the first sync reported 2 skipped; the second reported 2 updated and removed both flags. The captures use a Core-only Windows project, with its path shortened to <project>.

To preserve custom launch arguments across ordinary syncs, remove managed enrollment before creating your own entries. install --skip mcp applies to the first install; it refuses an already-installed project. Preview removal:

Command

vaultspec-core spec mcps uninstall --dry-run

Captured output

  claude
    - vaultspec-core
    - vaultspec-rag
  antigravity
    - vaultspec-core
    - vaultspec-rag
  codex
    - vaultspec-core
    - vaultspec-rag
  6 removed

Re-run it with --force to apply:

Command

vaultspec-core spec mcps uninstall --force

Captured output

MCPs uninstall sync
  claude
    - vaultspec-core
  antigravity
    - vaultspec-core
  codex
    - vaultspec-core
  3 removed

These captures use different projects: the preview includes core and vaultspec-rag; the applied run includes Core only. Removal deletes managed entries and can delete their configuration file if nothing else remains.

Recreate each entry you need with --read-only, then check ownership with sync. This excerpt shows an externally managed Core entry in a project with both components:

Command

vaultspec-core spec mcps sync

Captured output

  5 created  1 skipped
  - MCP server 'vaultspec-core' in <project>/.mcp.json is externally managed; use --force to adopt it explicitly.

Confirm that each custom entry is reported as externally managed and still contains --read-only. Ordinary syncs leave external entries alone; sync --force adopts and overwrites them. The captured path is shortened.

Core also accepts --read-only, through both its module launch and the vaultspec-core-mcp command. Releases before 0.2.4 named that command vaultspec-mcp:

vaultspec-core-mcp --help

Captured output

Usage: vaultspec-core-mcp [OPTIONS] COMMAND [ARGS]...

  Run the Vaultspec MCP server.

Options:
  --parent-pid <int>  Explicit client PID for the stdio lifetime watchdog
                      (watched in addition to the discovered client)
  --read-only         Expose only non-mutating MCP tools.
  --help              Show this message and exit.

Append the flag to Core’s launch arguments. The same managed-entry overwrite warning applies. Confirm your client’s available tools against Core’s read-only tool list. check remains available without repairs; invoke is withheld.

For vaultspec-rag, start the resident service before using its tools; follow vaultspec-rag MCP setup.

Check that it connectedLink to Check that it connected

Open your client’s available-tool list and check for Core’s status and find. Read-only mode exposes fewer tools, and vaultspec-rag adds a separate set.

If Core’s tools are missing, restart the client and check whether it requires approval to launch the server. Check the installed configuration:

Command

vaultspec-core doctor

For a Claude configuration, look for:

Captured output

  mcp ok .mcp.json present

This confirms the configuration file exists, not that the client connected.

To prove the server itself answers, speak to it directly. It is a stdio server, so a client is three lines of JSON on its standard input: the handshake, the notification that the handshake is done, and one call. Run this from a project that has a vault:

vaultspec-core-mcp <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"status","arguments":{}}}
EOF

That is a POSIX heredoc. PowerShell has no such operator and reserves <, so the block above is a parse error there rather than a failed run. Its equivalent is a single-quoted here-string piped in, and the closing '@ has to sit at the start of its line:

Command

@'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"status","arguments":{}}}
'@ | vaultspec-core-mcp

Both were run against 0.2.4, and the refusal further down translates the same way. It answers one line of JSON per request. The second is the status call, and its result is the shape every tool on this page returns - abridged here to the summary line and the first feature, because the rollup also carries totals and the plans in flight:

Captured output

{"jsonrpc":"2.0","id":2,"result":{"content":[{"text":"1 active features, 0 plans in flight","type":"text"}],"isError":false,"structuredContent":{"tool_schema_version":"0.2.4","kind":"rollup","features":[{"name":"search-api","doc_count":2,"latest_activity":"2026-09-21","has_plan":true,"status":"Planned","plan_tier":"L2","plan_completion_percent":0.0}],...}}}

Two things in that answer are worth knowing before you read the tool reference. content carries a sentence for a person, and structuredContent carries the same answer as data - your agent reads the second, which is why its summaries can be more specific than the one line the server wrote. And isError is a field inside result rather than a JSON-RPC error, so a refusal arrives on the success path. Ask status for a feature that is not there - the same three lines, with one argument changed:

vaultspec-core-mcp <<'EOF'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"probe","version":"1"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"status","arguments":{"target":"no-such-feature"}}}
EOF

Captured output

{"jsonrpc":"2.0","id":2,"result":{"content":[{"text":"Error executing tool status: Could not resolve orientation target 'no-such-feature'. Run `vaultspec-core vault feature list` to enumerate available targets.","type":"text"}],"isError":true}}

That is result, not error. A client that only checks whether the call completed reads it as a success, which is why the refusals on this page are worth reading rather than assuming a silent tool worked.

Start a featureLink to Start a feature

Follow Run a feature from research to review to research, approve, and implement a change. Use the tool reference to look up parameters and write behavior.

When to use the command line insteadLink to When to use the command line instead

Use the CLI for resource syncs and plan changes above step level, including phases, waves, and tiers. These operations use the destructive invoke gateway over MCP, which can require host confirmation.

Rebuilding a feature index, managing MCP entries, and uninstalling require the CLI. See command-line guidance and the MCP reference.

Two writers, one vaultLink to Two writers, one vault

Supply expected_blob_hash when calling edit to reject a write if the document has changed since you read it. See the edit parameters.

The CLI equivalent is --expected-blob-hash. This example supplies a mismatched hash to demonstrate a refused write. Replace the document stem and body-file path with existing files in your project:

Command

vaultspec-core vault set-body 2026-09-04-payment-retries-research --body-file new-body.md --expected-blob-hash deadbeefdeadbeefdeadbeefdeadbeef

Captured output

Blob-hash conflict: document changed on disk since it was read
expected deadbeefdeadbeefdeadbeefdeadbeef, on disk 63ce7068181d11f30e097ef43d04e5dc150f5d27

The command exits 1 without changing the document. The captured on-disk hash will differ in your project. After a conflict, reread the document and reconcile your changes before retrying with its current hash.

Where to go nextLink to Where to go next