hypervault-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@hypervault-mcpsave this HTML snippet as a new artifact titled 'Hello World'"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
hypervault-mcp
MCP server for HyperVault — lets any MCP-capable agent save artifacts to a user's vault and claim vanity subdomains.
Built with FastMCP.
Hosted endpoint: https://mcp.vault.cool/mcp (Streamable HTTP) — no
install needed, just point your MCP client at it with your own API key. See
Auth & rate limits for the header format.
Install & run
pip install -e . # from this directory (or: uv pip install -e .)
export HYPERVAULT_API_KEY=hv_... # create one in the web dashboard (/vault)
export HYPERVAULT_API_URL=https://hypervault.store # optional; defaults to hypervault.store
hypervault-mcp # STDIO (local agents)
hypervault-mcp --transport http --port 8787 # HTTP (web agents)Authentication differs by transport — see Auth & rate limits below.
Related MCP server: hashnet-mcp
Tools
Tool | What it does |
| Saves HTML or React/JSX and returns a permanent, installable URL. JSX is auto-detected and wrapped server-side. |
| Claims |
| Connects two existing artifacts (bidirectional, drawn in graph view). |
| Lists everything already in the vault. |
| Reads an artifact's current editable source (raw JSX for JSX artifacts, HTML otherwise) by slug or URL. Pass a |
| Writes a new iteration of a mutable artifact — a git commit on the living document. The page updates in place (URL unchanged) and the write is kept as a version. Immutable artifacts are refused. |
| Lists a mutable artifact's version history (git commits), newest first, with authorship. Revert by reading an old version and writing it back. |
| Fetches any artifact URL (vanity domains included) and returns the source prompt from its hidden |
| Permanently deletes an artifact (and its graph connections). Irreversible — the share URL stops working immediately. |
| Saves a multi-file artifact group — several |
| Reads a group's full file set and metadata by slug or URL. |
| Lists everything already saved as a group. |
| Adds a new file to an existing group (fails if that path already exists). |
| Replaces an existing file's content, including |
| Removes a file from a group. The root |
| Permanently deletes a whole group. Irreversible. |
| Stores a chunk in the user's private memory wiki (Imaging V2). Auto-titled, auto-tagged, summarized, and linked to related memories in their knowledge graph. |
| Natural-language search over the wiki ("what did I say about the Rust borrow checker?"). Top matches return the exact stored content; every match lists its linked memories. |
| Browses everything memorized, newest first (summaries + tags). |
| Permanently deletes one memory — only on the user's explicit request. |
| Creates a universal task board — a shared, versioned task list — plus the interactive board page the user watches it on. Returns |
| Lists the user's existing boards, so you can join one instead of creating a duplicate. |
| Reads the full list. With |
| Rollup only: counts, progress, epics, who holds what. Prefer it over the full list for status reporting on a large board. |
| Adds a task to an existing board. |
| Patches one task; only the arguments you pass change. |
| Claims a task — lock + assign + |
| Done, progress 100, lock released, in one call. The response includes the list |
Plus the hypervault://help resource with agent-facing usage notes.
Memories are owner-only: they power the Memory Control Panel at
/vault/memory and are never rendered on public pages.
Mutable artifacts (a living document)
Artifacts are immutable by default: a save is permanent, and re-saving the same
content just returns the existing link. Save with mutable=True to get a
document you can iterate on in place — its URL never changes, and every write is
kept as a git commit you can list and revert to:
saved = save_to_hypervault(content="<h1>v1</h1>", title="Notes", mutable=True)
read_artifact(saved["slug"]) # -> current source + head version
write_artifact(saved["slug"], "<h1>v2</h1>", message="expand intro")
artifact_history(saved["slug"]) # -> the commit chain, newest firstread_artifact → edit → write_artifact is the iteration loop; to revert, read
an old version's content (read_artifact(ref, version=...)) and write it back.
The write tools are owner-scoped (the API key resolves to its owner), so a
mutable artifact is read and written privately even when the page is public.
Artifact groups (multi-file projects)
Use an artifact group instead of save_to_hypervault when a project needs more
than one file — separate markup, styles, and script(s) that reference each
other normally, like a tiny JSFiddle. A group always runs/previews as a
container at https://hypervault.store/g/{slug} — a minimal editor/preview UI
similar to JSFiddle — routed through a required root index.html.
group = create_artifact_group(
files=[
{"path": "index.html", "content": "<link rel='stylesheet' href='style.css'><script src='app.js'></script>"},
{"path": "style.css", "content": "body { font-family: sans-serif; }"},
{"path": "app.js", "content": "console.log('hello from the group')"},
],
title="My Widget",
)
read_artifact_group(group["slug"]) # -> current files + metadata
add_artifact_group_item(group["slug"], "extra.js", "// more code") # add a new file
edit_artifact_group_item(group["slug"], "style.css", "body { color: red; }") # replace a file's content
remove_artifact_group_item(group["slug"], "extra.js") # remove a file (not index.html)
list_artifact_groups() # browse everything saved
delete_artifact_group(group["slug"]) # permanently delete the groupValidation runs locally before any network call, so bad input never reaches the backend:
Exactly one root file at path
index.html— the entry point the run/preview container routes through. A nested one likepublic/index.htmldoes not count.Paths must be relative, use
/as the separator, contain no..segments, and only[A-Za-z0-9._/-]characters.Extensions are limited to
.html,.css,.js,.jsx.At most 50 files; 256 KB per file; 1 MB total.
Paths must be unique (case-insensitively).
The root
index.htmlcan't be removed withremove_artifact_group_item— edit its content instead, or delete the whole group.
Universal task boards (shared work lists)
A task board is a shared, versioned task list that an agent and the user work
from together. One call creates both halves: a JSON data artifact
(tasks-{project}) the agent syncs through, and an interactive board page
(taskboard-{project}) the user opens to watch and steer the work live. Every
write is an artifact version (audit trail + rollback), writes are
optimistic-concurrency-safe, and claims are locks, so several agents can share
one board without collisions.
board = create_task_board(
title="Eurorack choir firmware",
tasks=[
{"id": "epic-1", "title": "Firmware", "type": "epic"},
{"title": "Bring up I2S clocking", "parent": "epic-1", "priority": "high"},
],
)
project = board["project"]
board["board"]["url"] # <- hand this to the user; it's the living UI
tasks = tasklist_get(project)["tasklist"]["tasks"]
task_claim(project, tasks[1]["id"], agent_name="claude-code:session-abc")
task_update(project, tasks[1]["id"], progress=50, note="I2S clock locked at 48 kHz")
task_complete(project, tasks[1]["id"], note="landed in PR #12")
tasklist_get(project, since_version=12) # -> {"unchanged": true, ...} when nothing moved
tasklist_summary(project) # -> counts, progress, epics, claimsThe protocol agents should follow (it's also spelled out in
hypervault://help, so a connected agent reads it without being told):
Read at session start, and re-poll with
since_versionat tool boundaries — that's how the user's steering from the board page reaches you mid-task.Claim deliberately. Prefer tasks assigned to you or unassigned. A live foreign lock fails with a 409 naming the holder;
forceis only for a holder who is clearly gone (expired locks need no force). Locks last 60 minutes by default, 24 h max, and re-claiming your own task renews it.Push every meaningful change immediately — the user's board polls the same list, and a stale board means they're steering blind.
Send
expected_versionon writes. A version conflict comes back as{conflict: true, latest, error}— andlatestis the whole fresh list, so the tools return that payload rather than collapsing it into an error message. Re-apply your change on top oflatest; don't overwrite.Map both ways via
metadata.externalIdto keep a native todo list and the board in sync.
Statuses are todo | in_progress | blocked | review | done | cancelled;
priorities are low | medium | high | critical. Marking a task done (either
tool) releases the lock, and a done task can't be re-claimed. Task writes
return the whole list for convenience — on a large board that's token-heavy, so
reach for tasklist_summary and since_version polling instead.
Claude Desktop / Claude Code config
{
"mcpServers": {
"hypervault": {
"command": "hypervault-mcp",
"env": {
"HYPERVAULT_API_KEY": "hv_your_key_here"
}
}
}
}Running under greywall (sandboxed agents)
The server is single-host on purpose: every tool call — including
extract_source_prompt, which resolves artifact URLs through the backend's
/api/extract — goes to the API origin only. That means it works inside
deny-by-default sandboxes like greywall
with exactly one domain allowed:
export HYPERVAULT_API_KEY=hv_...
greywall --profile claude,python --settings ./greywall.json -- claudeThen allow the API host (hypervault.store, or your HYPERVAULT_API_URL) in
the greyproxy dashboard. The greywall.json template also
marks HYPERVAULT_API_KEY as a secret, so the sandboxed agent only ever sees
a placeholder — greyproxy substitutes the real key into the
X-HyperVault-Key header outside the sandbox. Full guide:
docs/greywall.md.
Auth & rate limits
Keys are minted (and revoked) in the web dashboard's Vault → Agent API keys panel. This MCP server never stores or looks up keys itself — it forwards whatever key you give it straight to the real HyperVault backend (hypervault.store), which is the only place that ever validates one (it stores just a salted SHA-256 hash and enforces 60 requests/minute per key).
How the key gets there depends on the transport:
STDIO (
hypervault-mcp, no--transport http) — a single trusted local process. The key comes from theHYPERVAULT_API_KEYenvironment variable, set once when you start the server (as in Install & run above).HTTP (
hypervault-mcp --transport http, and the hosted Vercel deployment) — a single server can be shared by many callers, so every request must carry its own key, sent per-call as either:Authorization: Bearer hv_...(standard, recommended for MCP clients), orX-HyperVault-Key: hv_...
There is no shared fallback key for HTTP: a request with neither header is rejected with an "Authentication required" tool error before any call reaches the backend, even if the server process happens to have
HYPERVAULT_API_KEYset in its own environment. Listing the available tools (tools/list) doesn't require a key — no user data is involved — but every tool call does. Configure your MCP client to send your key as a header on the hosted endpoint, e.g. for amcp.json-style config:{ "mcpServers": { "hypervault": { "url": "https://mcp.vault.cool/mcp", "headers": { "Authorization": "Bearer hv_your_key_here" } } } }https://mcp.vault.cool/mcpis a custom-domain alias for the same deployment ashttps://hypervault-mcp.vercel.app/mcp— the two are interchangeable and always serve identical code.
Tests
pip install -e ".[test]"
pytestThe suite (tests/) covers the request-shaping logic of every tool, the
_client/_request HTTP layer (mocked with respx — no real network
calls), the extract_source_prompt preferred/legacy fallback chain, the task-board
tools (body shaping, the empty-patch and blank-agent_name guards, and the
409 conflict payload coming back intact instead of as an exception), and —
most importantly — the per-request auth model: header parsing, the
STDIO-vs-HTTP key resolution split, and full end-to-end requests against the
real ASGI app proving an unauthenticated tools/call is rejected even when
an operator HYPERVAULT_API_KEY is set in the environment.
Smoke test
With the web app running locally (npm run dev in the repo root) and a key
exported:
python - <<'PY'
from fastmcp import Client
from hypervault_mcp.server import mcp
import asyncio
async def go():
async with Client(mcp) as client:
tools = await client.list_tools()
print("tools:", [t.name for t in tools])
result = await client.call_tool("save_to_hypervault", {
"content": "<h1>Hello from an agent</h1>",
"title": "MCP smoke test",
})
print(result)
asyncio.run(go())
PYTask boards need a backend running hypervault ≥ PR #128:
python - <<'PY'
from fastmcp import Client
from hypervault_mcp.server import mcp
import asyncio
async def go():
async with Client(mcp) as c:
board = (await c.call_tool("create_task_board", {
"title": "MCP smoke", "tasks": [
{"id": "epic-1", "title": "Epic", "type": "epic"},
{"title": "Child task", "parent": "epic-1"},
]})).data
p = board["project"] # board["board"]["url"] is the human page
lst = (await c.call_tool("tasklist_get", {"project": p})).data["tasklist"]
tid = next(t["id"] for t in lst["tasks"] if t["parent"] == "epic-1")
await c.call_tool("task_claim", {"project": p, "task_id": tid, "agent_name": "smoke-test"})
await c.call_tool("task_update", {"project": p, "task_id": tid, "progress": 50, "note": "halfway"})
done = (await c.call_tool("task_complete", {"project": p, "task_id": tid, "note": "done"})).data
assert done["summary"]["byStatus"]["done"] == 1
assert (await c.call_tool("tasklist_get", {"project": p,
"since_version": done["summary"]["version"]})).data["unchanged"] is True
print("task board:", board["board"]["url"])
asyncio.run(go())
PYMaintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-qualityAmaintenanceMCP server for BrewPage, a free no-signup hosting service. Lets AI agents publish HTML, Markdown, JSON, files, or a full multi-file static site and get a public URL instantly via a REST API.2Apache 2.0

hashnet-mcpofficial
Alicense-qualityDmaintenanceUniversal MCP server for discovery, chat, registration, credits, and workflow automation across the HOL Registry Broker ecosystem.13213Apache 2.0
wundervaultofficial
AlicenseAqualityAmaintenanceMCP server for Wundervault zero-knowledge secret management. Exposes vault secrets to AI agents via the Model Context Protocol — secrets are decrypted server-side and never returned to the agent in plaintext.61082AGPL 3.0- Alicense-qualityDmaintenanceMCP server for domainagent.dev, enabling AI agents to search, register, deploy, host, and manage domains with USDC payment on Base via x402. Supports static site deployment via Cloudflare Pages and DNS management.16MIT
Related MCP Connectors
Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.
Artifact store for AI agents. Hosted OAuth at mcp.artifacta.io/mcp; local stdio via npm/PyPI.
MCP server for AgentDocs (agentdocs.eu): read, search, write, comment on & share Markdown docs.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/johnnyclem/hypervault-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server