Documentation

How to use StashKV

StashKV is a namespaced JSON key-value store for AI agents. Create a space, get a token, and read/write JSON over MCP tools or a plain REST API. No signup, no accounts.

Concepts

Ids (space and key) must match [a-zA-Z0-9_-]{1,64}. A token is bound to exactly one space.

Quickstart

Create a space — the token is returned once, so save it.

curl -X POST https://stashkv.com/v1/spaces
# -> { "space": "k3f9p2a1b2", "token": "sk_live_..." }

Or click Create a space on the home page. Then connect an MCP client or use the REST API below.

Connect via MCP

The hosted server is the MCP server. Point any MCP client at the /mcp endpoint with your token as a bearer header.

Claude Code — CLI

claude mcp add --transport http stashkv https://stashkv.com/mcp \
  --header "Authorization: Bearer sk_live_..."

Per-project — .mcp.json

Commit this and keep the token in an env var instead of in git:

{
  "mcpServers": {
    "stashkv": {
      "type": "http",
      "url": "https://stashkv.com/mcp",
      "headers": { "Authorization": "Bearer ${STASHKV_TOKEN}" }
    }
  }
}

Then set STASHKV_TOKEN in each environment (laptop shell profile, cloud box secrets) and run claude.

MCP tools

Your token is bound to one space, so space is optional on every tool — omit it to use the token's space. In an agent you just ask in natural language ("remember this", "what's stashed under memory?") and the client picks the right tool.

ToolArgumentsWhat it does
stash_create_space space? Mint a new space; returns { space, token }. Token shown once.
stash_put key, value, if_match? Overwrite the entire value at a key. Returns { version, updated_at }.
stash_get key Read a key. Returns { value, version, updated_at } or { found: false }.
stash_patch key, patch Shallow-merge an object into the existing value and bump the version.
stash_list List keys with versions and timestamps.
stash_delete key Delete a key. Returns { deleted: true }.

put replaces the whole value; patch merges keys into an existing object.

REST API

Every request carries Authorization: Bearer <token>.

Method & pathNotes
POST /v1/spacesPublic. Body { space? }201 { space, token }, 409 if taken.
GET /v1/spaces/:space/keys/:key{ value, version, updated_at }, 404 if missing.
PUT /v1/spaces/:space/keys/:keyBody { value }. Optional If-Match: <version>412 on mismatch.
PATCH /v1/spaces/:space/keys/:keyBody { patch }. Shallow-merges into an object value. 404 if missing.
GET /v1/spaces/:space/keys{ keys: [{ key, version, updated_at }] }.
DELETE /v1/spaces/:space/keys/:key204.

A round-trip with curl:

TOKEN=sk_live_...; SPACE=k3f9p2a1b2; H="Authorization: Bearer $TOKEN"

curl -X PUT https://stashkv.com/v1/spaces/$SPACE/keys/memory -H "$H" \
  -H 'Content-Type: application/json' -d '{"value":{"hello":"world"}}'

curl https://stashkv.com/v1/spaces/$SPACE/keys/memory -H "$H"

Concurrency

Every value has an opaque version. To avoid clobbering another writer, pass the version you last read as if_match (MCP) or If-Match (REST). If it no longer matches, the write is rejected — { conflict: true, current_version } over MCP, 412 over REST — so re-read and retry. A write with no if_match is last-write-wins.

Token model

Limits & errors