Basalt docs
basaltapp.io

MCP-Server

Basalt bringt einen hauseigenen MCP-Server mit. Damit kann ein Assistent — Claude, eine Agenten-CLI, alles, was das Protokoll spricht — einen Workspace lesen und beschreiben, ohne dass jemand Klebecode schreiben muss.

Es gibt nichts zu installieren. Der Server läuft auf Ihrer Basalt-Instanz und antwortet unter https://app.basaltapp.io/mcp; Sie richten den Assistenten auf diese Adresse und geben ihm ein Token.

Er ist eine dünne Schicht über der öffentlichen API: Der Endpunkt hat keine eigene Rechtelogik, sondern stellt gewöhnliche API-Anfragen mit Ihrem Zugangsdatum. Ein Assistent sieht und ändert damit genau das, was Sie können. Seiten gehen als kanonisches Markdown über die Leitung.

Einrichten

Zuerst ein Token anlegen: Einstellungen → Tokens, im Workspace, in dem der Assistent arbeiten soll. content:read, wenn er nur lesen soll, content:write, wenn er auch schreiben soll. Das Geheimnis wird einmal angezeigt.

Ein hier erstelltes Token gilt hier — es liest und schreibt, was Basalt Ihnen zeigt, und nichts, was in den anderen Apps liegt. Deshalb müssen Sie dem Assistenten auch nicht sagen, welchen Workspace er nehmen soll: Das Token nennt einen, und der Endpunkt liest ihn dort ab.

In der Konfigurationsdatei eines MCP-Hosts:

{
  "mcpServers": {
    "basalt": {
      "type": "http",
      "url": "https://app.basaltapp.io/mcp",
      "headers": {
        "Authorization": "Bearer basalt_pat_…"
      }
    }
  }
}

Die Hosts schreiben das unterschiedlich; gebraucht werden überall dieselben zwei Dinge: die Adresse und der Authorization-Header. In Claude Code etwa:

claude mcp add --transport http basalt https://app.basaltapp.io/mcp \
  --header "Authorization: Bearer basalt_pat_…"

Wenn Ihr Konto in mehreren Workspaces ist und Sie einen ausdrücklich nennen möchten, verwenden Sie stattdessen https://app.basaltapp.io/mcp/w/<Workspace-ID>. Ein Token kann immer nur seinen eigenen Workspace nennen, die beiden müssen also übereinstimmen.

Dass ein Assistent nur liest, regelt das Token und keine Einstellung: Ein content:read-Token weist der Server bei jedem Schreibvorgang ab, und das ist eine härtere Zusicherung als ein Schalter auf der Clientseite.

Als Connector hinzufügen

Hosts ohne Header-Feld — claude.ai gehört dazu — fügen den Endpunkt als Connector hinzu und melden Sie stattdessen an. Tragen Sie dieselbe Adresse https://app.basaltapp.io/mcp in den Connector-Dialog ein; der Rest ist eine Anmeldung und ein Bildschirm mit der Frage, ob Sie verbinden möchten. Nichts zu kopieren, kein Token, das Sie aufbewahren müssen.

Ein Connector reicht weiter als ein Token, und der Bildschirm sagt das, bevor Sie zustimmen:

  • Er gilt für jeden Workspace, in dem Sie Mitglied sind, nicht für einen.
  • Er liest und schreibt, was Sie können. Einen nur lesenden Connector gibt es nicht; für einen Assistenten, der nur schauen soll, erstellen Sie ein Token mit content:read.
  • Er sieht weiterhin nur Basalt, und er hört auf zu funktionieren, wenn Ihr Zugriff endet.

Weil ein Connector mehrere Workspaces umfasst, muss der Assistent sagen, welchen er meint: https://app.basaltapp.io/mcp/w/<Workspace-ID>.

Wenn etwas abgelehnt wird

Der Endpunkt antwortet wie die API, eine Ablehnung sagt also, welcher der drei Fälle vorliegt:

  • 401 — kein Zugangsdatum, oder eines, das unbekannt, widerrufen oder abgelaufen ist.
  • 403 — ein Zugangsdatum, das das nicht darf: ein Token ganz ohne content:read, ein content:read-Token, das schreiben soll, oder eines, das zu einem anderen Workspace gehört als dem, den die Adresse nennt.
  • Alles andere ist die gewöhnliche Antwort der API, mit ihrem eigenen Wortlaut durchgereicht.

Was der Assistent bekommt

Zwölf Werkzeuge. Nur lesend, sofern nicht anders gekennzeichnet.

Werkzeug Wozu
get_workspace Der Workspace, Ihre Rolle und jede Collection, die Sie sehen können, mit Ihrer dortigen Zugriffsstufe. Der erste Aufruf in einem fremden Workspace.
search_pages Volltextsuche über Titel und Inhalte. So kommt man an eine Seitenkennung.
list_pages Strukturelle Auflistung: die Kinder einer Seite oder die oberste Ebene einer Collection.
get_page Eine Seite als kanonisches Markdown, Feldwerte als YAML-Frontmatter, dazu eine Versionsangabe.
list_databases Die Datenbanken des Workspace oder einer Collection.
get_database Die Spalten einer Datenbank: Schlüssel, Typen, Pflichtangaben und die erlaubten Auswahlwerte.
query_database Zeilen mit Filtern und Sortierung. Jede Zeile trägt eine pageId.
create_page schreibend — eine Seite in einer Collection, wahlweise unter einer Elternseite, wahlweise mit Inhalt.
update_page schreibend — ersetzt den ganzen Inhalt und/oder benennt um. Nimmt die Version aus get_page.
update_page_fields schreibend — setzt Feldwerte, ohne den Inhalt anzurühren.
create_database_row schreibend — eine Zeile, die in Basalt eine Seite ist.
trash_page schreibend — legt eine Seite samt Unterbaum in den Papierkorb. Umkehrbar; ein Werkzeug zum endgültigen Löschen gibt es bewusst nicht.

Fünf Felder, auf die Sie sich verlassen können

Jeder Basalt-Workspace hat diese Felder, unter genau diesen Schlüsseln, und niemand kann sie umbenennen, umtypisieren oder löschen. Im Frontmatter einer Seite lesbar, über update_page_fields schreibbar, in query_database filterbar.

Schlüssel Typ Wofür
summary Text Ein, zwei Sätze dazu, worum es auf der Seite geht. search_pages und list_pages geben sie unter jedem Treffer aus — so lässt sich auswählen, was zu öffnen ist, ohne etwas zu öffnen.
status Einfachauswahl Draft, In Review, Approved, Published, Outdated, Archived — sagt, wie belastbar eine Seite ist. Die Liste ist in jedem Workspace dieselbe.
page_type Einfachauswahl Core, Process, Guide, Reference, Decision, Meeting notes, Template, Archive. Ebenfalls überall gleich.
tags Mehrfachauswahl Freier Wortschatz. Ein Wert, den es noch nicht gibt, entsteht beim Schreiben.
related Relation Kuratierte Verknüpfungen zwischen Seiten, symmetrisch: A mit B zu verknüpfen verknüpft B mit A.

Auf einer gerade angelegten oder überarbeiteten Seite summary zu setzen ist das Nützlichste, was ein Agent für den nächsten tun kann.

Zwei Ressourcen lassen sich direkt als Kontext anhängen: basalt://workspace (Collections und Datenbanken mit ihren Kennungen) und basalt://page/{pageId} (eine Seite als Markdown).

Drei Verhaltensweisen sollte man kennen, weil sie ändern, wie ein Assistent vorgehen sollte:

  • update_page ersetzt den Inhalt. Seite lesen, den erhaltenen Text ändern, alles zurückschicken. Ein Ausschnitt kürzt die Seite ab.
  • Versionen sind optimistische Sperren. get_page liefert eine; gibt man sie an update_page weiter, scheitert der Schreibvorgang, statt eine Änderung zu überschreiben, die jemand zwischenzeitlich gemacht hat. Diese Weigerung ist der Zweck.
  • Kennungen werden nie geraten. Sie kommen aus get_workspace, search_pages, list_pages oder query_database.

Was er kann und was nicht

Das Token ist die Identität. Der Server handelt als die Person, die das Token erzeugt hat, mit genau deren Zugriff — mehr kann er nicht, weil es unterhalb der API keinen Pfad gäbe, der das erlaubte. Eine Seite, die diese Person nicht lesen darf, wird nicht zurückgegeben, taucht in keiner Auflistung auf und wird von der Suche nicht gefunden.

Der Assistent sieht also einen betrachterabhängigen Workspace: Zeilenzahlen, Suchtreffer und Seitenbäume sind das, was diese Person sehen kann — nicht das, was existiert.

Manche Verweigerungen kann der Betreiber beheben, andere nicht. Der Server unterscheidet sie deshalb in der Nachricht, die er dem Modell reicht:

  • Ein fehlender Geltungsbereich nennt die genaue Bereichszeichenkette und sagt, dass ein weiterer Versuch nichts hilft — jemand muss ein anderes Token erzeugen.
  • Inhalt, den die Person nicht lesen darf, wird als solcher benannt, mit Verweis auf search_pages.
  • Nicht gefunden behauptet bewusst nicht zu wissen, ob die Seite fehlt oder bloß unlesbar ist — Basalt hält das absichtlich auseinander, und etwas anderes zu behaupten schickte einen Assistenten auf die Suche nach einem Tippfehler, den es nicht gibt.

BASALT_READ_ONLY=true hält die schreibenden Werkzeuge komplett zurück. Weiten kann es nichts — ein content:read-Token verweigert ohnehin jeden Schreibzugriff —, aber „das Modell hat nie ein Schreibwerkzeug gesehen" ist betrieblich eine stärkere Aussage als „das Schreiben ist immer fehlgeschlagen", und es spart dem Assistenten die Züge, in denen er das herausfindet.

Die Tokenverwaltung ist von hier aus überhaupt nicht erreichbar. Ein Zugang, der Zugänge erzeugen kann, weitet sich still aus und überlebt den Widerruf des ersten — deshalb ist die Token-Oberfläche von Haus aus nur mit Sitzung erreichbar.