Relinkia

MCP Server

Connect your Relinkia knowledge graph to Claude Desktop or any MCP-compatible AI environment — and let the AI answer from your own notes.

Overview

The Relinkia MCP server exposes your personal knowledge graph as structured memory for AI tools. Claude can query your notes, concepts, and connections directly — without you having to copy-paste content into the conversation.

In standard mode, two tools are available to Claude once the server is connected:

relinkia_search

Find notes on a specific topic. Use this for standalone queries unrelated to the current conversation.

relinkia_get_context

Link the current conversation to your existing notes. Use this when the query depends on what has just been discussed.

Privacy by design. Claude never receives your raw note content. It receives short summaries (gists) and structured metadata. The full text of your notes never leaves Relinkia.

Requirements

Plan

Thinker (€12/month) or Thinker + BYOK (€5/month). The MCP server is not available on the free plan.

Mature graph

The MCP server becomes genuinely useful once you have at least 50 validated concepts. With fewer concepts, Claude has little to work with.

Compatible client

Claude Desktop, Claude.ai, Claude Code, or any client that supports the Model Context Protocol.

Setup

Claude Desktop

First, generate an API token: Relinkia → Settings → Integrations → Generate MCP token. Then edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "relinkia": {
      "command": "npx",
      "args": ["-y", "@relinkia/mcp-server"],
      "env": {
        "RELINKIA_API_TOKEN": "<your-api-token>"
      }
    }
  }
}

Claude.ai (Remote MCP)

Claude.ai uses OAuth to connect to Remote MCP servers — no API token needed. Go to Settings → Integrations → Add MCP server and follow these steps:

  1. Enter https://mcp.relinkia.app/sse as the server URL.
  2. Click Add — claude.ai automatically initiates the OAuth authorization flow.
  3. A Relinkia login and consent page opens in your browser.
  4. Log in to Relinkia (if not already logged in) and click Approve.
  5. You are redirected back to claude.ai — Relinkia tools are now available.

LangChain, n8n, or custom agents (REST)

The same tools are exposed over a standard REST API for non-MCP clients:

Base URL : https://api.relinkia.app/api/v1/agent/
Auth     : Authorization: Bearer <your-api-token>
Schema   : /api/v1/agent/openapi.json

relinkia_get_context

Context-aware search enriched by the current conversation. Same pipeline as relinkia_search, but the embedding and reranking are augmented by a conversation summary you provide.

When to use

The query is tied to what has just been discussed. Examples: “Do my notes connect with what we just said?” — “Have I already thought about something like this?”

When NOT to use

If the user simply wants to find notes on a topic without reference to the current conversation — use relinkia_search. It is faster and sufficient for standalone queries.

Parameters

ParameterTypeRequiredDescription
qstringYesNatural language search query
conversation_contextstring (≤ 1200 chars)NoA short summary of the current conversation — written by the AI, not copy-pasted verbatim. Focuses on intent and themes, not word-for-word exchanges. Never stored after the call.
limitinteger (1–20)No — default 10Maximum number of results

Example call

relinkia_get_context({
  q: "productive failure and learning",
  conversation_context: "Discussion on rethinking school assessment
    as a calibrated stimulus rather than a sanction. Parallel with
    Taleb's antifragility applied to education. Question about
    graduated exposure to error.",
  limit: 5
})

Understanding responses

Sources

Both tools return a sources array. Each source includes a title, a URL back to your note, a role, and the date it was last updated. Claude cites these as links — never as verbatim quotes.

"sources": [
  {
    "title": "Calibrated friction as stimulus",
    "url": "https://relinkia.app/note/{id}",
    "role": "argument_central",
    "last_updated": "2026-02-11"
  }
]

Possible roles: argument_central, external_source, emerging_connection, counter_argument.

Temporal advisory

If a retrieved note has been superseded by a more recent one, the response includes a temporal_advisory. Claude will surface this before drawing on the older note — to avoid presenting an abandoned position as your current thinking.

"temporal_advisory": "The most recent note on this point
  (11 February) nuances what you wrote in November.
  Mention this before relying on the older note."

Disambiguation

When a query matches several distinct clusters without a clear dominant match, relinkia_get_context returns a disambiguation_needed status instead of guessing. Claude will then ask you which thread to follow before answering.

{
  "status": "disambiguation_needed",
  "interpretations": [
    {
      "cluster": "Antifragility in finance",
      "note_count": 4,
      "hint": "Taleb notes, hedging, optionality"
    },
    {
      "cluster": "Antifragility in education",
      "note_count": 7,
      "hint": "More recent — graduated exposure to error"
    }
  ],
  "message_to_display": "You have two distinct threads on
    antifragility. Which one should I connect to our discussion?"
}

Quotas

Agent calls that trigger AI work draw from the same daily gesture quota as in-app gestures — there is no separate agent quota. Plain note search does not count as a gesture.

PlanGestures / day (shared)Price
Free15€0
Thinker50€12/month
Thinker + BYOKNo daily limit*€5/month

* With BYOK, there is no daily limit: only an anti-abuse safety cap of 300 AI actions per day applies. MCP tools do not use your personal Anthropic key: they make no call to Anthropic. Their search and retrieval run on the Relinkia RAG infrastructure (embeddings, vector search, reranking), covered by the platform fee, and the background processing they trigger (concept extraction, discoveries) runs on Relinkia's accounts.

Owner Mode

Owner mode unlocks ten tools for account owners who want to use a personal AI agent to read and write their knowledge base directly. Unlike the standard mode — which returns gists and metadata — owner mode gives the agent access to the full text of notes and the ability to create or update them.

Typical use cases: maintaining a structured knowledge base with an AI assistant, syncing notes from external sources, or running automated pipelines that enrich your graph overnight.

Privacy note

Owner mode is designed for agents acting on your behalf. The full text of your notes is transmitted to the AI. Only use owner mode with agents you control and trust.

Authentication

Owner mode requires a dedicated owner token — separate from the standard API token. Generate it in: Settings → Integrations → Generate owner token.

Pass it as a Bearer token in the Authorization header:

Authorization: Bearer <your-owner-token>

For Claude Desktop or MCP server config, use the RELINKIA_OWNER_TOKEN env variable:

{
  "mcpServers": {
    "relinkia-owner": {
      "command": "npx",
      "args": ["-y", "@relinkia/mcp-server"],
      "env": {
        "RELINKIA_OWNER_TOKEN": "<your-owner-token>"
      }
    }
  }
}

The _context block

Every owner tool response carries a _context block. It tells the agent whether the scope exists and which canonical documents it holds, ranked for the current request.

Canonical document. A canonical document is a reference document of the scope: a note with a docKey whose type is synthesis, index or decision, or that is explicitly marked canonical: true. A docKey alone makes a note addressable (get_by_doc_key, update_canonical, supersession), not canonical: an addressable question, journal or contact note is not listed in canonicalDocs. A synthesis or index marked canonical: false is not listed either; a decision is always canonical. Set the status with the canonical parameter of create_note and update_note_metadata.

"_context": {
  "scope": { "name": "project-x", "exists": true, "noteCount": 12, "decisionCount": 3 },
  "canonicalDocs": [
    { "docKey": "project-x-decisions", "title": "Decisions", "type": "index",
      "currentVersion": 2, "updatedAt": "2026-10-17T16:05:00.000Z", "isDecision": false,
      "relevanceScore": 0.41, "embeddingStatus": "ready", "pinned": true },
    { "docKey": "project-x-architecture", "title": "Architecture", "type": "synthesis",
      "currentVersion": 3, "updatedAt": "2026-10-18T09:12:00.000Z", "isDecision": false,
      "relevanceScore": 0.82, "embeddingStatus": "ready" },
    { "docKey": "project-x-sources", "title": "Sources", "type": "index", "currentVersion": 1,
      "updatedAt": "2026-10-18T09:40:00.000Z", "isDecision": false,
      "relevanceScore": null, "embeddingStatus": "pending" }
  ],
  "canonicalDocsTruncated": false,
  "canonicalDocsRanking": "relevance",
  "serverTime": "2026-10-18T09:41:02.000Z",
  "protocolVersion": "canonical-docs/0.7"
}
FieldMeaning
typeStored type of the note, on every item: synthesis, index, decision, or another type marked canonical. isDecision is kept and is true when the type is decision.
pinnedtrue on the pinned document only: the document the tool acts on directly (see Order of documents below). It is first because of the pin, not because of its score — its relevanceScore stays its own, so compare scores to judge relevance. The field is absent on every other item, and on every item of a call that acts on no particular document (search_notes, list_scopes, get_note_full).
canonicalDocsRankingrelevance (semantic ranking against the request) or recency (most recently updated first — used when no document of the scope has a vector yet, or when the request cannot be embedded).
relevanceScoreCosine similarity clamped to [0,1] between the request and the best-matching passage of the document, when the ranking is relevance. A long document is split into passages and scored on the closest one, so a long or old document whose answer lies far from its beginning still comes first. Having more passages, a long document also has more chances to match: length favors it. null when no score was computed — the document has no vector, or the ranking is recency. Null means unknown, never irrelevant.
embeddingStatuspending: indexing not finished (typical right after a write, or when the daily embedding cap is reached). ready: indexed. failed: the last indexing attempt failed; a retry may bring it back to pending, then ready. ready with a null score in a relevance ranking means the document is indexed but its vector is missing and being repaired: judge it by its title.
canonicalDocsTruncatedtrue when at least one canonical document of the scope is not in the list. The list holds at most 20 documents. Up to 200 canonical documents are ranked on each call; beyond that, only the most recently updated ones are ranked. A document left out stays reachable with search_notes or get_by_doc_key.
protocolVersionVersion of this block: canonical-docs/0.7.

Order of documents. In a relevance ranking, documents with a score come first, highest score first; documents without a score follow, most recently updated first — they are never sorted as a score of 0. In a recency ranking, every document is ordered by update date. In both cases, the document the tool addresses directly (the docKey of create_note, get_by_doc_key, update_canonical or update_note_metadata) stays first, with or without a score, and carries pinned: true — a document you have just created is therefore always in the response, even in a scope with more than 20 canonical documents.

Two rankings. search_notes and canonicalDocs answer two different questions. search_notes is a keyword search: it finds the notes of the scope, of any type, that contain the words of the query, ranked by full-text relevance. canonicalDocs lists only the canonical documents, ranked by meaning (semantic similarity) to the request. The two orders differ by design: a note can be first in one and low or absent in the other, and neither order is wrong. Use search_notes for words, names and exact terms, and to go through every match; use canonicalDocs to find the reference document closest in meaning to your task.

The block may be cached for up to 60 seconds: a document can still show pending for that long after its indexing has finished. Every write through the owner tools refreshes it immediately.

get_note_full

Retrieves the complete text content of a note by ID or document key. Returns the full body as a concatenation of all sections — unlike the standard search tools which return only gists.

Parameters

ParameterTypeRequiredDescription
noteIdstringOne of noteId or docKeyMongoDB ID of the note
docKeystring (slug)One of noteId or docKeyDocument key (slug) assigned at creation

Response

{
  "noteId": "...",
  "title": "Architecture decisions",
  "body": "We chose event sourcing because...",
  "scope": "project-x",
  "docKey": "project-x-architecture",
  "type": "note",
  "currentVersion": 3
}

search_notes

Keyword (full-text) search across owner notes within a scope — not the semantic ranking of canonicalDocs (see Two rankings above). Returns at most limit results per page (default 20, maximum 50), each with its noteId, title, docKey, score and a gist: the beginning of the note, at most 500 characters, with gistTruncated: true when the note is longer. Use get_note_full to fetch the full body of a specific result.

Pages. count is the number of results in the page. hasMore: true means more results exist: pass nextCursor as cursor, with the same q and scope, to get the next page, without duplicates or gaps as long as the scope does not change. nextCursor is null on the last page. A list that ends with hasMore: true is not the whole answer.

Score and order. The score is relative to the query: 1 for the best match of the query, the others as a fraction of it, between 0 and 1, on a scale fixed by the first page and kept on the following pages. It is not comparable between two queries. The score of search_notes and the relevanceScore of canonicalDocs are two different scales and must not be compared to each other. Results with the same score are ordered by noteId ascending, so the same call always returns the same order.

Parameters

ParameterTypeRequiredDescription
qstringYesFull-text search query
scopestring (slug)YesScope to search in. An unknown scope returns an empty list, not an error
limitintegerNoMaximum number of results in the page, at least 1. Default 20, maximum 50: a larger value is reduced to 50. Any other value returns VALIDATION
cursorstringNoOpaque token: the nextCursor of the previous response, unchanged, with the same q and scope. A cursor from another query returns VALIDATION; so does null, the nextCursor of a last page: it means there are no more results
{
  "items": [
    { "noteId": "683e4a2f1c9b...", "title": "Research report", "docKey": "ia-report",
      "score": 1, "gist": "The first 500 characters of the note…", "gistTruncated": true },
    { "noteId": "683e4b071d2a...", "title": "Reading notes", "docKey": null,
      "score": 0.62, "gist": "Hippocampus and memory consolidation…", "gistTruncated": false }
  ],
  "count": 2,
  "limit": 2,
  "hasMore": true,
  "nextCursor": "eyJ2IjoxLCJvIjoyLCJoIjoi...",
  "_context": { ... }
}

get_by_doc_key

Retrieves a note by its document key (slug). Useful for deterministic access to well-known notes such as journals, configuration notes, or index pages.

Parameters

ParameterTypeRequiredDescription
docKeystring (slug)YesUnique document key assigned at note creation. Must be a slug (lowercase, hyphens, max 80 characters).

Returns the same format as get_note_full.

create_note

Creates a new note in the owner’s knowledge base. Returns the generated note ID and the type actually stored. Optionally assigns a permanent document key for future deterministic access.

Parameters

ParameterTypeRequiredDescription
typestring (enum)YesDeclared by the caller and stored as is (no inference). Choose it by who wrote the content and its role: fleeting (a quick capture or unprocessed thought of your own), literature(your notes on, or extracts from, one external source you read — not a list of sources, not your own report), permanent (one idea, written in your own words), index (a list or map that points to other notes or sources: table of contents, reading list, list of sources or references per axis), project (notes tied to a specific project, deliverable or piece of work), synthesis (your own consolidated report or state of the art, drawn from several notes or sources), question (an open question to explore or answer later). Aliases: note (stored as permanent) and source (stored as literature). Decisions are created with create_decision: decision is rejected.
scopestring (slug, max 80)YesDomain or project area for this note
titlestring (max 500)YesNote title
bodystringYesNote body in plain text or Markdown
docKeystring (slug, max 80)NoPermanent document key. Must be unique across your notes. Enables deterministic access via get_by_doc_key.
canonicalbooleanNoCanonical status. Omit it to follow the type: with a docKey, a synthesis or index is canonical, other types are only addressable. true lists a note of another type as canonical and requires a docKey; false keeps a synthesis or index out of canonicalDocs.

Response

HTTP 201
{ "noteId": "683e4a2f1c9b...", "storedType": "synthesis" }

storedType is the type actually stored, after alias resolution: note → permanent, source → literature.

Over MCP, create_note returns the same fields plus the context envelope:

{
  "noteId": "683e4a2f1c9b...",
  "storedType": "synthesis",
  "_context": { "protocolVersion": "canonical-docs/0.7", "scope": { ... }, "canonicalDocs": [ ... ] }
}

_context.protocolVersion is canonical-docs/0.7: the version of the context envelope carried by every tool response, distinct from the version of the capabilities descriptor (canonical-docs/0.2).

Errors

CodeErrorMeaning
409DUPLICATE_KEYA note with this docKey already exists. Choose a different key or omit it.
422VALIDATIONtype is decision: use create_decision; or canonical: true without a docKey. The body names the field and gives a message. Nothing is written.
400Bad RequestA parameter does not match its format (for example a scope or docKey outside the slug grammar). Over MCP, the same cases return a VALIDATION error naming the field.

update_canonical

Replaces the body of an existing note addressable by docKey, canonical or not (the response field canonical gives its effective canonical status). Uses optimistic concurrency: the server rejects the update if the note has been modified since you last read it. This prevents overwriting changes made by another agent or by the user in the app.

How optimistic concurrency works

Every note has a currentVersion counter that increments on every successful update. When you call update_canonical, you pass the version you read as baseVersion. If the server’s version still matches, the update proceeds and the version increments. If it does not match (someone else updated it), the server returns a 409 conflict.

Recommended workflow: (1) get_note_full → record currentVersion → (2) compute new body → (3) update_canonical with baseVersion = currentVersion → (4) on 409, re-read and retry.

Parameters

ParameterTypeRequiredDescription
noteIdstringYesID of the note to update
baseVersioninteger (≥ 0)YesThe currentVersionyou read before editing. Must match the server’s current version.
newBodystringYesNew canonical content (plain text or Markdown)
lastWriterstringNoIdentifies the writing surface (e.g. "claude-code", "claude-ai"). Appears in CONFLICT_STALE_VERSION messages.
supersedesstring (slug)NodocKey of the document this note supersedes. Triggers the supersession chain — the old document gains a supersededBy field pointing to this note.

Response

HTTP 200
{ "noteId": "683e4a2f1c9b...", "currentVersion": 4, "scope": "project-x",
  "docKey": "project-x-architecture", "canonical": true }

Errors

CodeErrorMeaning
409CONFLICT_STALE_VERSIONThe note was modified after you read it. currentVersionin the response body gives the server’s current version — re-read and retry.
404NOTE_NOT_FOUNDNo note with this ID belonging to your account.
422NOT_CANONICALThe note has no docKey: only a note with a docKey can be updated here, whether or not it is canonical.

update_note_metadata

Changes the metadata of an existing note without touching its body. The metadata fields are type, to fix a note imported with the wrong type, and canonical, to set whether the note is a canonical document; send one or both in one call. The note keeps its docKey, title, body, scope, links and tags; it gets a new version and a new history entry. Any note of yours can be changed, with or without a docKey, except decisions (a decision is always canonical). MCP only.

It uses the same optimistic concurrency as update_canonical: read the note with get_note_full (currentVersion, type) immediately before writing, and pass that version as baseVersion. Any other field than noteId, baseVersion, type, canonical and lastWriter is refused with VALIDATION.

The new type is part of the indexed text and of every vector point, and it selects how a long note is split: a successful change re-indexes the whole note. Until the indexing is done, the note shows embeddingStatus: pending in _context, where it is pinned first when it is canonical. Requesting the values the note already has writes nothing and returns changed: false with the current version. If the note shows embeddingStatus: failed after a change, do not call the tool again: the type is already written and the indexing is resumed automatically.

Parameters

ParameterTypeRequiredDescription
noteIdstringYesID of the note to change
baseVersioninteger (≥ 0)YesThe currentVersionyou read just before. Must match the server’s current version.
typestringOne of type, canonicalNew type, same values as create_note: fleeting, literature, permanent, index, project, synthesis, question, and the aliases note and source. Never decision.
canonicalboolean or nullOne of type, canonicaltrue: canonical whatever the type (requires a docKey). false: not canonical, still addressable. null: follow the default of the type. Never on a decision. Changing it alone does not re-index the note.
lastWriterstringNoIdentifies the writing surface. Appears in CONFLICT_STALE_VERSION messages.

Response

{
  "noteId": "683e4a2f1c9b...",
  "currentVersion": 4,
  "storedType": "synthesis",
  "changed": true,
  "canonical": true,
  "_context": { "protocolVersion": "canonical-docs/0.7", "scope": { ... }, "canonicalDocs": [ ... ] }
}

Errors

ErrorMeaning
CONFLICT_STALE_VERSIONThe note was modified after you read it. The message gives the current version, the date and the last writer. Nothing is written: re-read the note and confirm with the user — never retry with an incremented version.
NOTE_NOT_FOUNDNo note with this ID belonging to your account. The same answer is given for a note that belongs to someone else.
FORBIDDEN_NOT_OWNERThe caller is not the owner principal.
VALIDATIONtype is decision or not in the list, the note is a decision (use update_decision), or a field other than the four parameters was sent. The message names the field. Nothing is written.

list_scopes

Lists all scopes in the knowledge base with their volumetry — number of notes and decisions per scope.

When to use

Call list_scopes before accessing a scope whose name isn’t provided by the user — for example, to discover which scopes exist before searching or writing within one.

Parameters

This tool takes no parameters.

Response

[
  { "scope": "project-x", "noteCount": 12, "decisionCount": 3 },
  { "scope": "architecture", "noteCount": 8, "decisionCount": 1 }
]

Decisions

Decisions are a distinct knowledge type from canonical notes. Where a canonical note can be superseded by a newer document, a decision is never superseded — it is only revised. Every revision is appended to a history[] array, preserving the full audit trail.

Use decisions to record choices that need a stable, auditable history — such as architectural decisions, configuration choices, or team agreements. Use canonical notes for knowledge that evolves and may be replaced.

create_decision

Creates a new decision with a stable semantic key. The key is immutable after creation and must be unique within the scope.

Parameters

ParameterTypeRequiredDescription
scopestring (slug)YesDomain or project area for this decision
decisionKeystring (slug)YesStable semantic key for this decision (e.g. "auth-protocol"). Immutable after creation.
bodystringYesDecision content in plain text or Markdown
lastWriterstringNoIdentifies the writing surface (e.g. "claude-code"). Stored in the history entry.

Errors

CodeErrorMeaning
409CONFLICT_DUPLICATE_KEYA decision with this key already exists in the scope. Use update_decision to revise it.

update_decision

Revises an existing decision. The previous body is appended to history[] — decisions are append-only. Uses optimistic concurrency via baseVersion.

Parameters

ParameterTypeRequiredDescription
scopestring (slug)YesScope containing the decision
decisionKeystring (slug)YesKey of the decision to revise
bodystringYesNew decision content
baseVersioninteger (≥ 0)YesThe currentVersionyou read before editing. Must match the server’s current version.
lastWriterstringNoIdentifies the writing surface. Appears in CONFLICT_STALE_VERSION messages.

Errors

CodeErrorMeaning
409CONFLICT_STALE_VERSIONThe decision was modified after you read it. Re-read and retry.

get_decision

Returns the current body of a decision and its full revision history.

Parameters

ParameterTypeRequiredDescription
scopestring (slug)YesScope containing the decision
decisionKeystring (slug)YesKey of the decision to retrieve

Response

{
  "decisionKey": "auth-protocol",
  "scope": "architecture",
  "currentBody": "We use JWT with 1h expiry...",
  "currentVersion": 2,
  "updatedAt": "2026-07-15T10:23:00Z",
  "history": [
    {
      "version": 1,
      "body": "We use session cookies...",
      "updatedAt": "2026-06-01T08:00:00Z",
      "lastWriter": "claude-code"
    }
  ]
}

list_decisions

Lists all decisions in a scope with their current version and last update time.

Parameters

ParameterTypeRequiredDescription
scopestring (slug)YesScope to list decisions from

Response

[
  {
    "decisionKey": "auth-protocol",
    "currentVersion": 2,
    "updatedAt": "2026-07-15T10:23:00Z",
    "lastWriter": "claude-code",
    "summary": "Authentication protocol choice — JWT vs session cookies"
  }
]

Capabilities descriptor

Agents can query this endpoint at startup to discover what the server supports and adapt their behaviour accordingly — for example, skipping write calls if writeEnabled is false.

GET /api/ai/capabilities
Authorization: Bearer <your-owner-token>
{
  "protocolVersion": "canonical-docs/0.2",
  "principal": "owner",
  "ownerMode": true,
  "fullReadEnabled": true,
  "writeEnabled": true,
  "supportedOperations": ["create_note", "update_canonical", "update_note_metadata", "list_scopes"],
  "contextEnvelopeEnabled": true,
  "scopeGrammar": "^[a-z0-9]+(-[a-z0-9]+)*$",
  "creatableNoteTypes": ["fleeting", "literature", "permanent", "index", "project", "synthesis", "question"],
  "noteTypeAliases": { "note": "permanent", "source": "literature" }
}