Getting Started
Connect to SRag via MCP or the REST API. Search, ingest, and explore the knowledge graph.
Authentication
All SRag surfaces are protected. There are three flows depending on how you connect:
REST API — Bearer token
Every /api/* request (except GET /api/openapi.json) requires an Authorization: Bearer <Supabase access token> header — the same token the dashboard gets after SSO sign-in. Requests without a valid token receive 401 with a WWW-Authenticate challenge. Trusted backend services can alternatively present a signed X-MCP-Assertion header.
MCP — OAuth 2.1 (automatic)
The /mcp endpoint (and the project-bound /mcp/:projectId variant) is an OAuth 2.1 protected resource. MCP clients like Cursor and Claude Desktop handle this automatically: on the first 401 they discover the built-in authorization server, open the SSO login in your browser, and attach the token to every request from then on. You never configure headers manually — just add the server URL and sign in when prompted.
Access control — projects, members, shares
Authorization is enforced in the database with Row Level Security. Every document lives in a project with an owner. You see exactly what you own, what you were invited to (as viewer or editor, either with full access — all documents plus the full knowledge graph — or selective access — only individually shared documents), and single documents shared with you. Document grants include the knowledge derived from those documents — their facts, relationships, and the entities they mention — while entity descriptions stay hidden (they synthesize the whole project; full membership unlocks them). Admins can also define groupsthat work as share targets with the same options. Searches on the unscoped MCP endpoint automatically span all of it — no extra setup. Manage members and shares from the dashboard's Projects page or the membership API endpoints below.
File uploads — one-time signed URLs
Uploads are two-step so that clients without auth headers (an agent's shell running curl) can still send files. First an authenticated caller mints a single-use URL — via the rag_prepare_upload MCP tool or POST /api/:projectId/upload-token (write access to the project required). Then the file is POSTed as multipart form data to the returned /uploads/:token URL with no auth header — the token in the path is the only credential. Tokens are bound to one project, single-use, and expire after 10 minutes by default.
MCP Integration
SRag implements the Model Context Protocol (MCP) with streamable HTTP transport — an open standard for connecting AI agents to external tools and data. Any MCP-compatible client (Cursor, Claude Desktop, etc.) can connect and use all 24 SRag tools through natural language.
One-click Cursor setup
Connect to the default unscoped endpoint — searches span every project you own or are a member of, and write tools ask which project to use. No configuration needed.
Add to Cursorhttps://api.srag.simeonov.app/mcpOptional: pin the connection to a single project by appending its UUID (/mcp/<project-uuid>). Create a new project here, or use the rag_create_project / rag_list_projects tools after connecting.
Manual setup
Add this to your .cursor/mcp.json or Claude Desktop config:
{
"mcpServers": {
"srag": {
"type": "streamableHttp",
"url": "https://api.srag.simeonov.app/mcp"
}
}
}Available tools (24)
whoami
Identity of the authenticated user — id, email, auth source, and Supabase profile
rag_list_projects
List the projects you can access (owned, member, group, admin) with your role and access mode in each
rag_create_project
Create a new project (knowledge-base workspace) owned by you
rag_search
Combined search with two toggleable pipelines: chunks (vector + BM25 + fusion + rerank) and cognitive (entities, facts, relationships). On unscoped connections it spans every project you can access.
rag_store
Store content — returns immediately, cognitive pipeline processes in background. On unscoped connections takes a project argument (or lists your writable projects)
rag_prepare_upload
Get a one-time signed URL + curl command to upload a local file (PDF, DOCX, …) without reading it into context. Same project resolution as rag_store
rag_read
Read full original document content by source ID
rag_delete
Delete a document and cascade-clean all cognitive data
rag_get_document
Get document metadata, chunk status, and cognitive status
rag_list_documents
List and browse documents with filtering and pagination
rag_list_sources
List source types and their document counts
rag_stats
Knowledge base statistics (documents, chunks, entities, facts)
rag_expand_chunk
Expand a chunk with neighboring context for more surrounding text
rag_reingest
Re-process a document with new chunking/dedup settings
rag_entities
Search entities by name or semantic similarity
rag_recall
Complete entity recall — entity, facts, relationships, and mentions in one call
rag_facts
Search atomic facts with confidence filtering and category selection
rag_expand_fact
Get the source chunks behind a fact for provenance verification
rag_timeline
Temporal evolution of facts — see how knowledge changed over time
rag_changes
What changed since a timestamp — new facts, supersessions, retractions
rag_document_entities
Get all entities extracted from a specific document
rag_retry_cognitive
Retry failed cognitive processing (entity/fact extraction) for a document
rag_activity
Recent activity feed — ingestion events, processing completions, errors
rag_document_logs
Processing event timeline for a specific document
REST API
Base URL
https://api.srag.simeonov.app/api/:projectIdReplace :projectId with your project UUID — you need access to the project (owner, member, or admin). Create a project first via POST /api/scopes with { "name": "my-project" }.
| Method | Endpoint | Description |
|---|---|---|
| Projects | ||
| POST | /scopes | Create a new project — you become the owner (returns UUID) |
| GET | /:projectId/members | List project members (users, pending invites, and group grants) |
| POST | /:projectId/members | Invite by email or group_id as viewer/editor with full or selective access (pending if no account yet) |
| PATCH | /:projectId/members | Change a member's role and/or access mode |
| DELETE | /:projectId/members | Revoke a membership, group grant, or pending invite |
| POST | /:projectId/claim | Claim an ownerless project (admin only) |
| POST | /:projectId/transfer-ownership | Transfer project ownership to another member |
| Document Sharing | ||
| GET | /:projectId/documents/:sourceId/members | List who a document is shared with (users and groups) |
| POST | /:projectId/documents/:sourceId/members | Share a document by email or group_id (text + knowledge derived from the document; non-members become selective project members) |
| DELETE | /:projectId/documents/:sourceId/members | Revoke a document share |
| Search | ||
| POST | /:projectId/search | Combined search (knowledge + chunks, independently toggleable via pipeline/cognitivePipeline) |
| Ingestion | ||
| POST | /:projectId/ingest | Queue document for ingestion |
| POST | /:projectId/ingest/batch | Batch ingest multiple documents |
| POST | /:projectId/upload-token | Mint a one-time signed upload URL |
| POST | /uploads/:token | Upload a file with a minted token (public — no auth header, multipart form data, served at server root not /api) |
| Documents | ||
| GET | /:projectId/documents | List documents with filtering |
| GET | /:projectId/documents/:sourceId | Get document metadata and status |
| GET | /:projectId/documents/:sourceId/content | Read full content + chunks |
| GET | /:projectId/documents/:sourceId/logs | Ingestion and cognitive event logs |
| GET | /:projectId/documents/:sourceId/entities | Entities extracted from document |
| POST | /:projectId/documents/:sourceId/reingest | Re-process with new settings |
| POST | /:projectId/documents/:sourceId/retry-cognitive | Retry cognitive processing |
| DELETE | /:projectId/documents/:sourceId | Delete document and cognitive data |
| Chunks | ||
| GET | /:projectId/chunks/:chunkId/expand | Expand chunk with neighboring context |
| Knowledge Graph | ||
| GET | /:projectId/entities | Search entities by name or similarity |
| GET | /:projectId/entities/:entityId/recall | Complete entity recall (facts, relationships, mentions) |
| GET | /:projectId/entities/:entityId/graph | N-hop entity relationship graph traversal |
| GET | /:projectId/entities/:entityId/timeline | Fact timeline for an entity |
| GET | /:projectId/facts | Search atomic facts |
| GET | /:projectId/facts/:factId/expand | Fact provenance (source chunks) |
| GET | /:projectId/changes | Recent fact changes since timestamp |
| Meta | ||
| GET | /:projectId/stats | Knowledge base statistics |
| GET | /:projectId/sources | Source types and counts |
| GET | /:projectId/activity | Activity feed |
OpenAPI Schema
https://api.srag.simeonov.app/api/openapi.jsonFull OpenAPI 3.1 specification for all endpoints. Use it to auto-generate client libraries or let an AI agent build integrations.
Search example
// First, create a project (one-time — you become the owner)
// POST https://api.srag.simeonov.app/api/scopes { "name": "my-project" }
// → { "id": "a3f2b1c4-...", "name": "my-project" }
const PROJECT_ID = "a3f2b1c4-..."; // UUID from project creation
const ACCESS_TOKEN = "eyJ..."; // Supabase access token (see Authentication)
// Combined search (both pipelines enabled by default)
const response = await fetch(`https://api.srag.simeonov.app/api/${PROJECT_ID}/search`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${ACCESS_TOKEN}`,
},
body: JSON.stringify({
query: "How does authentication work?",
limit: 10,
// pipeline: null, // uncomment to skip chunk retrieval (knowledge only)
// cognitivePipeline: null, // uncomment to skip cognitive search (chunks only)
includeSuperseded: true, // include outdated facts marked as superseded
}),
});
const { results, knowledge, debug } = await response.json();
// knowledge.entities — matched entities with descriptions
// knowledge.facts — relevant facts (isCurrent: false = superseded)
// knowledge.relationships — connections between entities
// results — ranked source chunks (empty when pipeline is null)Ingest example
const PROJECT_ID = "a3f2b1c4-..."; // UUID from project creation
const ACCESS_TOKEN = "eyJ..."; // Supabase access token (see Authentication)
const response = await fetch(`https://api.srag.simeonov.app/api/${PROJECT_ID}/ingest`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${ACCESS_TOKEN}`,
},
body: JSON.stringify({
content: "Your document content here...",
sourceType: "agent_memory",
title: "My Document",
}),
});
// Queued for background processing — worker picks it up automatically
const { queueId, sourceId, status } = await response.json();File upload example (one-time signed URL)
const PROJECT_ID = "a3f2b1c4-...";
const ACCESS_TOKEN = "eyJ...";
// Step 1 — mint a one-time signed upload URL (authenticated)
const mint = await fetch(`https://api.srag.simeonov.app/api/${PROJECT_ID}/upload-token`, {
method: "POST",
headers: { Authorization: `Bearer ${ACCESS_TOKEN}` },
});
const { upload_url, curl_example, expires_in_seconds } = await mint.json();
// Step 2 — POST the file to the URL. NO auth header — the one-time
// token in the URL path is the only credential. Single-use, expires
// after ${expires_in_seconds}s (default 600).
const formData = new FormData();
formData.append("file", myFile); // File or Blob
const res = await fetch(upload_url, { method: "POST", body: formData });
const { queueId, sourceId, status } = await res.json();
// Or from a shell (this is what MCP agents do via rag_prepare_upload):
// curl -s -X POST -F 'file=@/path/to/report.pdf' '<upload_url>'Cognitive Features
When content is ingested, a background cognitive pipeline extracts structured knowledge — entities, relationships, and atomic facts. Contradictions are detected automatically, outdated facts are superseded, and entity descriptions are refreshed. Search runs two independent pipelines: chunk retrieval (vector + BM25 + fusion + rerank) for evidence, and cognitive search (entities, facts, relationships) for understanding. Both can be enabled independently or combined.
Entities and relationships extracted from every document with 5-stage resolution and cross-document merging.
Contradictions, refinements, and retractions detected automatically. Old facts superseded by new ones. Temporal valid_from dates ensure correct supersession regardless of ingestion order.
Each fact carries an valid_from timestamp. Full audit trail of changes. See what is true now and what used to be true, with exact dates.
Entity Recall
Get everything known about an entity in one call — its description, all current facts, relationships to other entities, and the source documents where it appears.
const PROJECT_ID = "a3f2b1c4-...";
const ACCESS_TOKEN = "eyJ..."; // Supabase access token (see Authentication)
const AUTH = { Authorization: `Bearer ${ACCESS_TOKEN}` };
// Get everything known about an entity in one call
const response = await fetch(
`https://api.srag.simeonov.app/api/${PROJECT_ID}/entities/ENTITY_ID/recall`,
{ headers: AUTH },
);
const recall = await response.json();
// recall.entity — name, type, description, aliases
// recall.facts — all current facts about the entity
// recall.relationships — connections to other entities
// recall.mentions — source documents where entity appearsFact Search
Search atomic facts with category and confidence filters. Categories: fact, decision, plan, observation, opinion.
const PROJECT_ID = "a3f2b1c4-...";
const ACCESS_TOKEN = "eyJ..."; // Supabase access token (see Authentication)
const AUTH = { Authorization: `Bearer ${ACCESS_TOKEN}` };
// Search facts with category and confidence filters
const response = await fetch(
`https://api.srag.simeonov.app/api/${PROJECT_ID}/facts?query=database+migration&category=decision`,
{ headers: AUTH },
);
const { facts } = await response.json();
// Each fact has: content, confidence, category, is_current, valid_from, subject_entity
// valid_from: when the fact was true (ISO 8601 or null)
// Categories: fact, decision, plan, observation, opinionFact Timeline
Track how knowledge about an entity evolved — what changed, when, and why. Superseded facts are preserved with full provenance.
const PROJECT_ID = "a3f2b1c4-...";
const ACCESS_TOKEN = "eyJ..."; // Supabase access token (see Authentication)
const AUTH = { Authorization: `Bearer ${ACCESS_TOKEN}` };
// See how knowledge about an entity evolved over time
const response = await fetch(
`https://api.srag.simeonov.app/api/${PROJECT_ID}/entities/ENTITY_ID/timeline`,
{ headers: AUTH },
);
const { current, superseded, events } = await response.json();
// current — facts that are currently true
// superseded — facts that were replaced by newer information
// events — change trail (created, superseded, retracted)