Developers
Point any AI at any of your knowledge bases.
A scoped knowledge base in Graniite is one folder + one bearer string. Pick whichever path fits. The no-code path is folder, scoped token, paste. The code path is MCP and REST with an OpenAPI spec that drops into the Vercel AI SDK, LangChain, LlamaIndex, n8n, and custom Python or TypeScript.
Other memory layers in this category ship as an SDK and ask you to build the front end. Graniite ships the front end too. Every scoped knowledge base you issue is backed by the same product real users open every day. Your agent and your users see the same library.
No code
Paste a token into your AI client.
Group items into a folder. Issue a scoped token bound to that folder. Paste it into Claude Desktop, Cursor, or any MCP-aware client. 30 seconds, no SDK, no library install.
Skip to the no-code pathCode
Wire it into your agent stack.
MCP and REST. Per-token capabilities and folder scope. Hybrid vector + keyword search. Per-token activity log. OpenAPI 3.1 spec drops into LangChain, the Vercel AI SDK, and most agent frameworks without an adapter.
Skip to the code pathNo-code path
Folder → scoped token → agent.
A scoped token is a bearer string bound to one folder. Connect it to an AI client and that client reads from the folder only. Graniite never owns the chat surface, just feeds your AI the right slice of your library.
- 01
Group items into a folder.
One folder per project, client, codebase, or research area. Open folders →
- 02
On the folder page, click New token.
Pick a name (e.g.
claude-desktop), read-only by default, write opt-in. The page reveals the token once and shows the snippets below inline so you can paste straight into the client config. Or, on supporting clients (Claude Desktop, Cursor), use the OAuth one-click connect instead. No JSON editing. - 03
Paste the snippet into your AI client.
Restart the client. Graniite’s tools appear in the tool picker; the AI now reasons over that folder only.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) and add a new MCP server. Bridges HTTP through mcp-remote.
{
"mcpServers": {
"graniite": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://graniite.co/api/mcp",
"--header",
"Authorization: Bearer <paste your scoped token here>"
]
}
}
}Cursor
Cursor speaks MCP natively over HTTP. Settings → MCP → Add server.
{
"name": "graniite",
"url": "https://graniite.co/api/mcp",
"headers": {
"Authorization": "Bearer <paste your scoped token here>"
}
}Other MCP-aware clients (n8n’s MCP node, custom MCP clients, ChatGPT Desktop once it ships native MCP) all consume the same https://graniite.co/api/mcp endpoint plus a bearer header.
Code path
Two surfaces. One bearer token.
MCP is the agent’s memory surface. Read and add via JSON-RPC tool calls from any MCP-aware AI client. REST API is the management surface, with full CRUD over folders and items for n8n, Zapier, scripts, and custom integrations. The same scoped tokens authenticate both.
MCP, the agent memory surface
Four tools. Read + add only. Update / delete / organize live on the REST surface below.
search_knowledge_baseread | Semantic + keyword + hybrid search over the user’s library. Returns top-K chunks with similarity scores and source titles. |
get_itemread | Full content + AI transforms for one item by id. |
list_recentread | Recent items across the user’s entire library. |
add_to_knowledgewrite | Add a URL or text snippet. Defaults to embed-only (no AI transform). Agents read chunks, not transforms. |
REST API, the management surface
Beta
Full CRUD over folders, items, and memberships. Built for automations + integrations (n8n, Zapier, cron scripts). All endpoints described in the /api/v1/openapi.json spec. Drops into any OpenAPI-aware tool wrapper.
Endpoint shapes may change as we learn from real usage. The MCP server is the more stable surface today — build production integrations there where you can; reach for REST when MCP can’t cover the workflow.
GET /api/v1/foldersread | List folders in scope. Includes per-folder item_count. |
POST /api/v1/folderswrite · whole-library | Create a folder. Whole-library tokens only. |
DELETE /api/v1/folders/{id}write · whole-library | Delete a folder. Default preserves items; pass ?cascade_items=true to also delete items whose only folder is this one. |
GET /api/v1/itemsread | Paginated list. Filters: folder_id, archived, in_kb, page, per_page. |
GET /api/v1/items/{id}read | Full item: metadata, transcript, outputs, and folder memberships. |
DELETE /api/v1/items/{id}write | Delete an item. Cascades to outputs, chunks, folder memberships, and storage objects (via the cron drainer). |
POST /api/v1/items/{id}/folderswrite | Add the item to one or more folders. Idempotent. Multi-folder scope or whole-library token required (a single-folder token has no destination to add to). |
DELETE /api/v1/items/{id}/folders/{folderId}write | Remove one membership. Allowed even if it’s the item’s only folder (item becomes unfiled). |
POST /api/v1/ingestwrite | URL or text-snippet ingest. Same shape as MCP add_to_knowledge for REST clients that don’t speak JSON-RPC. |
POST /api/v1/uploads/*write | Three-step signed-URL flow for binary uploads (audio, video, PDF, images). Agents that produce files can drop them straight into the user’s library. |
Scope a token down
Every token carries three scope dials. Use them to give an AI client exactly the slice of the library it needs and nothing else, the way you’d give a Unix process the smallest set of file permissions that gets the job done.
capabilities | read, write, or both. A read-only token can’t add or modify anything. |
folder_id | Bind a token to one folder. Reads only see items in that folder; writes get auto-added to it. The no-code flow on /folders/[id] pre-fills this for you. |
kb_only | On by default. Forces every write through the agent to be added to the knowledge base. Toggle off only if an agent should be able to add inert items the user reviews later. |
Curl
# Search the user's knowledge base
curl -X POST https://graniite.co/api/mcp \
-H "Authorization: Bearer lev_..." \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_knowledge_base",
"arguments": { "query": "what did that podcast say about agents" }
}
}'
# Add a URL (requires write capability)
curl -X POST https://graniite.co/api/v1/ingest \
-H "Authorization: Bearer lev_..." \
-H "Content-Type: application/json" \
-d '{
"kind": "url",
"url": "https://www.youtube.com/watch?v=..."
}'Vercel AI SDK
Wire Graniite directly as an AI SDK tool. The MCP server runs over HTTP, so the standard experimental_createMCPClient works with no adapter package needed.
import { experimental_createMCPClient as createMCPClient, generateText } from "ai";
import { gateway } from "@ai-sdk/gateway";
const mcp = await createMCPClient({
transport: {
type: "sse",
url: "https://graniite.co/api/mcp",
headers: { Authorization: `Bearer ${process.env.GRANIITE_TOKEN!}` },
},
});
const { text } = await generateText({
model: gateway("anthropic/claude-sonnet-4-6"),
tools: await mcp.tools(),
prompt: "Summarize what's in my Graniite library about LLM observability.",
});
await mcp.close();Hybrid search
search_knowledge_base accepts a mode parameter. Default is hybrid (vector similarity blended with Postgres full-text rank), which catches both fuzzy semantic matches and exact strings (proper nouns, version numbers, library names) that pure vector search smooths over. Override to semantic or keyword when you have a reason to.
{
"name": "search_knowledge_base",
"arguments": {
"query": "Postgres logical replication",
"mode": "hybrid",
"limit": 8
}
}Upload binary content
For audio, video, PDF, or images, request a signed URL, PUT the bytes to it, then call finalize. The pattern bypasses the serverless body-size cap and lets agents drop files up to 50 MB straight into the user’s library. Audio and video go to /finalize; PDFs and images go to /finalize-document. The signed-URL response tells you which.
# 1. Ask for a signed URL
curl -X POST https://graniite.co/api/v1/uploads/signed-url \
-H "Authorization: Bearer lev_..." \
-H "Content-Type: application/json" \
-d '{"mime":"audio/mpeg","size":4823104,"filename":"meeting.mp3"}'
# → {"path":"...","signed_url":"...","finalize_endpoint":"finalize"}
# 2. PUT the bytes directly to signed_url
curl -X PUT "<signed_url from step 1>" \
-H "Content-Type: audio/mpeg" \
--data-binary @meeting.mp3
# 3. Finalize → ingestion runs server-side
curl -X POST https://graniite.co/api/v1/uploads/finalize \
-H "Authorization: Bearer lev_..." \
-H "Content-Type: application/json" \
-d '{"path":"<path from step 1>","mime":"audio/mpeg","size":4823104,"filename":"meeting.mp3"}'OpenAPI spec
The REST surface (/api/v1/ingest today, more endpoints later) ships an OpenAPI 3.1 spec. LangChain’s OpenAPIToolkit, LlamaIndex’s OpenAPIToolSpec, and most agent frameworks can consume it directly without us writing per-framework adapters.
curl https://graniite.co/api/v1/openapi.jsonWhat it costs you
Read calls (search_knowledge_base, get_item, list_recent) are free on every tier. Write calls (add_to_knowledge, /api/v1/ingest) for paid-transcription content (audio, video, YouTube) count against your monthly transcription quota, the same quota the UI uses. Webpage scrapes and pasted text are free. Quota state is visible at /settings; quota errors return HTTP 402 with the tier and cap so your client can render an upgrade prompt.
MCP + REST API access is a paid-tier feature. Free users get the in-app experience but can’t mint tokens. Token-create calls return HTTP 402 with {tier, cap, used} in the body. See /pricing for tier shape; above the gate, every paid tier issues unlimited tokens.
Per-token visibility
Every call logs to /settings/integrations so you can see what your agents are doing: query strings, latency, result counts, which token. 90-day retention, clearable from the UI.