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 Cursor
https://api.srag.simeonov.app/mcp

Optional: 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:

.cursor/mcp.json
{
  "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/:projectId

Replace :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" }.

MethodEndpointDescription
Projects
POST/scopesCreate a new project — you become the owner (returns UUID)
GET/:projectId/membersList project members (users, pending invites, and group grants)
POST/:projectId/membersInvite by email or group_id as viewer/editor with full or selective access (pending if no account yet)
PATCH/:projectId/membersChange a member's role and/or access mode
DELETE/:projectId/membersRevoke a membership, group grant, or pending invite
POST/:projectId/claimClaim an ownerless project (admin only)
POST/:projectId/transfer-ownershipTransfer project ownership to another member
Document Sharing
GET/:projectId/documents/:sourceId/membersList who a document is shared with (users and groups)
POST/:projectId/documents/:sourceId/membersShare a document by email or group_id (text + knowledge derived from the document; non-members become selective project members)
DELETE/:projectId/documents/:sourceId/membersRevoke a document share
Search
POST/:projectId/searchCombined search (knowledge + chunks, independently toggleable via pipeline/cognitivePipeline)
Ingestion
POST/:projectId/ingestQueue document for ingestion
POST/:projectId/ingest/batchBatch ingest multiple documents
POST/:projectId/upload-tokenMint a one-time signed upload URL
POST/uploads/:tokenUpload a file with a minted token (public — no auth header, multipart form data, served at server root not /api)
Documents
GET/:projectId/documentsList documents with filtering
GET/:projectId/documents/:sourceIdGet document metadata and status
GET/:projectId/documents/:sourceId/contentRead full content + chunks
GET/:projectId/documents/:sourceId/logsIngestion and cognitive event logs
GET/:projectId/documents/:sourceId/entitiesEntities extracted from document
POST/:projectId/documents/:sourceId/reingestRe-process with new settings
POST/:projectId/documents/:sourceId/retry-cognitiveRetry cognitive processing
DELETE/:projectId/documents/:sourceIdDelete document and cognitive data
Chunks
GET/:projectId/chunks/:chunkId/expandExpand chunk with neighboring context
Knowledge Graph
GET/:projectId/entitiesSearch entities by name or similarity
GET/:projectId/entities/:entityId/recallComplete entity recall (facts, relationships, mentions)
GET/:projectId/entities/:entityId/graphN-hop entity relationship graph traversal
GET/:projectId/entities/:entityId/timelineFact timeline for an entity
GET/:projectId/factsSearch atomic facts
GET/:projectId/facts/:factId/expandFact provenance (source chunks)
GET/:projectId/changesRecent fact changes since timestamp
Meta
GET/:projectId/statsKnowledge base statistics
GET/:projectId/sourcesSource types and counts
GET/:projectId/activityActivity feed

OpenAPI Schema

https://api.srag.simeonov.app/api/openapi.json

Full OpenAPI 3.1 specification for all endpoints. Use it to auto-generate client libraries or let an AI agent build integrations.

Search example

search.ts
// 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

ingest.ts
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)

upload.ts
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.

Knowledge Graph

Entities and relationships extracted from every document with 5-stage resolution and cross-document merging.

Self-Healing Facts

Contradictions, refinements, and retractions detected automatically. Old facts superseded by new ones. Temporal valid_from dates ensure correct supersession regardless of ingestion order.

Temporal Memory

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.

entity-recall.ts
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 appears

Fact Search

Search atomic facts with category and confidence filters. Categories: fact, decision, plan, observation, opinion.

fact-search.ts
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, opinion

Fact Timeline

Track how knowledge about an entity evolved — what changed, when, and why. Superseded facts are preserved with full provenance.

fact-timeline.ts
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)