nessie

MCP und verbundene Tools

Verbinden Sie Nessie mit MCP-Servern und koppeln Sie einen externen Agenten, damit er in Nessie in Ihrem Namen arbeiten kann.

Was MCP ist

Das Model Context Protocol ist eine kleine, offene Konvention, um einem Sprachmodell Tools zu beschreiben und sie aufzurufen. Ein Server erklärt, was er kann: eine Liste benannter Tools, jedes mit einem JSON-Schema für seine Argumente. Ein Client erkennt diese Liste und ruft die Tools im Auftrag des Modells auf. Das Protokoll ist bewusst schlicht gehalten. Sein Nutzen liegt darin, dass eine einmal geschriebene Integration mit jedem Modell und jedem Produkt funktioniert, das es spricht.

Nessie steht auf beiden Seiten

Das lohnt eine genaue Unterscheidung, denn die beiden Hälften werden leicht verwechselt. Sie liegen bewusst auf unterschiedlichen Pfaden.

  • Ausgehend. Nessie ist ein MCP-Client. Sie verbinden Server, die jemand anderes betreibt, und die Tools, die sie bereitstellen, werden zu Tools, die Ihre Agenten nutzen können. Die Verwaltungsoberfläche liegt unter /api/mcp/*.
  • Eingehend. Nessie ist außerdem ein MCP-Server. Ein Agent, der anderswo läuft, etwa Claude Code oder Codex auf einem Entwicklerrechner, kann auf Ihre Boards und Dokumente zugreifen. Dieser Endpunkt ist POST /mcp, bewusst außerhalb von /api, damit die beiden gegensätzlichen Bedeutungen nicht nur ein Pfadsegment auseinander liegen.

Einen MCP-Server mit Nessie verbinden

Katalogeinträge und Instanzen

Es gibt zwei Objekte, und die Unterscheidung ist wichtig:

  • Ein Katalogeintrag ist die Definition eines Servers: sein Name, sein Transport, seine Authentifizierung. Er wird einmal geschrieben und kann geteilt werden.
  • Eine Instanz ist dieser Eintrag, in einem bestimmten Bereich installiert, mit den Zugangsdaten, die ihn erreichen. Wenn Sie denselben Eintrag für zwei verschiedene Teams installieren, entstehen zwei Instanzen.

Die meisten Menschen berühren keines von beiden direkt. Der Zugang in der Admin-Oberfläche ist der App Store unter /admin/apps. Er durchsucht denselben Katalog, mit ausgeblendeten Verbindungsdetails, und Verbinden auf einem Eintrag legt eine Instanz an. Betreiber, die die rohen Objekte brauchen, nutzen /api/mcp/catalog und /api/mcp/instances.

Ist ein Server noch nicht im Katalog, nimmt POST /api/mcp/discover eine URL entgegen und liefert zurück, was der Server über sich selbst sagt. POST /api/mcp/library/import übernimmt einen Eintrag aus der öffentlichen Server-Bibliothek. Eine Erstverbindung lässt sich auch direkt aus einer URL mit POST /api/apps/custom anlegen.

Transporte

Nessie verbindet sich über HTTP mit entfernten Servern. Zwei Transporte funktionieren: Streamable HTTP, der aktuelle MCP-Transport, und der ältere HTTP+SSE-Transport. Wählen Sie http, sofern der Server nur sse anbietet.

Der Transport stdio wird für Connectors, die Sie selbst schreiben, abgelehnt. stdio bedeutet, dass der MCP-Server ein lokaler Prozess ist, den der Host startet. Beliebige Programme im Nessie-Server laufen zu lassen, kann ein Betreiber nicht sinnvoll prüfen. Server, die nur als lokal auszuführendes Paket veröffentlicht sind, fallen aus demselben Grund aus den Bibliotheksimporten heraus. Ein Wert ws existiert im Protokollfeld, ist aber nicht implementiert. Eine Verbindung, die ihn nutzt, schlägt fehl, sobald Nessie sie öffnen will.

Wie Nessie sich am Server authentifiziert

Ein Katalogeintrag deklariert eine von fünf Methoden: none, api_key, bearer, basic oder oauth2.

api_key setzt den Schlüssel in einen Header, und der Eintrag legt fest, welcher Header und welches Präfix verwendet wird. Authorization: Bearer …, X-API-Key: … und X-Auth-Token: Token … sind also dieselbe Methode, nur anders konfiguriert. Der Schlüssel selbst wird einmalig mit POST /api/mcp/instances/:instanceId/secret eingegeben und ist danach nie wieder lesbar. Keine Antwort der Instanz-Routen enthält eine Zugangsdaten-Referenz.

oauth2 gibt es in zwei Formen. Ein Server mit festen Endpunkten hat sie in seinem Katalogeintrag. Ein Server, der Standard-Metadaten veröffentlicht, braucht gar nichts zu konfigurieren: Nessie liest die Dokumente zur geschützten Ressource und zum Autorisierungsserver und erzeugt sich selbst einen Client, entweder über dynamische Client-Registrierung oder über das Client-ID-Metadatendokument, das Nessie unter seinem eigenen Well-known-Pfad veröffentlicht. In beiden Fällen läuft der Handshake über POST /api/mcp/instances/:instanceId/oauth/start, gefolgt von der Weiterleitung des Anbieters zurück an GET /api/mcp/oauth/callback. Der State-Token ist einmalig verwendbar, wird in der Datenbank gehalten und ist zehn Minuten gültig. PKCE wird immer verwendet.

Eine Regel überrascht viele: Selbst ein Inhaber einer Organisation kann einer anderen Person kein persönliches oder OAuth-Token zuordnen. Ein gemeinsam genutzter Zugang ist nur bei einem API-Key-Eintrag möglich, der als solcher validiert wurde. Alles andere wird abgelehnt. Ein Zugang, der einer Person gehört, bleibt ein Zugang dieser Person.

Wo die Zugangsdaten liegen

Connector-Geheimnisse und OAuth-Token-Bündel werden in Ihrer eigenen Postgres-Datenbank gespeichert, in zweckgebundenen AES-256-GCM-Umschlägen unter dem unabhängig versionierten Verschlüsselungsschlüsselring der Bereitstellung. Sie werden ausschließlich über undurchsichtige Referenzen secret_* angesprochen. Sie liegen bewusst nicht im externen Secret-Vault, der die übrigen Nessie-Geheimnisse hält. Eine Produktionsbereitstellung, die den verschlüsselten Speicher nicht konfiguriert hat, startet nicht. Sie führt keinen OAuth-Handshake durch, den sie anschließend verlieren würde.

Wohin eine Verbindung reicht

Eine Instanz wird in einem von sechs Bereichen installiert: system, organization, project, team, channel oder user. Dieser Bereich ist eine harte Obergrenze dafür, welche Läufe die Instanz nutzen können. Freigaben können ihn nur weiter einschränken, nie erweitern. Ein Connector, den Sie mit Ihrem eigenen Konto installiert haben, kann so nicht stillschweigend zu einem organisationsweiten werden.

Wer wo installieren darf, folgt derselben Struktur. Inhaber und Admins der Organisation verwalten Installationen in jedem Bereich. Alle anderen installieren Connectors in ihrem eigenen Bereich user und können gemeinsame Installationen sehen, die sie erreichen dürfen.

Einem Agenten ein Tool geben

Einen Server zu verbinden, gibt seine Tools niemandem automatisch. Wenn eine Instanz installiert wird, prüft Nessie sie und überträgt jedes Tool, das sie anbietet, in die Tool-Registry. Diese Registry zeigt die Admin-Oberfläche unter /admin/advanced/tools: eingebaute Tools, MCP-Tools, Bundle-Tools und Executor-Tools in einer Liste, jeweils mit Quelle und Status.

Ein übertragenes Tool hat einen von drei Status: active, pending_review oder disabled. Tools aus einer Installation mit gemeinsamem Bereich kommen als pending_review und müssen auf dieser Seite genehmigt werden, bevor ein Agent sie sieht. Tools aus Ihrer eigenen Installation im Bereich user sind sofort aktiv, denn die einzige betroffene Person sind Sie. Die Prüfung wiederholt sich und ist kein einmaliges Ritual. Stellt eine spätere Prüfung fest, dass sich Beschreibung oder Schema eines Tools verändert haben, geht es zurück auf pending_review und wird nicht mehr angeboten, bis jemand die Änderung ansieht.

Welche Agenten ein aktives Tool dann aufrufen dürfen, entscheidet sich auf zwei Wegen:

  • Eine über den App Store angelegte Verbindung erfordert eine ausdrückliche Freigabe. Ein Agent erhält das Tool nur, wenn eine Freigabe es benennt. Die Freigabe wird gegen den aktuellen Fingerprint des Tools geprüft, daher braucht ein geändertes Tool eine neue Entscheidung.
  • Sonst ist das Tool standardmäßig für die Agenten eingeschaltet, die den Bereich des Tools erreichen. Einzelne Agenten lassen sich auf dem Detailpanel des Tools ausschalten.

Eine Freigabe benennt genau einen Berechtigten, eine Rolle oder einen Agenten, nie beides, und ein Verbot schlägt eine Erlaubnis. Für eine Verbindung im Bereich user stellt sich die Frage gar nicht: Jeder Agent, mit dem diese Person spricht, kann sie nutzen. Nur ein ausdrücklich gesetzter Ausschalter hält sie zurück.

Eine Stelle, an der man leicht im Falschen sucht: /settings/accounts in der Admin-Oberfläche sind verbundene Konten. Dazu gehören Slack, Postfächer, Modellabonnements und die OAuth-Verknüpfungen zu Linear, Jira, GitHub und Trello, die externe Boards anbinden. MCP-Connectors finden Sie unter /admin/apps, und die daraus entstehenden Tools unter /admin/advanced/tools.

Genehmigungsschranken bei Tool-Aufrufen

Einige Tool-Aufrufe halten an und warten auf eine Person. Dann schlägt der Lauf nicht fehl. Der Aufruf wird eingefroren, also Tool-Name, ein Hash seiner Argumente und genug Zustand, um fortzufahren. Eine Genehmigungsanfrage erscheint unter /api/approvals, damit jemand sie beantwortet. Das Fortsetzen ist idempotent, daher kann eine doppelte Genehmigung den Aufruf nicht zweimal ausführen. Die entscheidende Person sieht eine begrenzte Zusammenfassung dessen, was verlangt wird. Die exakten Argumente und der ursprüngliche Lauf bleiben serverseitig.

Es gibt zwei getrennte Schranken, und sie werden unterschiedlich konfiguriert.

  • Strukturelle Schranken sind eine Eigenschaft bestimmter eingebauter Tools und nicht konfigurierbar. Gesendete Mails aus dem eigenen Postfach eines Agenten oder aus einem verbundenen Postfach, das Senden eines Gmail-Entwurfs, das Trennen eines Mailkontos, das Anlegen, Ändern oder Absagen eines Kalendertermins sowie eine Browser-Aktion, die auf eine Website schreiben würde, bei der der Browser nicht angemeldet ist, sind alle so geschützt. Dafür steht ein Zeitfenster von 24 Stunden zur Beantwortung bereit statt der üblichen 30 Minuten.
  • Richtlinien-Schranken stammen aus Policy-Regeln für das Paar tool/invoke. Eine Regel, die einen Aufruf erlaubt, kann requiresApproval tragen. Ohne geprüfte Genehmigung liefert die Auswertung APPROVAL_REQUIRED zurück, statt auszuführen. Regeln werden zuerst nach Verboten ausgewertet und nach Bereich geordnet.

Welcher Bildschirm der Admin-Oberfläche eine Richtlinienregel requiresApproval für ein Tool anlegt, konnten wir nicht bestätigen. Das Datenmodell und die Durchsetzung sind beide vorhanden, der Bildschirm, der eine solche Regel schreibt, aber nicht.


Einen externen Agenten mit Nessie verbinden

Die andere Richtung. Nessie betreibt einen eigenen MCP-Server unter POST /mcp, über Streamable HTTP. Er ist zustandslos: Jeder Aufruf trägt seine eigenen Zugangsdaten und bestimmt seinen Akteur selbst, daher gibt es keine Sitzung, die einen Client an ein Replikat binden würde. ChatGPT, Claude, Claude Code, Codex oder ein Agent auf dem Laptop einer Person können an Ihren Boards, Dokumenten und Kunden arbeiten, und zwar innerhalb des Werkzeugs, das diese Person ohnehin nutzt. Die Schritt-für-Schritt-Anleitung für jede App finden Sie unter ChatGPT, Claude und weitere KI-Apps verbinden.

Was ein gekoppelter Zugang eigentlich ist

Das ist der Teil, den man richtig verstehen muss, denn das naheliegende Denkmodell ist falsch: ein API-Schlüssel mit angehängten Berechtigungen.

Ein gekoppelter Zugang ist nie eine Identität. Er benennt einen Menschen, und jeder Tool-Aufruf läuft als dieser Mensch, gegen dieselben Dienstfunktionen, die auch die HTTP-Routen aufrufen. Ein Agent kann daher nichts erreichen, was die Person, die ihn überlassen hat, nicht auch per Klick erreichen könnte. Bereiche schränken diese Reichweite nur ein. Kein Bereich erweitert sie.

Die Gültigkeit wird bei jedem einzelnen Aufruf neu gelesen und nie aus dem Token übernommen: Widerruf, Ablauf, die Token-Version des Benutzers, seine Mitgliedschaft in der Organisation und seine aktuelle Rolle. Eine Herabstufung, eine Deaktivierung oder ein „Überall abmelden“ wirkt beim nächsten Aufruf des Agenten, nicht erst beim Ablauf des Zugangs.

Das Token ist undurchsichtig, beginnt mit nag1_, wird nur als SHA-256-Hash gespeichert und ist 90 Tage gültig. Auf jeder anderen Route als dem MCP-Endpunkt wird es mit einem eigenen 403 abgelehnt. Wer es dort vorlegt, erhält keinen Teilerfolg, den man wiederholen müsste. Dadurch bedeutet „Ich habe einem Agenten meine Boards überlassen“ nicht zugleich „Ich habe ihm mein Konto überlassen“.

Zwei Wege, sich zu verbinden

Eine App, die einen Browser öffnen kann, etwa ChatGPT, Claude, Claude Code oder Codex, nutzt das Autorisierungsprofil von MCP: OAuth 2.1 mit PKCE (S256), dynamische Client-Registrierung unter POST /mcp/oauth/register, Refresh-Tokens und Resource Indicators. Die App schickt die Person zu /settings/security. Dort wählt sie, was die App tun darf und welche ihrer Teams sie erreicht. Danach kehrt der Browser mit einem Code zur App zurück. Das Zugriffs-Token gilt eine Stunde und wird erneuert. Die Verbindung bleibt 90 Tage bestehen.

Ein Kommandozeilen-Agent steuert keinen Browser und kann keine Callback-URL hosten. Deshalb koppelt er sich stattdessen über den Device Authorization Grant (RFC 8628).

  1. Der Agent ruft POST /mcp/auth/device mit einem clientName und den gewünschten scopes auf. Er erhält einen device_code, einen kurzen user_code, eine verification_uri und eine verification_uri_complete, in deren Abfrage der Code bereits steht, dazu das Abfrageintervall interval und ein expires_in. Er gibt die URI aus.
  2. Eine Person öffnet diese URI, während sie angemeldet ist, auf /settings/security. Dort sieht sie, welcher Agent fragt, in wessen Namen er arbeiten würde, bis wann und genau was er tun könnte. Sie wählt Zulassen oder Nicht zulassen.
  3. Der Agent fragt POST /mcp/auth/token mit dem deviceCode ab und berücksichtigt authorization_pending, slow_down, expired_token und access_denied. Bei Erfolg erhält er { access_token, token_type, scope, expires_at }.

In beiden Fällen gibt es einen menschlichen Schritt, denn der Zugang erbt die Berechtigungen einer Person. Deshalb muss eine Person sich dafür entscheiden, ihn zu überlassen. Hier wird nichts aus dem Nichts gewährt. Das Verbinden lässt sich außerdem für eine ganze Organisation unter /admin/security?tab=programs abschalten. Diese Einstellung wird geprüft, wenn jemand eine Verbindung zulässt, nicht wenn ein Agent eine startet.

Erkennung

Ein nicht authentifiziertes POST /mcp antwortet mit 401 und einem Header WWW-Authenticate, der auf /.well-known/oauth-protected-resource (RFC 9728) zeigt. Dieses Dokument nennt diesen Ursprung als Autorisierungsserver. Seine Metadaten unter /.well-known/oauth-authorization-server (RFC 8414) nennen die Endpunkte für Registrierung, Autorisierung, Token und Widerruf. Diese Kette ist alles, was ein Client braucht, sobald er die Adresse hat. Um die Adresse ausgehend von einer Domain zu finden, liest ein Agent /.well-known/ai-catalog.json. Dieses Dokument verweist auf die Server Card unter /mcp/server-card (MCP Server Cards, SEP-2127). Die Endpunkte der Device-Freigabe stehen im Dokument der geschützten Ressource unter x-nessie-device-authorization.

Eine Bereitstellung kann außerdem unter einer zweiten, kürzeren Adresse antworten. Die Adresse https://nessie.works/mcp der Nessie Cloud wird an die API weitergeleitet. Ein Client, der auf diesem Weg kommt, erhält genau diese Adresse als Ressource zurück, die Anmeldung bleibt bei der API. Eine Weiterleitung würde nicht genügen, denn ein Client lehnt Metadaten ab, die eine andere Adresse nennen als die, die er bekommen hat. Der Betreiber trägt diese Ursprünge in NESSIE_MCP_ALIAS_ORIGINS ein.

Bereiche und Tools

Bereiche sind absichtlich grob gehalten: Ein Bereich, den niemand erklären kann, setzt auch niemand richtig. Eine Verbindung, die mehr als ein Team erreicht, listet diese Teams mit nessie_team_list auf. Jedes andere Tool nennt dann seine teamId.

BereichErreicht
boards_readProjekte, Boards und Tickets, mit ihren Kommentaren, Dateien, Labels, Typen und Checklisten
boards_writeTickets anlegen, bearbeiten und verschieben, und alles, was daran hängt
documents_readWissensbereiche, Dokumente und Tabellen
documents_writeDokumente entwerfen und bearbeiten sowie die Veröffentlichung eines Dokuments anfragen
clients_readDen Kundenposteingang, Kontakte, Kontaktlisten, Newsletter und Kontaktformulare
clients_writeNotizen, Übernehmen, Zuweisen und Schließen von Gesprächen, Kontaktlisten und die Vorbereitung von Newslettern
clients_sendAlles, was ein Kunde erhält: eine Antwort, eine erste E-Mail oder eine Textnachricht. Wird nie vorausgewählt, nur die Person selbst kann es ankreuzen.
website_toolsDie Seitentools der registrierten Website Ihres Teams, bedient in einem gehosteten Browser, den Sie steuern dürfen. Wird nie vorausgewählt, nur die Person selbst kann es ankreuzen.

Ein Aufruf ohne den Bereich, den er braucht, kommt als Tool-Ergebnis zurück, das den anzufragenden Bereich nennt, nicht als Transportfehler. So kann das Modell etwas Nützliches berichten, statt immer wieder in dieselbe Wand zu laufen.

Für externe Tracker gibt es keine eigene Tool-Familie. Ein Board ist ein Board, egal ob seine Aufgaben in Nessie entstehen oder aus Linear, Jira, GitHub oder Trello gespiegelt werden. Deshalb deckt ein einziges Tool-Set beides ab, und jede Aufgabe gibt an, woher sie stammt. Unterschiedlich ist nur das Schreiben: Ein Board, das aus einer nur lesbaren Quelle gespiegelt wird, lehnt einen Schreibvorgang mit einer Begründung ab. Sie sagt dem Agenten, dass das andere System das Ticket besitzt und ein erneuter Versuch nichts ändert.

Ein Dokument zu veröffentlichen ist eine Genehmigung, nie ein Bereich

Agenten entwerfen, eine Person veröffentlicht. Für die eigenen Agenten von Nessie wird diese Regel durchgesetzt, indem ein Agent-Akteur schlicht abgewiesen wird. Ein gekoppelter Zugang wird aber als Person aufgelöst, deshalb kann diese Abweisung ihn nicht erfassen. Die Schranke muss anderswo sitzen.

Deshalb veröffentlicht nessie_doc_publish nicht. Es öffnet eine Genehmigung knowledge.page.publish, dieselbe, die auch ein Nessie-Agent öffnet, und gibt { status: "awaiting_approval", approvalId } zurück. Abfragen liefern dieselbe Anfrage zurück, statt eine zweite zu öffnen. Die Entscheidung fällt so, wie jede andere Veröffentlichungsentscheidung in Nessie fällt: durch eine Person, über dieses Dokument, in dem Moment, in dem es existiert.

Es gibt bewusst keinen Veröffentlichungs-Bereich. Es gab einen, nämlich ein Häkchen bei der Kopplung, das besagte, dieser Agent dürfe veröffentlichen. Er wurde zurückgezogen. Er entschied einmal und neunzig Tage lang eine Frage, die Nessie überall sonst pro Dokument stellt, und zwar bevor das Dokument existierte. Die Person, die das Häkchen setzte, konnte daher nicht wissen, was sie zu veröffentlichen zustimmte. nessie_doc_publish braucht documents_write, weil Nachfragen nicht kostenlos ist: Es liest die Seite und legt einer Person eine Entscheidung vor. Doch dieser Bereich gewährt nichts im Hinblick auf die Veröffentlichung.

Zwei Identitäten werden bei der Anfrage festgehalten, und der Unterschied ist tragend. Der Anfragende ist der Zugang, nie der Mensch, in dessen Namen er handelt. Der erforderliche Genehmigende ist dieser Mensch, und nur er darf antworten. Würde die Anfrage die Person als Anfragende nennen, würde die Regel, die verhindert, dass jemand die eigene Anfrage genehmigt, genau die eine Person ausschließen, die zur Entscheidung berechtigt ist.

Gekoppeltes sehen und widerrufen

Die gekoppelten Agenten einer Person listet /settings/security auf, mit einer Bezeichnung und einem Widerrufs-Schalter für jeden. Ein Inhaber oder Admin einer Organisation sieht jeden Zugang der Organisation unter /admin/security?tab=programs: wie er heißt, was er darf, ob er aktiv ist und auf wessen Konto er zugreift. Jeden davon kann er widerrufen. Die persönliche Liste bleibt auf die eigene Person beschränkt. Eine Liste aktiver Zugänge ist eine Liste möglicher Einstiegspunkte, kein allgemeiner Lesestoff.

Schreibvorgänge über einen Zugang werden der Person zugeschrieben, die ihn nutzt, und tragen die ID des Zugangs in den Audit-Metadaten. So kann das Protokoll die eigene Änderung einer Person von einer unterscheiden, die ihr Agent für sie vorgenommen hat.

Was noch nicht verfügbar ist

Ausdrücklich, weil die Lücke zwischen den Fähigkeiten eines Protokolls und denen eines bestimmten Servers der Ort ist, an dem Dokumentation gewöhnlich versagt:

  • Chat, Kanäle, Läufe und die Verwaltung von Agenten sind nicht über MCP erreichbar.
  • Ein Client bereitet einen Newsletter vor, und eine Person versendet ihn. Nichts sendet, plant oder löscht eine Kampagne, und die E-Mail selbst wird im Designer geschrieben.
  • Das Verknüpfen und Zusammenführen von Kontakten, Änderungen am CRM-Schema, Importe und die Einrichtung von Kanälen bleiben im Browser bei einer Person.
  • Der Schalter für das Verbinden ist eine Einstellung auf Organisationsebene. Team- und persönliche Überschreibungen kann ein Team oder eine Person heute nicht setzen.