1. Warum überhaupt über Berechtigungen in der ChatGPT‑App nachdenken (und wo liegt hier das besondere Risiko)
Im „gewöhnlichen“ Web‑Produkt gibt es zwischen Nutzer und Ihrer Datenbank nur ein paar Schichten: Frontend, API, DB. In der ChatGPT‑App erscheint zwischen Nutzer und API ein weiterer aktiver Teilnehmer – die LLM. Und sie ist nicht nur ein „Textfilter“, sondern eine Entität, die:
- selbst auswählt, welche Tools sie mit welchen Argumenten aufruft;
- durch Prompt‑Injection getäuscht werden kann – auch über Daten;
- Tools „verwechseln“ oder Argumente erfinden kann, mit denen Sie nicht gerechnet haben.
Wenn man der LLM zu viele Befugnisse erteilt, erhält man das klassische Confused Deputy‑Problem: das Modell führt gewissenhaft aus, was aus seiner Sicht der Nutzer oder ein Dokumententext verlangt, ruft dabei aber delete_all_orders statt get_last_order auf.
Daher ist unser Ziel:
- Minimieren der Rechte der auth_tokens (welche Daten und Aktionen grundsätzlich verfügbar sind).
- Begrenzen, welche Tools dem Modell in einem konkreten Szenario überhaupt zur Verfügung stehen.
- Ergänzen durch menschliche Kontrolle dort, wo die Folgen besonders kritisch sind.
Und all das sollte ohne Paranoia und Totalverbot passieren, sonst wird die App nutzlos. Das Gleichgewicht zwischen Komfort und Sicherheit ist unsere Hauptaufgabe in diesem Modul.
2. Zugriffsmodell im Ökosystem: wer greift worauf zu
Um den Überblick zu behalten, betrachten wir das System als Ganzes. Wir haben mehrere Ebenen – jede mit eigener Zuständigkeit und eigenen Rechten.
flowchart TD U[Benutzer in ChatGPT] --> C[ChatGPT UI + LLM] C --> A["Ihre App (visueller Plan + Widget)"] A --> G[MCP Gateway / API Edge] G --> S[MCP‑Server und Microservices] S --> D[Datenbanken, Queues, externe APIs]
Kurz zu den Rollen:
- ChatGPT UI und LLM: werden von OpenAI betrieben. Sie geben Anweisungen (system‑prompt, tool descriptions), kontrollieren aber nicht die internen Token und Rechte der Plattform.
- Ihre App (Plan, Tools, Widget): Sie entscheiden, welche Tools verfügbar sind, wie sie beschrieben sind, welche UX‑Bestätigungen nötig sind und welche Daten das Widget anzeigen darf.
- MCP Gateway / API Edge: hier geschieht die Token‑Prüfung, das Mapping von userId, tenantId, der Liste der scopes und die Weiterleitung an den richtigen Service.
- MCP‑Server und Microservices: führen Tools aus, machen DB‑ und externe API‑Aufrufe. Hier sollten die Prüfungen maximal streng sein: scopes, Tenant‑Isolation, Eingabevalidierung.
- Speicher und externe APIs: letzte Verteidigungslinie (DB‑Einschränkungen, Berechtigungen der Accounts externer Dienste).
Der Kernpunkt: Die LLM ist keine Quelle der Zugriffsrechte. Alles, was im MCP‑Server ankommt, betrachten wir als „vom Modell formulierte Nutzeranfrage“. Zu entscheiden, ob eine Operation wirklich ausgeführt werden darf, ist die Aufgabe Ihres Backend‑Codes, nicht des Prompts.
3. AuthN vs AuthZ: was wir bereits können und was wir hinzufügen
Im Modul zur Authentifizierung haben Sie bereits:
- AuthN (Authentication) – ermittelt, wer der Nutzer ist. Über OAuth 2.1/PKCE erhielt ChatGPT vom IdP ein Token, das dann bei MCP‑Aufrufen mitgesendet wurde. Darin standen sub, user_id oder Ähnliches, manchmal tenant_id.
- Basis‑AuthZ – eventuell haben Sie bereits user/admin‑Rollen unterschieden und zumindest „ist es ein Nutzer“ oder „ist es ein Admin“ geprüft.
Nun wird es komplexer:
- jedes auth_token sollte einen Satz von Scopes tragen – String‑Rechte im Stil resource:action, zum Beispiel catalog:read, orders:write, payments:create;
- Ihr MCP‑Server muss die Übereinstimmung dieser scopes für jede Aktion prüfen, nicht nur „einmal am Eingang“;
- verschiedene Tools und sogar unterschiedliche Operationen innerhalb eines Tools können unterschiedliche Scopes benötigen.
In OAuth‑2.1‑Begriffen ist ChatGPT ein „public client“, MCP ein „resource server“, und Ihr OAuth‑Server weiß, welche Scopes unterstützt werden und was sie bedeuten. MCP‑Ressourcen‑Metadaten deklarieren üblicherweise scopes_supported, damit ChatGPT genau die benötigten Berechtigungen beim Nutzer anfordern kann.
4. Scopes für GiftGenius entwerfen
Nehmen wir unser Lernprojekt GiftGenius und schauen, welche Datendomänen und Aktionen es gibt. Funktional haben wir etwa:
- Anzeigen des Katalogs und der Geschenk‑Detailseiten;
- Empfehlungen basierend auf der Historie;
- Bestellungen erstellen;
- Checkout starten / Gelder abbuchen;
- administratives Bearbeiten des Katalogs.
Anstatt einen allmächtigen giftgenius:full_access zu bauen, legen Sie das besser in sinnvolle Scopes auf.
Namenskonvention: resource:action
Bewährt hat sich die Strategie resource:action, wobei:
- resource die Domäne beschreibt: catalog, recommendations, orders, payments, admin.
- action den Aktionstyp beschreibt: read, write, manchmal konkreter: create, delete, manage.
Beispiel für GiftGenius:
| Scope | Was es erlaubt |
|---|---|
|
Öffentlichen Geschenkkatalog lesen |
|
Empfehlungshistorie des Nutzers lesen |
|
Neue Bestellungen anlegen |
|
Bestellhistorie des Nutzers lesen |
|
Zahlung/Checkout initiieren |
|
Katalog bearbeiten (nur für Admin‑UI/Support) |
Ein normaler GiftGenius‑Nutzer benötigt etwa (durch Leerzeichen getrennt): catalog:read recommendations:read orders:write orders:read payments:create. Dem Administrator fügen wir catalog:admin hinzu.
Wichtig: kein universelles *:* oder admin:all. Je granularer, desto einfacher lässt sich ein konkretes Recht widerrufen, ohne die gesamte Anwendung zu zerlegen.
Scope‑Typen: read vs write vs critical
Sinnvoll ist eine mentale Markierung der Scopes nach Kategorien:
- sichere (read): verändern keinen Zustand, geben höchstens Daten preis;
- verändernde (write): erstellen/ändern Entitäten, erhöhen Zähler, fassen aber kein Geld an und löschen nicht wild;
- kritische (critical): Zahlungen, Account‑Löschung, massenhaftes Löschen von Daten.
Für kritische Rechte kann man erhöhte Kontrollen anwenden:
- sie nur einer minimalen Zahl von Nutzern erteilen;
- bei der Token‑Erteilung in der ChatGPT‑UI eine gesonderte Zustimmung anfordern;
- auf MCP‑Seite eine zusätzliche Bestätigung verlangen (z. B. einmalige PIN – bereits fortgeschrittene Szenarien).
Scopes im Code: RequestContext und requireScope
Auf MCP‑Ebene bietet es sich an, einen einheitlichen Kontexttyp anzulegen:
// mcp/context.ts
export interface RequestContext {
userId: string; // wer
tenantId: string; // innerhalb welcher Organisation
scopes: string[]; // welche Berechtigungen dem Token erteilt wurden
}
// Einfacher Helper zur Rechteprüfung
export function requireScope(
ctx: RequestContext,
needed: string
) {
if (!ctx.scopes.includes(needed)) {
throw new Error(`Missing scope: ${needed}`);
}
}
Es wird angenommen, dass Sie den RequestContext im MCP‑Gateway nach der Token‑Validierung bilden: JWT dekodiert, Signatur/Ablauf geprüft, sub, tenant, scope extrahiert – und anschließend wird dieser Kontext allen Tool‑Aufrufen beigefügt.
Weiter im Tool‑Handler:
// mcp/tools/createOrder.ts
import { requireScope, RequestContext } from "../context";
export async function createOrder(
input: CreateOrderInput,
ctx: RequestContext
) {
requireScope(ctx, "orders:write");
// danach – Logik zum Erstellen der Bestellung
}
Nun gilt: Selbst wenn das Modell unerwartet createOrder dort aufruft, wo Sie es UX‑seitig nicht erwarten, wird das Tool ohne orders:write schlicht nicht ausgeführt.
securitySchemes auf Tool‑Ebene
Die MCP‑Spezifikation erlaubt, pro Tool anzugeben, welche Authorisierungsschemata und Scopes erforderlich sind. In den offiziellen Beispielen werden securitySchemes direkt an die Toolbeschreibung gehängt.
Ein hypothetisches Beispiel:
// mcp/server.ts
server.registerTool(
"createOrder",
{
title: "Create order",
description: "Creates a new order for current user",
inputSchema: {/*...*/},
securitySchemes: [
{ type: "oauth2", scopes: ["orders:write"] }
]
},
async ({ input }, ctx: RequestContext) => {
requireScope(ctx, "orders:write");
// ...
}
);
Hier gibt es zwei Schutzebenen:
- deklarativ: ChatGPT weiß, dass dieses Tool orders:write benötigt, und initiiert bei fehlenden Rechten den Auth‑Flow (oder informiert den Nutzer);
- imperativ: Ihr Code prüft vor der eigentlichen Aktion erneut alles.
Wenn ein Token vorhanden ist, aber die Scopes fehlen, sollte der Server einen Fehler mit WWW-Authenticate zurückgeben: Bearer error="insufficient_scope", scope="orders:write" – und ChatGPT kann beim Nutzer eine Erweiterung der Rechte anfragen (Step‑up Authorization).
Insight
In den offiziellen Beispielen wird securitySchemes verwendet. Diese war in der offiziellen Spezifikation nicht in der Form bestätigt, in der sie in den Beispielen des ChatGPT Apps SDK steht. Daher sollte sie als Erweiterung des offiziellen Protokolls markiert werden – durch das Umbrechen in _meta. Eine funktionierende Variante des obigen Beispiels:
// mcp/server.ts
server.registerTool(
"createOrder",
{
title: "Create order",
description: "Creates a new order for current user",
inputSchema: {/*...*/},
_meta: { // so
securitySchemes: [
{ type: "oauth2", scopes: ["orders:write"] }
]
}
},
async ({ input }, ctx: RequestContext) => {
requireScope(ctx, "orders:write");
// ...
}
);
5. Per‑Tool‑Berechtigungen und „gefährliche“ Tools
Scopes beantworten die Frage „was dieses auth_token grundsätzlich darf“. Im Token gibt es aber auch noch die Liste der Tools, die das Modell nutzen darf. Auch diese müssen sorgfältig entworfen werden.
Klassifizierung der Tools
Wir teilen Tools grob in:
- informationelle (informational / read‑only): lesen Daten, bauen Berichte, rechnen etwas ohne Nebenwirkungen;
- wirksame (consequential): verändern Zustand, buchen Geld ab, löschen etwas.
In der Dokumentation zu ChatGPT Apps wird empfohlen, read‑only‑Tools explizit als sicher zu markieren und bei gefährlichen Tools die Konsequenzen zu beschreiben sowie zusätzliche UX‑Bestätigungen einzubauen.
Das lässt sich umsetzen über:
- Annotationen am Tool (Felder wie readOnlyHint, destructiveHint);
- textuelle Beschreibung: „Dieses Tool löscht Bestellungen unwiderruflich“;
- ein separates Flag confirmation_required, das Ihr App‑Plan nutzt, um einen Bestätigungsschritt in den Dialog einzufügen.
UX‑Bestätigungen für kritische Aktionen
GiftGenius hat z. B. ein Tool chargeCustomer (initiiert eine Abbuchung). Sie möchten selbstverständlich nicht, dass das Modell es ohne Zustimmung des Nutzers ausführt.
So könnte das auf Plan‑Ebene der App aussehen:
// app/plan/tools.ts (Pseudocode)
export const tools = [
{
name: "giftgenius.list_catalog",
description: "Geschenkkatalog anzeigen",
annotations: { readOnlyHint: true }
},
{
name: "giftgenius.create_order",
description: "Bestellung ohne Zahlung erstellen",
annotations: { consequential: true }
},
{
name: "giftgenius.charge_customer",
description: "Geld für die Bestellung abbuchen",
annotations: {
consequential: true,
destructiveHint: true,
confirmationRequired: {
title: "Geld von der Karte abbuchen?",
message: "Es wird eine Zahlung für Bestellung N ausgeführt."
}
}
}
];
Die konkreten Feldnamen hängen von der SDK‑Version ab, die Idee entspricht jedoch den Empfehlungen: read‑only‑Tools als sicher markieren, gefährliche Tools als bestätigungspflichtig mit klarer Beschreibung.
Ihr Widget kann dann reagieren: Schlägt das Modell vor, charge_customer aufzurufen, zeigen Sie dem Nutzer ein modales Fenster mit klarer Formulierung und führen den Tool‑Call erst nach Klick auf „Bestätigen“ wirklich aus.
Beispielkomponente im Widget (vereinfacht):
// widget/components/ConfirmCharge.tsx
export function ConfirmCharge(props: {
orderId: string;
onConfirm: () => void;
}) {
return (
<div>
<p>Geld für Bestellung {props.orderId} abbuchen?</p>
<button onClick={props.onConfirm}>
Ja, Zahlung bestätigen
</button>
</div>
);
}
Das Modell initiiert die Idee „Zeit zu zahlen“, aber den finalen Button drückt der Mensch. Das ist der human‑in‑the‑loop, den Sicherheitsteams so schätzen.
Tools nur für Agents/Backoffice
Ein weiterer häufiger Fall: Es gibt Tools, die nur von Agenten (im Sinne des Agents SDK) oder internen Admin‑UIs genutzt werden dürfen, nicht jedoch von der „normalen“ ChatGPT‑App der Nutzer.
Zum Beispiel rebuildSearchIndex oder syncCatalogFromERP. Diese sollten Sie:
- nicht in die allgemeine Tool‑Liste der normalen App aufnehmen;
- in einem separaten Agent/Orchestrator konfigurieren;
- mit eigenen Scopes und ggf. separatem Auth‑Pfad absichern.
Wenn Sie sie einfach in die Tool‑Liste der App aufnehmen, steigt das Risiko, dass das Modell plötzlich entscheidet: „Ich erstelle den Index jetzt neu – vielleicht hilft das beim Finden eines Geschenks.“
6. Netzwerksegmentierung und Vertrauensgrenzen
Rechte sind nicht nur scopes auf einem Token. Die zweite große Achse ist die Segmentierung von Netzwerk und Services.
Idealbild:
- Es gibt genau einen öffentlichen Einstieg ins Backend – den MCP Gateway/Edge API;
- alles, was PII und Geld speichert, lebt im privaten Netzwerk/VPC und ist nur über dieses Gateway erreichbar;
- Outbound‑Traffic vom Backend ist auf eine Allowlist freigegebener Domains beschränkt (Zahlungsdienst, CRM, eigene Microservices).
Schematisch:
flowchart LR ChatGPT -- HTTPS --> Edge[API Gateway / MCP Endpoint] Edge -- private network --> MCP[MCP server] MCP -- private --> DB[(DB mit PII)] MCP -- private --> SVC[Internal microservices] MCP -- HTTPS (allow) --> Stripe[Payments API]
Wichtige Regeln hier:
- DB und interne Services sind nicht direkt ins Internet exponiert. Direkter Zugriff nur aus dem privaten Netz und nur von Services, die ihn wirklich benötigen.
- Edge/Gateway führt Auth und Rate‑Limiting durch. Genau dort werden Token und Scopes geprüft, zu häufige Anfragen gedrosselt und zentrale Audit‑Logs geschrieben.
- Egress‑Kontrolle. Der MCP‑Server sollte nicht beliebige URLs im Internet aufrufen können (SSRF, Datenabflüsse). Die Liste externer Hosts am besten explizit begrenzen.
In der Praxis – ob Deployment auf Vercel, Render oder in Kubernetes‑Clustern – lassen sich manche Dinge nicht manuell konfigurieren, aber selbst dort kann man trennen:
- separate Projekte/Cluster für dev/staging/prod;
- verschiedene Umgebungsvariablen und Schlüssel je Umgebung;
- einen separaten „Edge“‑Service (HTTP‑Wrapper um MCP) und separate private Services.
Damit haben wir bereits zwei Schutzachsen: Token‑Rechte (scopes) und Netzwerkgrenzen. Ergänzen wir eine dritte – Multi‑Tenancy, wenn eine App mehrere Organisationen bedient.
7. Multi‑Tenant / organisatorischer Kontext
Bisher haben wir implizit mit einem Nutzer gearbeitet. Viele ChatGPT‑Anwendungen sind jedoch Multi‑Tenant: dieselbe App bedient dutzende Firmen. GiftGenius lässt sich leicht zum B2B‑Service für Konzerne ausbauen: jede Abteilung mit eigenen Katalogen, Budgets, Bestellungen.
Was ist ein Tenant und woher bekommt man ihn
Ein Tenant ist typischerweise:
- eine Organisation/Firma (Acme Corp);
- ein Workspace (Arbeitsbereich);
- manchmal ein Projekt oder eine Umgebung.
Die Haupteigenschaft: Daten eines Tenants dürfen für andere Tenants nicht sichtbar sein.
Im Auth‑Flow landet der Tenant üblicherweise in:
- einem Token‑Claim (tenant, org_id);
- einem separaten Parameter in der Autorisierungsanfrage (weniger verlässlich als ein Claim, der vom IdP signiert ist).
Wichtig: Wir vertrauen nur der tenantId aus dem verifizierten Token, nicht aus Tool‑Argumenten. Wenn das Modell {"tenantId": "acme"} generiert, im Token des Nutzers aber tenantId: "globex" steht, ist das als Einbruchsversuch zu werten.
Tenant im Anfragekontext
Fügen wir tenantId in unseren RequestContext ein (haben wir oben bereits getan) und erlauben nicht, ihn aus Eingabedaten zu überschreiben.
Basiskontrolle:
// mcp/tenant.ts
import { RequestContext } from "./context";
export function enforceTenant<TInput>(
input: TInput & { tenantId?: string },
ctx: RequestContext
) {
if (input.tenantId && input.tenantId !== ctx.tenantId) {
throw new Error("Tenant mismatch");
}
return { ...input, tenantId: ctx.tenantId };
}
Weiter im Tool:
// mcp/tools/listOrders.ts
export async function listOrders(
input: { limit?: number; tenantId?: string },
ctx: RequestContext
) {
const safe = enforceTenant(input, ctx);
return db.order.findMany({
where: { tenantId: safe.tenantId },
take: safe.limit ?? 20
});
}
Wir ignorieren den Tenant aus den Argumenten und setzen ihn strikt aus dem Kontext. So führt selbst ein Versuch der LLM oder eines Angreifers, einen fremden Tenant „unterzuschieben“, zu nichts.
Tenant‑Isolation auf DB‑Ebene
Architektonisch gibt es verschiedene Varianten:
- separate DB pro Tenant;
- separate Schemas;
- eine DB mit tenant_id in jeder Tabelle und strenger Filterung.
Unabhängig von der Variante gilt eine goldene Regel: Kein DB‑Query darf ohne Filterung nach tenant_id aus dem Kontext laufen. Besonders wichtig im RAG/Vektor‑Search: Vergisst man den Tenant‑Filter, sucht das Modell womöglich in Dokumenten anderer Organisationen.
8. Wie das mit unserer Next.js/Apps‑SDK‑Anwendung zusammenhängt
Bringen wir nun alles zusammen und schauen, wie Scopes, Tenant und Netzwerkgrenzen in unser Next.js‑Projekt mit dem Apps SDK einfließen. Fügen wir mehr Konkretheit hinzu und betrachten Next.js‑ und Apps‑SDK‑Code.
Wo Scopes und Tenant in unserem Projekt leben
Typischer Aufbau für das Lernprojekt:
- Im Next.js‑Projekt (Apps SDK) gibt es die App/Connector‑Konfiguration und Seiten für OAuth‑Callbacks.
- Im MCP‑Server – Code, der HTTP/SSE‑Anfragen aus ChatGPT annimmt, das Token prüft und das passende Tool aufruft.
Übertragen wir dorthin alles Besprochene:
- In den OAuth‑Einstellungen der MCP‑Ressource deklarieren wir scopes_supported für GiftGenius (catalog:read, orders:write, usw.).
- In der Apps‑SDK‑Konfiguration beschreiben wir die App mit der Auflistung der Tools und ihren Annotationen (read‑only, consequential, Confirmation‑Flows).
- Im MCP‑Server implementieren wir:
- Parsing und Prüfung des Tokens;
- Bildung des RequestContext { userId, tenantId, scopes };
- Helper requireScope, enforceTenant usw.;
- DB‑Aufrufe stets mit tenantId aus dem Kontext.
Beispiel eines „isolierten“ Pfads zur Auftragserstellung
Verfolgen wir einen End‑to‑End‑Szenarioablauf.
- Der Nutzer schreibt: „Lege eine Bestellung für dieses Set mit einem Budget von 50 $ an“.
- Das Modell entscheidet, dass giftgenius.create_order mit Argumenten { productId, budget, ... } aufgerufen werden soll.
- ChatGPT prüft: Gibt es in der App das Tool create_order, welche Scopes und securitySchemes sind dafür hinterlegt? Es versteht, dass orders:write benötigt wird.
- Ist ein Token bereits vorhanden und enthält orders:write, geht die Anfrage weiter; wenn nicht – initiiert ChatGPT eine OAuth‑Autorisierung mit Anfrage des benötigten Scope.
- Das MCP‑Gateway nimmt die Anfrage an, prüft das Token und bildet den RequestContext mit userId=123, tenantId="acme", scopes=["catalog:read","orders:write",...].
- createOrder im MCP:
- führt requireScope(ctx, "orders:write") aus;
- fixiert den Tenant via enforceTenant;
- erstellt die Bestellung ausschließlich innerhalb von tenantId="acme".
- Muss die Bestellung sofort bezahlt werden, initiiert das Modell oder das Backend anschließend charge_customer, wobei:
- das Tool im Plan als confirmationRequired markiert ist;
- das Widget ConfirmCharge rendert und den Nutzer explizit um Bestätigung der Abbuchung bittet.
So erreichen wir Defense‑in‑Depth: zu breite Prompts, Prompt‑Injections oder sogar UX‑Bugs führen nicht zu unkontrollierten Handlungen, weil am unteren Ende der Pyramide strenge Scope‑ und Tenant‑Prüfungen und manuelle Bestätigungen für kritische Aktionen stehen.
9. Typische Fehler beim Entwurf von Rechten und Segmentierung
Fehler №1: Ein einziger fetter Scope wie app:full_access.
Das ist für Demos bequem, im Produktivbetrieb aber gefährlich. Geht ein Token verloren, ist alles verloren. Man kann keine einzelne Operation sperren, ohne den Rest zu zerbrechen. Teilen Sie Rechte nach Domänen und Operationstypen auf (read/write/critical).
Fehler №2: Rechte nur „am Eingang“ prüfen und nicht innerhalb der Tools.
Manchmal heißt es: „Wenn ChatGPT das Token hat, kann es schon alles.“ Und dann wird das Tool createOrder aufgerufen, selbst wenn das konkrete Token kein orders:write hat. Richtig ist: Scopes in jedem Tool prüfen (oder zumindest zentral über ein Middleware für alle verändernden Operationen).
Fehler №3: Gefährliche Tools nicht markieren und keine Bestätigungen verlangen.
Wenn ein Tool Geld abbucht, Daten löscht oder Zugriffe ändert, darf es für das Modell nicht so aussehen wie listCatalog. Fehlende klare Annotationen und UX‑Bestätigungen erhöhen die Chance, dass das Modell es „einfach so, weil logisch“ aufruft. Trennen Sie mindestens read‑only von destruktiven Tools und markieren Sie letztere explizit.
Fehler №4: Vertrauen in tenantId aus Tool‑Argumenten.
Sehr häufiger Anti‑Pattern: ein Tool getOrders({ tenantId }), wobei tenantId vom Modell kommt. Nutzt man diesen Wert direkt, kann ein Nutzer aus tenantA die Daten von tenantB erhalten, indem er eine andere ID angibt. Der Tenant muss aus dem verifizierten Token kommen und allen DB‑ und externen Service‑Anfragen aufgezwungen werden; Nutzereingaben werden ignoriert oder auf Übereinstimmung validiert.
Fehler №5: MCP/DB sind direkt aus dem Internet erreichbar.
In einfachen Prototypen hängen MCP‑Server und DB manchmal offen im Internet auf HTTP/5432. In Prod ist das tabu: Sämtlicher Zugriff muss über ein sicheres Gateway/Proxy laufen, und die DB in einem privaten Netz leben. Andernfalls ist jeder verwundbare Endpoint oder ein löchriges Webhook ein direkter Weg zu den Daten.
Fehler №6: Dieselben Scopes/Secrets in dev und prod verwenden.
Ein Lieblingsweg, sich während einer lokalen Demo die Prod‑Daten zu löschen. Für jede Umgebung braucht es eigene Keys, Scopes und DBs. Selbst wenn jemand Zugriff auf ein dev‑Token erhält, kann er Prod‑Daten nicht schädigen.
Fehler №7: „Dem Modell nicht widersprechen wollen“.
Entwickler fürchten manchmal: „Wenn ich häufig insufficient_scope oder forbidden zurückgebe, arbeitet das Modell schlechter.“ In der Praxis ist das normales und erwartetes Verhalten: Das Modell lernt, welche Aktionen verfügbar sind und welche zusätzliche Rechte oder Bestätigungen erfordern. Schlimmer ist, wenn es „erfolgreich“ etwas tut, was es nicht darf – etwa eine zweite Zahlung auszuführen.
GO TO FULL VERSION