MCP-first utility toolbox for agents
raccha.ai is a small, sharp toolbox for agents: key-value storage today, queues coming next, webhooks and a mailbox after that. Reachable natively over MCP or plain HTTP, authenticated by a bearer credential bound to an account rather than a password. The website is a control plane only (config, roles, counts); it never renders stored data itself, that only ever moves over an authenticated API/MCP call.
Every route except /auth/request-link and /auth/verify requires a
credential, sent as Authorization: Bearer <key> or (browser-only) an
HttpOnly session cookie set by /auth/verify. A request with neither
returns 401 "missing credential"; a malformed, unknown, or revoked
credential returns 401 "invalid credential" -- deliberately
indistinguishable, the same way a KV slug that exists but belongs to a
different account returns the same 404 as one that does not exist at
all.
Two credential shapes, both bearer tokens:
owner_key -- unrestricted access to one account, minted on sign-in,
never expires until manually revoked.access_key -- scoped down to specific role_ids an admin picked at
mint time. Use this for anything handed to a third party or a
lower-trust automation; never share an owner_key.Three flows, depending on who or what is asking:
POST /auth/request-link
with an email. Delivery is real SMTP. The human clicks the emailed
link, which lands on /auth/verify and returns one owner_key per
organization that email belongs to, plus sets the session cookie.
One email can belong to more than one organization; each gets its
own separate owner_key.POST /auth/device/code mints a device_code and a
short human-readable user_code. Show the user_code to the human
running you and ask them to approve it at
https://raccha.ai/device.html, from a browser where they're
already signed in. Meanwhile poll POST /auth/device/token on an
interval (RFC 8628-shaped: expect authorization_pending until
approved). The human picks, at approval time, whether the poller
gets a full owner_key or a scoped access_key.POST /auth/invite,
same magic-link mechanics as flow 1, for an account that already
exists.GET /kv/{slug}/{key}, PUT /kv/{slug}/{key} -- namespace-scoped
key-value storage, the only stateful primitive that's fully live
today. Optional TTL on write.POST /queue/{slug}/push/{name}, POST /queue/{slug}/pop/{name} --
FIFO queue per namespace. Live, newer than KV.GET /stats -- per-account usage counts (what the dashboard renders).POST /telegram/pair-code, POST /telegram/webhook -- Telegram bot
pairing: inbound messages land in a queue, outbound send is a tool
call./admin/roles, /admin/roles/{id} -- role definitions an admin
manages, referenced by role_ids when minting an access_key./admin/access-keys, /admin/access-keys/{id},
/admin/access-keys/{id}/revoke -- scoped-credential lifecycle,
admin-gated.POST /tools/jwt-decode, /tools/hash, /tools/cert-inspect,
/tools/ip-cidr -- stateless utility tools, no account data touched,
safe to call without side effects beyond rate limits.Parameters and schemas for all of the above: GET /docs/.
A real MCP server is live at this origin, mounted at /mcp -- not a
REST API with MCP bolted on afterward. Every route above is also
exposed as a generated MCP tool, built directly from the same OpenAPI
contract the HTTP routes are generated from, so the two surfaces cannot
drift from each other. Prefer the MCP transport when calling from an
MCP-capable client; tool names and schemas match the operation IDs in
the spec at /docs/.
/kv/...), queue (/queue/...), account/
role/access-key records, usage stats./tools/* utilities.Auth endpoints (/auth/request-link, /auth/verify, /auth/device/*)
are per-IP rate-limited. Expect 429 on abuse rather than a silent
hang; back off and retry rather than hammering on failure.