stillvault-mcp
# Stillvault MCP server
Give an AI agent access to real secrets — API keys, database passwords — with a
named human approving each release on their device, and **without the secret ever
entering the model's context**.
This is a thin shim over the `stillvault` CLI. It contains no cryptography and holds
no secret material: every release, approval, and unsealing happens in the CLI and on
the approver's device, exactly as it does from a shell. The agent calls a tool; a
human approves on their phone or the web console; the secret is used and never shown
to the model.
## Why the secret never reaches the model
The headline tool, `stillvault_run`, doesn't return secret values. It runs a command
you choose, substitutes `stillvault://<path>` references into that process after
approval, and returns only the command's output. The plaintext lives only in the
child process, on the local machine, for that command's lifetime — never in the
conversation, and never in your LLM provider's logs.
There is a second tool, `stillvault_reveal`, for the rare case where the value itself
must be read. It says plainly what it costs (the secret enters the model context) and
should be the exception.
## Onboarding
### 1. Install the `stillvault` CLI
```sh
curl -fsSL https://stillvault.ai/install.sh | sh # macOS / Linux
# Windows (PowerShell):
irm https://stillvault.ai/install.ps1 | iex
```
### 2. Enrol this machine as an agent
The agent gets its own signing key — the org key never lives here. Create an
enrolment token in the web console (Agents), then:
```sh
stillvault agent-enroll --agent claude-prod --org <your-org-id> --token <one-time-token>
```
An admin admits it in the console after checking the fingerprint. Scope the paths it
may request with an access policy. See
<https://stillvault.ai/docs/agents/>.
### 3. Add the MCP server to your client
It runs over stdio via `npx` — no separate install.
**Claude Desktop / Claude Code** (`claude_desktop_config.json` or `.mcp.json`):
```json
{
"mcpServers": {
"stillvault": {
"command": "npx",
"args": ["-y", "@wolstapp/stillvault-mcp"],
"env": {
"STILLVAULT_AGENT": "claude-prod",
"STILLVAULT_TENANT": "<your-org-id>"
}
}
}
}
```
**Claude Code, one-liner:**
```sh
claude mcp add stillvault -e STILLVAULT_AGENT=claude-prod -e STILLVAULT_TENANT=<org-id> \
-- npx -y @wolstapp/stillvault-mcp
```
That's it. The agent can now request secrets, and you approve each release on your
device.
## The tools
### `stillvault_run` (preferred)
Runs a local command with secrets injected, never revealing them.
- `command` — the executable, e.g. `psql`, `curl`, `./deploy.sh`.
- `args` — arguments; any `stillvault://<path>` is replaced with the secret after
approval. Embed inside a longer string with `{{stillvault://<path>}}`.
- `secret_env` — optional map of environment variables whose values contain
references (e.g. `{"DATABASE_URL": "stillvault://db/prod/dsn"}`). Switches to the
safer mode where secrets go in the child's environment, not its command line.
Returns the command's stdout/stderr and exit code. Blocks until a human approves
(or the wait times out, default 130s).
### `stillvault_reveal` (exposes the value)
Returns a secret's plaintext into the conversation after approval. **This puts the
secret in the model's context and your provider's logs.** Prefer `stillvault_run`.
- `path` — the secret path, e.g. `db/prod/password`.
## Configuration
| Env var | Default | Purpose |
|---|---|---|
| `STILLVAULT_AGENT` | _(none)_ | Enrolled agent id; releases are signed with its key. Set this for managed use. |
| `STILLVAULT_TENANT` | _(none)_ | Your org id (managed broker per-tenant lookup). |
| `STILLVAULT_BROKER` | `https://stillvault.ai` | Broker URL (set for self-hosted). |
| `STILLVAULT_BIN` | `stillvault` | Path to the CLI if not on `PATH`. |
| `STILLVAULT_APPROVAL_WAIT` | `130` | Seconds to wait for each approval. |
## What this server is and isn't
- It **is** a launcher for the `stillvault` release loop, surfaced as MCP tools.
- It **does not** decrypt anything, hold keys, or talk to the broker directly — the
CLI does that, and the key that opens a secret only ever exists on the approver's
device.
- Approval is per release. A short, policy-bounded lease in the CLI means a tight
loop reading the same secret doesn't prompt a human on every call — see
<https://stillvault.ai/docs/how-it-works/>.
## Develop locally
```sh
npm install
npm run build
npm start # serves over stdio
```
TDQS
Scored across 2 tools
Both tools handle secrets but have clearly distinct purposes: stillvault_reveal returns the secret value to the conversation, while stillvault_run uses it in a command without revealing it. Their descriptions explicitly differentiate them and provide guidance on when to use each, leaving no ambiguity.
Both tools follow a consistent 'stillvault_verb' pattern in snake_case. The verb choice ('reveal' and 'run') clearly indicates their action, and the naming is uniform and predictable.
With only 2 tools, the server feels minimal but appropriately focused on its purpose: using secrets with human approval. However, it lacks any administrative tools (e.g., list, create, delete secrets), which might be expected from a secrets management server, making the count borderline.
The tools cover the two primary use cases (revealing and running secrets), but there is no way to discover available secrets or manage them. Agents must know the secret path in advance, which is a notable gap that could cause failures when the path is unknown.