mcp-capability-guard
mcp-capability-guard
Die meisten MCP-Server geben dem Modell eine geladene Waffe mit einem gemeinsamen Bearer-Token in die Hand: eine Anmeldedaten, jedes Tool, jeder Aufruf. Dieser Server zwingt das Modell, für jede Kugel um Erlaubnis zu bitten.
Es ist ein kleiner, vollständiger MCP-Server über einem fiktiven In-Memory-CRM (Larkspur Supply Co., sieben erfundene Kontakte), der die Schreibautorisierung per Capability-Token demonstriert – ein Muster, das aus einem Produktions-CRM-Agenten extrahiert wurde, den ich gegen ein echtes Adressbuch mit über 12.000 Kontakten betreibe. Die Daten hier sind Fiktion; die Durchsetzung ist der Teil, der ausgeliefert wird.
Das Design in fünf Schichten
Abgestufte Tool-Oberfläche. Lesezugriffe (
list_contacts,get_contact) sind frei. Schreibvorgänge existieren nicht als einzelne Tools – es gibt keinadd_note-Tool und keindelete_contact-Tool. Jede Mutation läuft über genau zwei Aufrufe:propose_write, dannexecute_write.Capability-Tokens (das Herzstück).
propose_writeerstellt ein einmalig verwendbares, mit TTL versehenes Warrant, das an genau eine Mutation gebunden ist – das Token enthält die Mutation, es verweist nicht auf eine, sodass es keine Lookup-Tabelle gibt, die vergiftet werden kann, und keine ID, die neu ausgerichtet werden kann.execute_writepräsentiert das Token zusammen mit der Mutation, und der Guard prüft die Gleichheit Feld für Feld. Die Präsentation eines Warrants mit einer anderen Mutation schlägt nicht nur fehl – es verbrennt das Token und nimmt den legitimen Schreibvorgang des Angreifers mit.Menschliche Bestätigung für die destruktive Stufe.
change_stage,remove_tagunddelete_contacterfordern zusätzlich das explizite Ja des Bedieners über die MCP-Formularabfrage, in einer Eingabeaufforderung, die die Operation, den Kontakt und die Nutzlast in einem Satz nennt. Die Abfrage läuft vor der Konsultation des Guards, sodass eine Ablehnung niemals das Warrant ausgibt – und ein Client ohne Abfragekanal erhält destruktive Schreibvorgänge verweigert, nicht stillschweigend ausgeführt. Fail-Closed, in beide Richtungen.Eine Basis, die die darüberliegenden Schichten nicht überschreiben können. Kontakte in der Phase
Closed-Lost-DNC(Do-Not-Contact, rechtliche Sperre) verweigern jeden Schreibvorgang innerhalb des Stores selbst, der nichts von Tokens oder MCP weiß. Ein vollständig genehmigter Ablauf – gültiges Warrant, passende Mutation, bestätigter Mensch – endet dort trotzdem. Das macht dies zu einer Verteidigung in der Tiefe und nicht zu einem einzelnen Tor mit drei Schildern.Ein append-only Audit-Log, das keine Warrants leaken kann. Jeder Vorschlag, jede Bestätigung, jede Ausführung und jede Verweigerung wird protokolliert. Token-IDs gelangen nur als 8-Zeichen-Fingerabdrücke in das Log – und das ist eine Kompilierzeit-Garantie: Das Fingerabdruckfeld enthält einen gebrandeten TypeScript-Typ, den nur die kürzende Funktion erzeugen kann. Freitext wird ebenfalls nach Wert bereinigt, da die eigenen Verweigerungsmeldungen des Guards das Token benennen, das sie verweigert haben. (Dies ist dieselbe Redact-by-Value-Disziplin wie bei meinem webhook-guard – dort für HTTP-Anmeldedaten, hier für lebende Warrants.)
read_auditist standardmäßig verweigernd: Wenn der Server nicht mitexposeAudit: truegebaut wird, ist das Tool überhaupt nicht registriert.
Related MCP server: tenant-scoped-crm
In Aktion sehen
npm install
npm run demoDie Demo verbindet den echten Server mit einem skriptbasierten Client über einen In-Memory-MCP-Transport und erzählt acht Schritte: zwei Schreibvorgänge, die landen (einer umkehrbar, einer destruktiv und bestätigt), dann fünf Angriffe – Replay, Bait-and-Switch, eine abgelehnte Bestätigung, eine Zielverschiebung und ein vollständig genehmigter Schreibvorgang gegen den eingefrorenen Datensatz – jeder trifft auf seine typisierte Verweigerung, während der Store byte-identisch bleibt. Es endet mit dem Lesen des Audit-Pfads und der Prüfung, dass keine vollständige Token-ID darin auftaucht. Die Demo prüft jede Erwartung inline und beendet sich bei jedem Fehlschlag mit einem Nicht-Null-Exit, sodass sie auch als Smoke-Test dient und bei jedem Push in CI läuft.
npm test # 158 offline tests
npm run typecheck # strict TypeScript, no emitAlles ist offline: keine API-Schlüssel, kein Netzwerk, keine Umgebungsvariablen, nichts zu konfigurieren. Deshalb führt CI die gesamte Suite, einschließlich der Demo, bei jedem Push ohne Geheimnisse aus.
Die Beweise liegen in den Test-Suiten
Zwei Suiten existieren speziell, um die obigen Behauptungen ehrlich zu halten:
test/structural.test.tsliest den Quellcode als Text und verankert die Architektur:src/tools.tsist das einzige Modul, das das MCP-SDK importiert; der Store weiß nichts darüber; die Guard- und Audit-Module importieren nur, was ihre Header behaupten; das Prägen von Tokens ist auf den Guard beschränkt; die ZeichenfolgetokenIderscheint nie insrc/audit.ts. Wenn eine Refaktorierung SDK-Code still in den Store verschiebt, schlägt diese Suite fehl, bevor sich irgendein Verhalten ändert.test/adversarial.test.tsspielt ein feindliches Modell gegen den vollständig verdrahteten Server: Skip-the-Propose, Replay, Bait-and-Switch mit Verbrennungsverifikation, Neuausrichtung eines Warrants auf einen anderen Kontakt, ein Vollgenehmigungsangriff auf den eingefrorenen Datensatz, ein abgelaufenes Warrant über eine injizierte Uhr, eine Bestätigungsumgehung und eine Audit-Integritätsprüfung mit vom Angreifer gewählten Token-IDs. Jeder Angriff muss auf seine exakte typisierte Verweigerung treffen, und nach allen muss der Store unverändert sein.
Die restlichen ~140 Tests decken Store, Guard, Audit und Tool-Oberfläche einzeln ab, einschließlich der Ordnungsinvariante, dass die Bestätigung vor der Ausgabe des Warrants läuft.
Versionierung und Umfang
Gebaut auf @modelcontextprotocol/sdk 1.30.0, das auf MCP-Revision 2025-11-25 abzielt. Die Revision 2026-07-28 macht servergeprägte Handles, die als gewöhnliche Tool-Argumente übergeben werden, zum kanonischen Mechanismus für zustandsübergreifende Aufrufe (SEP-2567) – das Capability-Token in diesem Repository ist genau dieses Muster, verwendet als Autorisierungsprimitive, sodass das Design unverändert in das zustandslose Protokoll übergeht.
Zwei Laufzeitabhängigkeiten: das SDK selbst und zod, das die Peer-Dependency-Schemasprache des SDKs ist – Tool-Eingabeschemas sind per SDK-Design Zod-Schemas, also ist es keine zusätzliche Abhängigkeit, sondern eher die andere Hälfte des SDKs. Nichts anderes gelangt in den Baum. Die Store-, Guard- und Audit-Module sind reines TypeScript mit null Importen außer node:crypto und den Typen der jeweils anderen, was es ermöglicht, 158 Tests offline in unter einer halben Sekunde auszuführen.
Was dies nicht ist. Dieses Repository implementiert kein OAuth und keine Ressourcen-Server-Rolle des MCP-Autorisierungsspezifikation. Diese lösen ein anderes Problem: den Nachweis, wer der Client ist an der Transportgrenze. Capability-Tokens regeln, was eine authentifizierte Sitzung tun darf, einen Schreibvorgang nach dem anderen – die beiden ergänzen sich, statt zu konkurrieren, und ihre Vermischung führt dazu, dass Server mit einem einzigen Bearer-Token enden, das alles autorisiert. Transportidentität ist hier bewusst ausgeklammert, damit das Autorisierungsmuster lesbar bleibt.
Einschränkungen, klar benannt
Das CRM ist fiktiv und im Speicher. Persistenz, Nebenläufigkeit und Mehrbenutzersitzungen sind echte Probleme, die diese Demo nicht hat.
Tokens leben im Serverspeicher; ein Neustart vergisst sie. In der Produktion läuft dasselbe Muster gegen einen dauerhaften Speicher mit derselben Einmalverwendungssemantik.
Die Abfragebestätigung ist nur so gut wie die Darstellung durch den Client. Ein Client, der dem Benutzer ein nacktes „Erlauben?" statt des Satzes des Servers zeigt, schwächt die Garantie – was ein Argument dafür ist, den vollständigen Satz in die Anfrage zu setzen, wie dieser Server es tut, und nicht dafür, die Abfrage zu überspringen.
Die Notiz-Zeitstempel des Stores verwenden die Wanduhr, sodass eine Zeile der Demo-Ausgabe zwischen Läufen variiert. Der Guard und das Audit-Log verwenden injizierte Uhren und sind deterministisch.
Anpassung
Das Muster lässt sich auf jeden MCP-Server übertragen, dessen Schreibvorgänge Konsequenzen haben: Ersetzen Sie den Store durch Ihr System, behalten Sie die Propose/Execute-Trennung bei, legen Sie Ihre eigenen Stufen fest und halten Sie die Basisregel in der Datenschicht statt in der Tool-Schicht. Die Guard- und Audit-Module importieren nichts von MCP und können als Ganzes herausgelöst werden.
MIT-Lizenz.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityAmaintenanceSecurity-enforcing MCP proxy that sits between an AI agent and any number of downstream MCP servers, intercepting every tool call through a capability-token policy gateway that can allow, deny, or escalate to human approval before the call reaches any real tool. It also exposes built-in operator tools for approval workflows, audit trail queries, token management, voice/HUD output, and hierarchical2112Apache 2.0
- AlicenseNot gradedqualityCmaintenanceA reference MCP server demonstrating safe agent access to multi-tenant CRM data with tenant isolation enforced in the data layer, role-based permissions, and human confirmation on writes.MIT
- FlicenseNot gradedqualityCmaintenanceA secure MCP server for CRM operations (contacts and deals) with Auth0 OIDC authentication, role-based access control (sales-rep read-only vs sales-manager full access), and on-behalf-of token exchange.
- AlicenseBqualityAmaintenanceA secure MCP server enabling tool calls (kb_search, read_doc, publish_report) through a zero-trust CapabilityBroker with OWASP LLM Top-10 guardrails and human-in-the-loop approval.3Apache 2.0
Related MCP Connectors
An authenticated remote MCP server for user-owned devices and one-shot capability invocation.
Personal MCP server for humans who create. Proof of authorship, license control.
Viridis Verified: wrap any MCP server with tamper-evident delivery receipts + metered fees.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/adamabdo-xynora/mcp-capability-guard'
If you have feedback or need assistance with the MCP directory API, please join our Discord server