UNBLOCK/ docs
api.kaeva.app ↗
[α] Cookbook 5 IDEs · 1 contract copy-paste-ready

Wire UNBLOCK into your IDE in under ten minutes.

Five recipes. Same 10 verbs everywhere. Every section ends with a remember → query round-trip you can run today against the production API at api.kaeva.app.

[00] Prerequisites

You need an UNBLOCK API key. Format: unb_<32hex>. The catalog-api derives a stable user_id from SHA-256(key) — see services/catalog-api/src/auth/api-key.ts.

If you don't have one yet, generate a 32-hex string locally and use that as your dogfood key. Production keychain-bind ships in Sprint 8; until then, the API-key path is the canonical auth surface.

# One-liner to mint a local dogfood key
echo "unb_$(python -c 'import secrets; print(secrets.token_hex(16))')"
Heads up. Every recipe below points at api.kaeva.app. If you're hitting a staging Worker, swap the URL to https://unblock-catalog-api-v01.virajsharma5599.workers.dev. The MCP shim source lives at services/dogfood-mcp/server.py.
[01] Recipes

Cursor.

Cursor reads MCP servers from .cursor/mcp.json at the project root (or ~/.cursor/mcp.json for global). Add the UNBLOCK shim and restart the workspace.

1 · Install the shim

git clone https://github.com/Viraj0518/UNBLOCK_0.1.0.git
cd UNBLOCK_0.1.0/services/dogfood-mcp
python -m venv venv && source venv/Scripts/activate
pip install -r requirements.txt

2 · Configure .cursor/mcp.json

{
  "mcpServers": {
    "unblock": {
      "command": "python",
      "args": ["/abs/path/to/UNBLOCK_0.1.0/services/dogfood-mcp/server.py"],
      "env": {
        "UNBLOCK_API_KEY": "unb_REPLACE_WITH_32HEX",
        "UNBLOCK_CATALOG_API": "https://api.kaeva.app"
      }
    }
  }
}

3 · Test it

Reopen Cursor, then in the agent panel:

@unblock remember the decision: "Cursor mcp.json is project-scoped"
@unblock query "Cursor mcp"

Round-trip should return your block at top-rank within ~1 s. If you see AUTH_INVALID, your key isn't in unb_<32hex> shape.

VS Code.

VS Code's native MCP support landed in 1.97. Two paths: native (.vscode/mcp.json) or via Continue.dev for older versions.

Native (VS Code 1.97+) · .vscode/mcp.json

{
  "servers": {
    "unblock": {
      "type": "stdio",
      "command": "python",
      "args": ["${workspaceFolder}/services/dogfood-mcp/server.py"],
      "env": {
        "UNBLOCK_API_KEY": "unb_REPLACE_WITH_32HEX",
        "UNBLOCK_CATALOG_API": "https://api.kaeva.app"
      }
    }
  }
}

Continue.dev fallback · ~/.continue/config.yaml

mcpServers:
  - name: unblock
    command: python
    args:
      - /abs/path/to/UNBLOCK_0.1.0/services/dogfood-mcp/server.py
    env:
      UNBLOCK_API_KEY: unb_REPLACE_WITH_32HEX
      UNBLOCK_CATALOG_API: https://api.kaeva.app

Test it

Open the chat panel, switch to Agent mode, then:

/unblock_remember content="VS Code MCP wired" block_type=note
/unblock_query text="VS Code MCP" scope=mine top_k=5

Claude Code.

Claude Code reads MCP servers from ~/.claude.json, or per-project from .claude/settings.json. The dogfood shim is the same Python server everywhere.

1 · CLI install (recommended)

claude mcp add unblock python \
  /abs/path/to/UNBLOCK_0.1.0/services/dogfood-mcp/server.py \
  --env UNBLOCK_API_KEY=unb_REPLACE_WITH_32HEX \
  --env UNBLOCK_CATALOG_API=https://api.kaeva.app

2 · Manual ~/.claude.json

{
  "mcpServers": {
    "unblock": {
      "command": "python",
      "args": ["/abs/path/to/UNBLOCK_0.1.0/services/dogfood-mcp/server.py"],
      "env": {
        "UNBLOCK_API_KEY": "unb_REPLACE_WITH_32HEX",
        "UNBLOCK_CATALOG_API": "https://api.kaeva.app"
      }
    }
  }
}

3 · Test it

Restart Claude Code. The 10 unblock_* tools (plus unblock_ingest for substrate dogfood) appear in the tool list.

Use unblock_remember to store: "Claude Code MCP works end-to-end"
Then unblock_query for "Claude Code MCP".

You should see your block come back as the top result. The full tool roster is documented in services/dogfood-mcp/README.md.

Codex (OpenAI).

Codex doesn't speak MCP natively yet — wire UNBLOCK as a function-calling layer. The 10 verbs map 1:1 to OpenAI tool definitions.

1 · Tool definitions (Python)

UNBLOCK_TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "unblock_remember",
            "description": "Capture a discrete block of knowledge. Returns a stable block_id.",
            "parameters": {
                "type": "object",
                "required": ["content"],
                "properties": {
                    "content": {"type": "string"},
                    "block_type": {"type": "string", "enum": [
                        "note","snippet","doc","code","trace","decision",
                        "anti-pattern","dataset","exploit","kg","other","conversation"
                    ]},
                    "scope": {"type": "string", "enum": ["private","team","public"]},
                    "tags": {"type": "array", "items": {"type": "string"}},
                },
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "unblock_query",
            "description": "Semantic search across blocks. Returns ranked results.",
            "parameters": {
                "type": "object",
                "required": ["text"],
                "properties": {
                    "text": {"type": "string"},
                    "scope": {"type": "string", "enum": ["mine","public","all"]},
                    "top_k": {"type": "integer", "minimum": 1, "maximum": 100},
                },
            },
        },
    },
    # … 8 more verbs: share, list, purchase, verify, attest, subscribe, update, extract
]

2 · Bridge function

import os, httpx

API = os.environ["UNBLOCK_CATALOG_API"]   # https://api.kaeva.app
KEY = os.environ["UNBLOCK_API_KEY"]

def call_unblock(name: str, args: dict) -> dict:
    """Codex tool-call → UNBLOCK HTTP. name = unblock_."""
    verb = name.removeprefix("unblock_")
    r = httpx.post(
        f"{API}/v1/{verb}",
        json=args,
        headers={"X-API-Key": KEY, "Content-Type": "application/json"},
        timeout=30.0,
    )
    r.raise_for_status()
    return r.json()

3 · Test it

export UNBLOCK_API_KEY=unb_REPLACE_WITH_32HEX
export UNBLOCK_CATALOG_API=https://api.kaeva.app
python -c "from bridge import call_unblock; \
  blk = call_unblock('unblock_remember', {'content': 'Codex bridge live'}); \
  print(blk); \
  print(call_unblock('unblock_query', {'text': 'Codex bridge', 'top_k': 3}))"

Perplexity.

Perplexity doesn't host arbitrary MCP servers — wire UNBLOCK as an HTTP API-key bridge from a Perplexity Pro space or Comet agent. Pattern: an outbound webhook in your space hits a tiny shim Worker that forwards to UNBLOCK with the right header.

1 · Deploy a 30-line Cloudflare Worker bridge

// perplexity-bridge.js — deploy with `wrangler deploy`
export default {
  async fetch(req, env) {
    const url = new URL(req.url);
    const verb = url.pathname.replace(/^\/+/, "");   // e.g. "remember"
    const body = req.method === "POST" ? await req.text() : "";
    const upstream = await fetch(`https://api.kaeva.app/v1/${verb}`, {
      method: req.method,
      headers: {
        "X-API-Key": env.UNBLOCK_API_KEY,
        "Content-Type": "application/json",
      },
      body: body || undefined,
    });
    return new Response(await upstream.text(), {
      status: upstream.status,
      headers: { "Content-Type": "application/json" },
    });
  },
};

2 · Wire from Perplexity Pro space

In your Perplexity space's connected actions, point the action endpoint at your bridge URL (https://unblock-bridge.<your-account>.workers.dev/remember) and define the input schema:

{
  "name": "unblock_remember",
  "description": "Save a fact UNBLOCK should remember.",
  "method": "POST",
  "url": "https://unblock-bridge.example.workers.dev/remember",
  "body": {
    "content": "{{user_input}}",
    "block_type": "note",
    "scope": "private"
  }
}

3 · Test it

curl -X POST https://unblock-bridge.example.workers.dev/remember \
  -H "Content-Type: application/json" \
  -d '{"content": "Perplexity bridge live", "block_type": "note"}'

curl -X POST https://unblock-bridge.example.workers.dev/query \
  -H "Content-Type: application/json" \
  -d '{"text": "Perplexity bridge", "top_k": 3}'

Pro tip: the bridge pattern works for any tool that lacks native MCP — Glean, Notion, Slack-AI, etc. One Worker, one secret, ten verbs.

[02] Universal round-trip

The same two-line smoke test, anywhere.

Whatever IDE or shim you wired, the round-trip is the same: POST /v1/remember then POST /v1/query. If both return 200, you're integrated.

curl -X POST https://api.kaeva.app/v1/remember \
  -H "X-API-Key: unb_REPLACE_WITH_32HEX" \
  -H "Content-Type: application/json" \
  -d '{"content": "smoke test from cookbook", "block_type": "note"}'
# → {"block_id": "blk_…", "version": 1, "user_id": "usr_…", …}

curl -X POST https://api.kaeva.app/v1/query \
  -H "X-API-Key: unb_REPLACE_WITH_32HEX" \
  -H "Content-Type: application/json" \
  -d '{"text": "smoke test", "scope": "mine", "top_k": 5}'
# → {"results": [{"block_id": "blk_…", "score": 0.94, …}]}
If query returns zero results within ~10 s of the remember call: Vectorize is async-indexed (~3-8 s typical) — retry once. If still zero after 30 s, the most likely culprit is a key/user_id mismatch (different keys → different usr_ namespaces). See architecture for the user-isolation model.