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:
Find notes on a specific topic. Use this for standalone queries unrelated to the current conversation.
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
Thinker (9€/month) or Thinker+ (19€/month). The MCP server is not available on the free plan.
The MCP server becomes genuinely useful once you have at least 50 validated concepts. With fewer concepts, Claude has little to work with.
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:
- Enter
https://mcp.relinkia.app/sseas the server URL. - Click Add — claude.ai automatically initiates the OAuth authorization flow.
- A Relinkia login and consent page opens in your browser.
- Log in to Relinkia (if not already logged in) and click Approve.
- 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_search
Semantic search across your knowledge base. Uses a hybrid pipeline (full-text + vector embeddings + Cohere reranking).
When to use
The user asks to find notes on a specific topic, with no reference to the current conversation. Examples: “What have I written about stoicism?” — “Find my notes on minimalism.”
When NOT to use
If the query refers to what has just been discussed (“Do my notes relate to what we were just talking about?”) — use relinkia_get_context instead.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| q | string | Yes | Natural language search query |
| limit | integer (1–50) | No — default 20 | Maximum number of results |
| type | string (enum) | No | Filter by note type: fleeting, literature, permanent, index, project, synthesis, question |
| status | string (enum) | No | Filter by maturity: draft, active, mature, archived |
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| q | string | Yes | Natural language search query |
| conversation_context | string (≤ 1200 chars) | No | A 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. |
| limit | integer (1–20) | No — default 10 | Maximum 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
Each call to relinkia_search or relinkia_get_context consumes one agent gesture.
| Plan | Agent gestures / day | Price |
|---|---|---|
| Free | Not available | — |
| Thinker | 20 | 9€/month |
| Thinker+ | 100 | 19€/month |
| BYOK | Unlimited* | 35€/month |
* BYOK covers your own LLM costs. The platform fee (included in the 35€) covers the Relinkia RAG infrastructure (Qdrant, reranking) consumed by each call.
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>"
}
}
}
}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
| Parameter | Type | Required | Description |
|---|---|---|---|
| noteId | string | One of noteId or docKey | MongoDB ID of the note |
| docKey | string (slug) | One of noteId or docKey | Document 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
Semantic search across owner notes, with an optional scope filter. Returns note titles, scopes, keys and current versions — not full body content. Use get_note_full to fetch the body of a specific result.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| q | string | Yes | Natural language search query |
| scope | string (slug) | No | Restrict search to a specific scope (domain/project area) |
| limit | integer (1–50) | No — default 20 | Maximum number of results |
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| docKey | string (slug) | Yes | Unique 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. Optionally assigns a permanent document key for future deterministic access.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| type | string (enum) | Yes | note or source |
| scope | string (slug, max 80) | Yes | Domain or project area for this note |
| title | string (max 500) | Yes | Note title |
| body | string | Yes | Note body in plain text or Markdown |
| docKey | string (slug, max 80) | No | Permanent document key. Must be unique across your notes. Enables deterministic access via get_by_doc_key. |
Response
HTTP 201
{ "noteId": "683e4a2f1c9b..." }Errors
| Code | Error | Meaning |
|---|---|---|
| 409 | DUPLICATE_KEY | A note with this docKey already exists. Choose a different key or omit it. |
update_canonical
Replaces the canonical body of an existing note. 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| noteId | string | Yes | ID of the note to update |
| baseVersion | integer (≥ 0) | Yes | The currentVersionyou read before editing. Must match the server’s current version. |
| newBody | string | Yes | New canonical content (plain text or Markdown) |
| lastWriter | string | No | Identifies the writing surface (e.g. "claude-code", "claude-ai"). Appears in CONFLICT_STALE_VERSION messages. |
| supersedes | string (slug) | No | docKey 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 }Errors
| Code | Error | Meaning |
|---|---|---|
| 409 | CONFLICT_STALE_VERSION | The note was modified after you read it. currentVersionin the response body gives the server’s current version — re-read and retry. |
| 404 | NOTE_NOT_FOUND | No note with this ID belonging to your account. |
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
| Parameter | Type | Required | Description |
|---|---|---|---|
| scope | string (slug) | Yes | Domain or project area for this decision |
| decisionKey | string (slug) | Yes | Stable semantic key for this decision (e.g. "auth-protocol"). Immutable after creation. |
| body | string | Yes | Decision content in plain text or Markdown |
| lastWriter | string | No | Identifies the writing surface (e.g. "claude-code"). Stored in the history entry. |
Errors
| Code | Error | Meaning |
|---|---|---|
| 409 | CONFLICT_DUPLICATE_KEY | A 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| scope | string (slug) | Yes | Scope containing the decision |
| decisionKey | string (slug) | Yes | Key of the decision to revise |
| body | string | Yes | New decision content |
| baseVersion | integer (≥ 0) | Yes | The currentVersionyou read before editing. Must match the server’s current version. |
| lastWriter | string | No | Identifies the writing surface. Appears in CONFLICT_STALE_VERSION messages. |
Errors
| Code | Error | Meaning |
|---|---|---|
| 409 | CONFLICT_STALE_VERSION | The 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| scope | string (slug) | Yes | Scope containing the decision |
| decisionKey | string (slug) | Yes | Key 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
| Parameter | Type | Required | Description |
|---|---|---|---|
| scope | string (slug) | Yes | Scope 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.3",
"ownerMode": true,
"fullReadEnabled": true,
"writeEnabled": true,
"supportedWriteOperations": ["create_note", "update_canonical", "list_scopes", "create_decision", "update_decision", "get_decision", "list_decisions"]
}