Zum Inhalt springen

MCP & KI-Integration

Das Model Context Protocol (MCP) erlaubt KI-Assistenten, eure Wissensdatenbank zu lesen und (mit passenden API-Key-Scopes) zu ändern – z. B. Suche, Dokumente listen, Dokumente anlegen oder aktualisieren.

Orimora bietet zwei MCP-Transporte:

  1. HTTP-Endpunkt unter /api/mcp — empfohlen für Remote-Zugriff. Nutzt den MCP Streamable HTTP Transport. Authentifizierung via API-Key als Bearer-Token.
  2. stdio-Server im Repository — für lokale Entwicklung. Der MCP-Client startet yarn mcp.

MCP zu aktivieren ist eine Team-Admin-Aktion. Es ist über die Berechtigung developer.mcp abgesichert, die das Ein-/Ausschalten des MCP-Endpunkts und die Verwaltung verbundener Apps steuert. Standardmäßig hat nur die Gruppe Admins diese Berechtigung — die Gruppen Editors, Members und Viewers nicht.

Wenn du den Bereich MCP-Server unter Einstellungen → Entwickler also nicht siehst, fehlt dir diese Berechtigung: Bitte eine:n Workspace-Admin, MCP zu aktivieren oder deiner Gruppe unter Einstellungen → Gruppen die Capability developer.mcp zu geben.

  • Eine:n Team-Admin (oder die Berechtigung developer.mcp), um MCP einzuschalten — siehe oben.
  • Für Cursor, Claude Desktop oder Obsidian: nichts weiter — diese verbinden sich mit einem persönlichen API-Key (kb_…), den du unter Einstellungen → Entwickler erstellst. (Die Claude-Mobile-App kann keine API-Keys nutzen — Smartphones verbinden sich nur über OAuth, siehe unten.)
  • Für die Claude-Mobile-App oder claude.ai-Custom-Connectors (OAuth): dein Orimora muss unter einer öffentlichen https://-Adresse erreichbar sein, und beim Self-Hosting musst du APP_URL auf diesen öffentlichen Origin setzen — er ist der OAuth-Issuer; mit APP_URL auf localhost funktioniert der Mobile-Flow nicht. Das ist die einzige erforderliche Einstellung: OAuth ist standardmäßig an (MCP_OAUTH_ENABLED) und braucht keinen separaten Key zum Kopieren — das At-Rest-Token-Secret nutzt deine bestehenden Secrets, in Produktion ist ein eigenes MCP_OAUTH_TOKEN_SECRET aber empfohlen. Alle MCP-OAuth-Variablen samt Defaults: Konfiguration → MCP OAuth (auch in .env.example).
  1. MCP einschalten. In der Web-App: Einstellungen → Entwickler → MCP-Server (HTTP) → aktivieren. Die Seite zeigt danach deine Verbindungs-URL ({APP_URL}/api/mcp) und die Kopier-Buttons.
  2. Client verbinden. Folge dem passenden Abschnitt unten:
  3. Prüfen und Zugriff verwalten. Nach dem Verbinden kann dein Assistent suchen und — mit Schreibrechten — Dokumente bearbeiten. Per OAuth verbundene Apps erscheinen unter Einstellungen → Entwickler → Autorisierte Apps mit Scope und letztem Zugriff; dort kannst du jede App widerrufen, um den Zugriff sofort zu beenden.
  • Derselbe Stack wie bei Installation: Node.js, Yarn, PostgreSQL und eine funktionierende .env mit mindestens DATABASE_URL (und den übrigen in der Konfiguration beschriebenen Secrets).
  • Ein API-Key aus der Web-App: Einstellungen → Entwickler. Den vollständigen Token einmal kopieren (Format kb_…). Der MCP-Server prüft ihn wie die REST-API gegen die Datenbank.

Der HTTP-Endpunkt liegt unter {APP_URL}/api/mcp (z. B. https://deine-domain.de/api/mcp) und muss pro Team aktiviert werden: Einstellungen → Entwickler → MCP-Server (HTTP). Nur Admins können den Schalter setzen.

Authentifizierung via Bearer-Token — dieselben API-Keys wie unter Einstellungen → Entwickler.

  1. In der Web-App Einstellungen → Entwickler öffnen und MCP-Server (HTTP) aktivieren.
  2. Unter API-Keys einen Key mit passenden Scopes anlegen (write, wenn Tools Dokumente ändern sollen). Den vollständigen Token einmal kopieren — Präfix kb_.
  3. Auf derselben Seite URL kopieren und Cursor-MCP-JSON kopieren nutzen (sichtbar, wenn MCP an ist). Im JSON YOUR_API_KEY durch den echten kb_…-Token ersetzen.
  4. Den mcpServers-Eintrag in die Cursor-MCP-Konfiguration einfügen:
    • Benutzerweit: ~/.cursor/mcp.json (macOS/Linux) bzw. der Pfad unter Cursor → Einstellungen → MCP für dein Betriebssystem.
    • Nur ein Repo: .cursor/mcp.json im Repository-Root.
  5. Cursor neu starten oder MCP neu laden, damit der Server erscheint.
{
"mcpServers": {
"orimora": {
"url": "https://deine-domain.de/api/mcp",
"headers": {
"Authorization": "Bearer YOUR_API_KEY"
}
}
}
}

https://deine-domain.de durch eure Instanz-URL und YOUR_API_KEY durch den vollständigen kb_…-Key ersetzen.

Die Config-Datei von Claude Desktop (claude_desktop_config.json) spricht nur stdio. Um aus ihr heraus den Orimora-HTTP-Endpunkt zu erreichen, leiten wir über die mcp-remote-Bridge – ein kleines Node-Helper-Paket, das zwischen stdio (was Claude spricht) und HTTP+Bearer (was Orimora spricht) übersetzt.

In Claude Desktop Einstellungen → Entwickler → Konfig bearbeiten öffnen (oder die Datei direkt – macOS: ~/Library/Application Support/Claude/claude_desktop_config.json) und einfügen:

{
"mcpServers": {
"orimora": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://deine-domain.de/api/mcp",
"--header",
"Authorization:${AUTH}"
],
"env": {
"AUTH": "Bearer YOUR_API_KEY"
}
}
}
}

Hinweise:

  • Token in env.AUTH ablegen und per ${AUTH} in --header referenzieren. So steht der Key in der Prozess-Umgebung, nicht auf der Kommandozeile (kein Leak in ps).
  • Kein Leerzeichen zwischen Authorization: und ${AUTH} – manche mcp-remote-Versionen verwerfen in --header alles nach dem ersten Space.
  • Nach dem Bearbeiten Claude Desktop komplett beenden (⌘Q auf macOS) und neu starten. Nur das Fenster schließen genügt nicht.
  • Auf macOS erbt Claude Desktop nicht zwingend den Shell-PATH. Falls npx nicht gefunden wird, absoluten Pfad eintragen (which npx).

Bridge vorab testen (ohne Claude-Config anzufassen):

Terminal-Fenster
npx -y mcp-remote https://deine-domain.de/api/mcp \
--header "Authorization:Bearer kb_…"

Startet der Prozess ohne 401, funktioniert dieselbe Konfiguration auch in Claude Desktop.

Standard MCP Streamable HTTP Requests senden:

  • POST /api/mcp — MCP JSON-RPC Nachrichten
  • GET /api/mcp — SSE-Stream für Server-initiierte Nachrichten
  • DELETE /api/mcp — Session-Cleanup

Alle Requests erfordern den Authorization: Bearer kb_… Header.

Die drei Flows oben nutzen einen statischen kb_…-API-Key — perfekt für Cursor, Claude Desktop und Obsidian. Die Claude-Mobile-App und claude.ai Custom Connectors unterstützen MCP ausschließlich über einen OAuth-2.1-Flow — auf dem Smartphone gibt es keine Möglichkeit, einen statischen kb_-API-Key einzufügen, OAuth ist also der einzige Weg, mobil zu verbinden. Du fügst eine URL ein, ein Browser öffnet sich, du loggst dich ein und bestätigst, und die App erhält ihr eigenes Token. Orimora unterstützt das out of the box — kein API-Key zum Kopieren.

Setup:

  1. Aktiviere MCP für dein Team: Einstellungen → Entwickler → MCP-Server → einschalten.
  2. Füge in der Claude-App einen Custom Connector hinzu und gib deine Orimora-MCP-Endpunkt-URL ein — sie MUSS den Pfad /api/mcp enthalten, z. B. https://wiki.example.com/api/mcp (derselbe Endpunkt wie Option 1, nur ohne API-Key). Gib nicht die bare Domain ein (https://wiki.example.com) — die trifft die Startseite und liefert 405, dann startet OAuth nie. Aus dem 401 an /api/mcp entdeckt die App den OAuth-Flow automatisch via /.well-known/oauth-protected-resource.
  3. Dein Browser öffnet einen Orimora-Login → Consent-Screen. Bestätige den angeforderten Zugriff (Lesen oder Lesen + Schreiben).
  4. Fertig. Die App hält ein kurzlebiges Access-Token (auto-refresh), gescoped auf dein Team.

Zugriff verwalten: Jede verbundene App erscheint unter Einstellungen → Entwickler → Autorisierte Apps mit gewährtem Scope und letzter Nutzung. Widerrufen dort macht die Tokens sofort ungültig — die App muss sich neu autorisieren.

Clients entdecken diese automatisch; hier für Betrieb und Debugging gelistet. Alle werden aus APP_URL (dem Issuer) abgeleitet:

EndpunktZweck
/.well-known/oauth-protected-resourceRFC-9728 Protected-Resource-Metadata
/.well-known/oauth-authorization-serverRFC-8414 Authorization-Server-Metadata
POST /oauth/registerDynamic Client Registration (RFC 7591)
GET/POST /oauth/authorizeAutorisierung + Consent (PKCE S256)
POST /oauth/tokenToken-Ausgabe + Refresh (Rotation)
POST /oauth/revokeToken-Widerruf (RFC 7009)

Vollständige Konfiguration (TTLs, CORS-Origins, erlaubte App-Schemes, Rate-Limit, Token-Secret) in der Konfigurations-Referenz → MCP OAuth.

Für lokale Entwicklung mit direktem Datenbankzugriff:

Terminal-Fenster
export ORIMORA_API_KEY="kb_dein_vollständiger_token"
yarn mcp

Der Prozess nutzt stdio – er wird von einem MCP-Client als Kindprozess gestartet, nicht im Browser geöffnet.

Technisch: tsx mit tsconfig.mcp.json und src/mcp-server/index.ts (siehe Script mcp in package.json).

{
"mcpServers": {
"orimora": {
"command": "yarn",
"args": ["mcp"],
"cwd": "/absoluter/pfad/zum/orimora-repo",
"env": {
"ORIMORA_API_KEY": "kb_…",
"DATABASE_URL": "postgresql://user:pass@host:5432/dbname"
}
}
}
}
  • cwd muss das Orimora-Repo-Root sein (Module und Pfade).
  • Lädt der Client eure .env, können doppelte Variablen entfallen – sonst DATABASE_URL explizit setzen.

Gleiches Muster: command, args, Arbeitsverzeichnis, Umgebung mit ORIMORA_API_KEY und DATABASE_URL.

create_document, update_document, append_to_document, prepend_to_document und insert_after_heading erwarten den Inhalt als Markdown über den Parameter markdown. Der Server wandelt ihn in das TipTap/ProseMirror-JSON um, das der Editor erwartet (über markdown-it → HTML → das gemeinsame TipTap-Schema).

Kein TipTap/ProseMirror-JSON über MCP senden. Die Tools exponieren kein content-Feld. Direktes Editor-JSON würde voraussetzen, dass der Client jede verwendete Extension und jedes Attribut kennt – das driftet mit der Zeit, und unbekannte Nodes werden still verworfen.

get_document spiegelt das und liefert den Inhalt nur als markdown (kein TipTap-JSON). Das hält Payloads klein und zwingt Clients in dasselbe Format auf Lese- und Schreibseite.

Voll round-trip-fähig (Lesen und Schreiben): Überschriften (H1–H6) inkl. Heading-IDs (### Titel {#anker}), Absätze, fett, kursiv, inline code, ~~durchgestrichen~~, <u>unterstrichen</u>, Highlight (==x==), Subskript (~x~), Superskript (^x^), Footnotes ([^1]-Referenzen + [^1]: Text-Definitionen), Emoji-Shortcodes (:joy: → 😂, als Unicode gespeichert), sortierte Listen (inkl. individueller Startnummer), unsortierte Listen, verschachtelte Listen, Task-Listen (- [ ] / - [x]), Blockzitate, Codeblöcke mit Sprach-Hint, Trennlinien, GFM-Tabellen, Links sowie Bilder über externe URLs.

Aktuell nicht via MCP unterstützt (im internen Backlog):

  • Definition Lists (term / : def) – werden vom Editor noch nicht gerendert; vorerst beim Schreiben vermeiden (Backlog Tier 3).
  • Inline-Base64-Bilder im Markdown – werden abgelehnt. Nutze das upload_image-Tool, um ein Bild an ein Dokument anzuhängen, oder referenziere eine extern erreichbare URL.

Für die absolute Markdown-Quelle jederzeit get_document aufrufen – der zurückgegebene markdown-String ist byte-genau äquivalent zu dem, was der Editor anzeigt.

Für bestehende Dokumente gezielte Änderungen nutzen statt Full-Rewrites:

  • append_to_document(id, markdown) – hängt ein Fragment am Ende an, getrennt durch eine Leerzeile.
  • prepend_to_document(id, markdown) – fügt am Anfang ein.
  • insert_after_heading(id, heading, markdown) – fügt direkt nach der ersten Überschrift ein, deren Text mit heading übereinstimmt (case-insensitive, getrimmt). Liefert HEADING_NOT_FOUND, wenn keine passt – Aufrufer sollten dann auf append_to_document fallback.

Alle drei lassen bestehenden Inhalt unverändert, benötigen write-Scope plus Schreibrecht aufs Dokument und nutzen dieselbe Markdown→TipTap-Konvertierung wie create_document.

delete_document führt einen Soft Delete aus (Dokument landet im Papierkorb, aus der App wiederherstellbar). Es ist eine zweistufige Aktion:

  1. Aufruf ohne confirm – der Server antwortet mit { status: "confirm_required", preview: { title, collectionName, bodyLength, … } }, damit der Agent dem User zeigen kann, was gelöscht werden soll.
  2. Zweiter Aufruf mit confirm: true – der Server legt das Dokument in den Papierkorb und liefert { status: "deleted", id, deletedAt }.

Hard-Deletes sind über MCP nicht verfügbar. Endgültiges Löschen passiert in der App über „Papierkorb leeren”.

API-Keys haben:

  • Scopes: read, write, admin – schreibende MCP-Tools brauchen wo nötig write.
  • Restricted Mode: optionale Allowlists pro Sammlung und Dokument-Overrides unter Einstellungen → Entwickler → Zugriff konfigurieren. Dieselben Regeln gelten für MCP und /api/v1/.

„Second Brain” (read-only) vs. beschreibbare Collections

Abschnitt betitelt „„Second Brain” (read-only) vs. beschreibbare Collections“

Typisches Agent-Setup: Eine Collection ist read-only Wissensbasis für die KI, eine andere ist Schreib-Fläche. Ein einziger API-Key reicht – Restricted Mode erlaubt per-Collection-Overrides, also kann ein Key Read-Only auf die Wissensbasis und Read+Write auf die Arbeits-Collection halten.

Für diesen Key unter Einstellungen → Entwickler → Zugriff konfigurieren:

  1. Restricted Mode aktivieren.
  2. Wissens-Collection auf Nur Lesen setzen.
  3. Arbeits-Collection auf Lesen + Schreiben setzen.
  4. Alle anderen auf Kein Zugriff.

Die MCP-Tools liefern auf jeder Collection in list_collections und auf jeder get_document-Antwort ein canWrite-Flag. Agenten sollten dieses Flag prüfen, bevor sie create_document / update_document / append_to_document / delete_document aufrufen, statt Fehlversuche zu riskieren.

Kurz-Checkliste für Maintainer: internal/dev-and-mcp.md im Repository.