mcpclerk
mcpclerk
Ein Governance-Proxy für MCP-Server: Er sitzt vor jedem MCP-Server, erzwingt eine Pro-Tool-Allowlist, hält Schreibwerkzeuge zur menschlichen Genehmigung zurück, wendet Pro-Tool-Kontingente an, schwärzt geheimnisaussehende Argumente und schreibt ein hash-verkettetes Audit-Log jedes Aufrufs.
Ein KI-Agent auf MCP-Servern kann jedes von ihnen bereitgestellte Werkzeug beliebig oft und mit beliebigen Argumenten aufrufen, und nichts zeichnet auf, was er getan hat, in einer Form, die jemand prüfen kann. In einem Unternehmen lautet die Frage nicht „Kann der Agent die Aufgabe erledigen?“, sondern was darf er tun, wer hat die gefährlichen Teile genehmigt, und was hat er tatsächlich getan?
mcpclerk beantwortet diese drei mit Code. Es ist selbst ein MCP-Server: Der Agent verbindet sich mit ihm, er verbindet sich mit den echten Servern und stellt deren Werkzeuge als upstream.tool erneut bereit. Jeder Aufruf durchläuft eine Pipeline: Allowlist, Kontingent, Schwärzung, Genehmigung, Weiterleitung, Protokollierung. Ein nicht gelistetes Werkzeug wird verweigert. Ein Schreibwerkzeug wartet auf eine menschliche Antwort y. Ablehnungen kommen als lesbare Fehler zurück. Das Log ist ein append-only JSON Lines, jeder Eintrag mit dem vorherigen gehasht, sodass eine Änderung an beliebiger Stelle die Kette bricht.
Die Demo umschließt den offiziellen Dateisystem-Server: Ein Lesevorgang wird durchgelassen, ein Schreibvorgang wird zurückgehalten und genehmigt, ein Verschieben wird verweigert, die vierte Suche innerhalb einer Minute wird wegen Kontingent verweigert, und das Log verifiziert. 49 Tests beweisen jede Kontrolle gegen einen Fake-Upstream, einschließlich der Tatsache, dass der Upstream immer die ungeschwärzten Argumente erhält.

Installation
pip install mcpclerk # Python 3.10+ (the MCP SDK requires it); pulls in mcp and pyyaml
mcpclerk --versionAus dem Quellcode: git clone https://github.com/hishamalward/mcpclerk && cd mcpclerk && pip install -e ".[dev]" && pytest.
Related MCP server: Agentrim MCP
Fünf Minuten
Schreiben Sie eine Richtlinie. Dies ist die aus der Demo (
examples/policy.filesystem.yaml):version: 1 defaults: unlisted: deny # a tool not named here is an unreviewed tool approval_timeout_s: 120 # a call nobody answers in time is refused, and logged as such upstreams: fs: transport: stdio command: npx args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp/mcpclerk-demo-sandbox"] tools: "read_*": allow list_directory: allow search_files: { decision: allow, quota: { per_minute: 3 } } write_file: approve edit_file: approve create_directory: approve move_file: deny # the filesystem server has no delete; move is its destructive opSehen Sie, was der Upstream bietet und was Ihre Richtlinie damit macht. Die eigenen Anmerkungen des Servers werden neben Ihrer Entscheidung angezeigt, so erkennen Sie, dass Sie ein destruktives Werkzeug erlaubt haben:
$ mcpclerk tools --policy examples/policy.filesystem.yaml tool decision rule read_only destructive quota fs.read_file allow glob:read_* True None -/- fs.write_file approve exact False True -/- fs.move_file deny exact False True -/- fs.search_files allow exact True None -/3Registrieren Sie den Proxy dort, wo Ihr Agent nach MCP-Servern sucht. Für Claude Code,
examples/.mcp.json:{ "mcpServers": { "fs-governed": { "command": "mcpclerk", "args": ["serve", "--policy", "examples/policy.filesystem.yaml"] } } }Warten Sie in einem zweiten Terminal auf Genehmigungen:
mcpclerk approve. Wenn der Agentfs.write_fileaufruft, sehen Sie den Aufruf mit bereits maskierten Geheimnissen und antworten mityodern.Danach:
mcpclerk verify audit/mcpclerk.jsonlundmcpclerk report audit/mcpclerk.jsonl.
Die fünf Kontrollen
Kontrolle | Was sie tut | Was sie verhindert | Was sie nicht verhindern kann | Belegt durch |
Allowlist |
| Dass der Agent ein Werkzeug verwendet, das niemand überprüft hat. | Eine schlechte Entscheidung in der Richtlinie selbst. |
|
Genehmigung |
| Ein unbeaufsichtigter Schreibvorgang. | Ein Mensch, der ohne zu lesen genehmigt. |
|
Kontingente |
| Außer Kontrolle geratene Schleifen; ein billiges Werkzeug, das durch Menge teuer wird. | Verteilen einer Schleife über viele Werkzeuge oder über Proxy-Neustarts ( |
|
Schwärzung | Schlüsselregeln ( | Dass Geheimnisse im Log oder auf dem Bildschirm eines Genehmigers landen. | Ein Geheimnis, das wie nichts auf der Liste geformt ist. Erweitern Sie |
|
Audit-Log | Ein JSON-Lines-Eintrag pro Aufruf mit Zeitstempel, Upstream, Werkzeug, geschwärzten Argumenten, Entscheidung, wer genehmigt hat, Ergebnis, Latenz und | Stilles Bearbeiten, Löschen oder Umordnen von Einträgen im Nachhinein; Abschneiden eines abgeschlossenen Laufs ( | Ein Angreifer, der die gesamte Kette von Anfang an neu schreibt (dies ist eine Kette, keine Signatur; siehe unten). Abschneiden eines Laufs, der mitten in der Ausführung abgebrochen wurde. |
|
Ergebnisse werden nicht protokolliert, nur ihre Größe und Inhaltstypen. Das Log ist eine Prüfung von Entscheidungen, keine Kopie der Daten; das Speichern von Ergebnissen würde es zu einem zweiten Ort machen, an dem Geheimnisse lecken könnten.
Wie ein Aufruf abläuft
agent ──tools/call fs.write_file──▶ mcpclerk ──▶ [namespace] ──▶ [allowlist] ──▶ [quota] ──▶ [redact for log]
│ │ │
refused-unknown refused-denied refused-quota
│
┌── decision = approve ──▶ [hold: approvals/<id>.json] ──▶ y ─┐
│ │ n / timeout │
│ refused-by-human / refused-timeout │
└── decision = allow ────────────────────────────────────────┤
▼
[forward with ORIGINAL args] ──▶ upstream ──▶ result
│
[append log entry, hash-chained]Jeder Pfad, einschließlich jeder Ablehnung, endet in einem Logeintrag. Ablehnungen werden dem Agenten als normales Werkzeugergebnis mit is_error: true und einer einzeiligen Begründung zurückgegeben: mcpclerk: refused-quota fs.search_files: 3/min exhausted; retry after 60s.
Genehmigung im Detail
Der Proxy wird normalerweise vom MCP-Client des Agenten gestartet, und das MCP-SDK startet Stdio-Server in einer neuen Sitzung, sodass der Proxy normalerweise kein eigenes Terminal hat. Deshalb ist der Mechanismus eine Datei-Warteschlange und die Terminal-Eingabeaufforderung ein Client davon:
approvals/<id>.jsonwird für jeden zurückgehaltenen Aufruf geschrieben, mit den geschwärzten Argumenten,requested_at,expires_atund"approved": null.mcpclerk approve(in einem beliebigen Terminal auf derselben Maschine) zeigt ausstehende Anfragen und schreibt Ihre Antwort.--oncebeantwortet eine und beendet sich; ohne das beobachtet es weiter.Das manuelle Bearbeiten der Datei auf
"approved": truefunktioniert ebenfalls, was ein Headless-Job oder ein Skript tut.Falls der Proxy doch ein steuerndes Terminal hat (Sie haben ihn von Hand gestartet), fragt er auch dort nach. Beide Pfade laufen parallel; die erste Antwort gewinnt.
Keine Antwort innerhalb von
approval_timeout_sist eine Ablehnung, protokolliert alsrefused-timeout. Schweigen bei einem Schreibvorgang bedeutet Nein.serve --approve-sessiongenehmigt automatisch jeden Approve-Klassen-Aufruf für diesen Prozess. Es gibt beim Start eine Warnung aus, derrun-start-Eintrag zeichnet es auf, jeder betroffene Eintrag sagtapproved_by: session-flag, undreportschreit darüber. Es kann nicht in der Richtliniendatei festgelegt werden; es ist eine Handlung pro Aufruf durch denjenigen, der den Prozess startet.
Das Audit-Log
{"kind":"call","ts":"2026-08-24T01:14:40.822Z","run_id":"20260824T011440Z-3e1c","id":"20260824T011440Z-0002",
"name":"fs.write_file","upstream":"fs","tool":"write_file","rule":"exact",
"args":{"content":"# notes\n[REDACTED:kv-secret]\n","path":"/tmp/mcpclerk-demo-sandbox/notes.md"},
"decision":"approved","approved_by":"file","held_ms":253.7,"outcome":"ok","is_error":false,
"latency_ms":7.7,"content_bytes":57,"content_types":["text"],
"seq":4,"prev_hash":"5c0e…","hash":"b41a…"}decisionist eines vonallowed,approved,refused-denied,refused-unknown,refused-quota,refused-timeout,refused-by-human.latency_msist nur die Upstream-Zeit; die Denkzeit des Menschen istheld_ms, sodass die p95-Latenz inreportdas Werkzeug bedeutet, nicht die Person.Ereigniseinträge (
run-startmit der SHA-256 der Richtlinie und den Flags,discovermit exponierten/versteckten Zählungen,run-endmit der Eintragszahl) teilen sich dieselbe Kette.verifybeendet sich mit 0 undOK n entries, chain intactoder mit 1 undFAIL at line N: <what>. Probieren Sie es aus:sed -i '' 's/allowed/approved/' examples/audit.demo.jsonl && mcpclerk verify examples/audit.demo.jsonl.
Das Beispiel-Log in examples/audit.demo.jsonl ist die echte Ausgabe des Demo-Laufs. Es ist konstruktionsbedingt sicher zu veröffentlichen: Die Schwärzungstests beweisen es, und die Demo schreibt einen gefälschten API-Schlüssel in eine Datei, genau damit das Log [REDACTED:kv-secret] zeigen kann, wo er gewesen wäre.
CLI
mcpclerk serve --policy policy.yaml [--log audit/mcpclerk.jsonl] [--approvals approvals] [--approve-session] [--no-tty]
mcpclerk approve [--approvals approvals] [--once] [--wait 60]
mcpclerk tools --policy policy.yaml [--json]
mcpclerk verify audit/mcpclerk.jsonl
mcpclerk report audit/mcpclerk.jsonl [--json]Exit-Codes: 0 ok, 1 Verifizierung fehlgeschlagen oder Richtlinie ungültig, 2 Verwendung. Die Richtlinie wird beim Start validiert, und jedes Problem (unbekannter Schlüssel, schlechte Entscheidung, nicht gesetzte ${ENV_VAR}, ein Stdio-Upstream ohne command) stoppt den Proxy, bevor er irgendetwas bedient.
Richtlinienreferenz
version: 1
namespace_separator: "." # "__" for clients that reject dots in tool names
defaults:
unlisted: deny # allow | deny | approve
approval_timeout_s: 120
quota: { per_run: null, per_minute: null }
redaction:
extend: ['(?i)my[-_ ]?internal[-_ ]?token\s*[:=]\s*\S+'] # value regexes, added to the built-ins
extend_keys: [client_secret] # key names, added to the built-ins
replace_builtin: false # true: only your patterns (warned about)
upstreams:
<name>: # [a-z0-9_-]+ ; becomes the prefix in <name>.<tool>
transport: stdio | http
command: ... args: [...] env: { KEY: "${FROM_PROXY_ENV}" } cwd: ... # stdio
url: https://... # http
tools:
<tool or glob>: allow | deny | approve
<tool>: { decision: approve, quota: { per_run: 10, per_minute: 3 }, approval_timeout_s: 60 }Vorherige Arbeiten und was dies stattdessen ist
Gateways für MCP existieren und tun mehr als dies: Lasso Security's mcp-gateway, IBM's mcp-context-forge und Docker's MCP Gateway bringen Registries, Multi-Tenant-Auth, Plugin-Pipelines und Beobachtbarkeit. mcpclerk beansprucht keine Neuheit. Es beansprucht Kleinheit und Verifizierbarkeit: ein zweckgebundener, lesbarer, lokaler Proxy, dessen gesamte Oberfläche die fünf obigen Kontrollen und ein überprüfbares Log ist. Es umfasst etwa 1.000 Zeilen Python, die man an einem Nachmittag lesen kann, mit einer Abhängigkeit über das MCP-SDK hinaus (ein YAML-Parser).
Was es (noch) nicht tut
Identität und benutzerbezogene Richtlinien. Es wird ein Bediener angenommen; das Protokoll zeichnet auf, dass ein Mensch genehmigt hat, nicht welcher Mensch.
Eine Weboberfläche oder entfernte Genehmigungskanäle (Slack, E-Mail).
mcpclerk approveist ein lokales Terminal.Richtlinienvererbung oder -vorlagen über Upstreams hinweg.
Ressourcen und Prompts. v0.1 proxyt nur Tools;
resources/listundprompts/listsind leer.HTTP-Upstreams, die Anforderungsheader benötigen. Der HTTP-Transport des SDK akzeptiert in dieser Version keine; eine Richtlinie, die
headerssetzt, schlägt laut fehl, anstatt stillschweigend nichts zu senden.Windows: Die Dateiwarteschlange und
mcpclerk approvefunktionieren; die prozessinterne Terminaleingabeaufforderung nicht (kein/dev/tty). CI führt Windows nach bestem Bemühen aus.
Bedrohungsmodell, ehrlich
Was ein Angreifer mit dem Sitz des Agenten zuerst versuchen würde, ist, ein Tool mit einem Namen aufzurufen, das in der Liste verborgen ist. Das wird verweigert und protokolliert (refused-unknown oder refused-denied). Was dies nicht verhindert: ein Tool, das erlaubt ist, für etwas Schädliches verwendet wird (die Richtlinie ist Ihr Urteil, mcpclerk setzt sie durch), ein Genehmiger, der blind absegnet, und jeder mit Schreibzugriff auf die Protokolldatei, der die gesamte Kette ab dem ersten Eintrag neu schreibt. Die Kette schützt vor stillen Änderungen, was die realistische Bedrohung ist; Signaturen oder ein externer Anker (Veröffentlichung des täglichen Kopf-Hashs an einem Ort, den Sie nicht kontrollieren) wären der nächste Schritt und sind in v0.1 nicht enthalten.
Entwicklung
pip install -e ".[dev]"
pytest -q # 49 tests, all in-process, no network, no subprocesses
python examples/demo_driver.py --approve-via-file # the demo against the real filesystem server (needs npx)
vhs examples/demo.tape # re-record the GIFTests verwenden den In-Memory-Transport des MCP SDK auf beiden Seiten: Client(proxy) → proxy → Client(fake_upstream). Der Fake-Upstream (tests/fake_upstream.py) hat ein secret_sink-Tool, das genau das zurückgibt, was es empfangen hat. So beweist die Testsuite, dass der Upstream unredigierte Argumente sieht, während das Protokoll dies nicht tut.
Verwandt: toilscan (derselbe Schreibsicherheitsinstinkt, angewendet auf ein Entwicklerwerkzeug), agent-slots (Laufzeitisolierung für parallele Agenten) und agentkeel (die Prozessseite: Tore und Auswirkungsradius für von Agenten geschriebenen Code; in Arbeit).
Für den, der das als Nächstes übernimmt: docs/learning/how-it-works.html ist die Tour (der Code in Aufrufreihenfolge, die Steuerungen, die Interviewantworten); docs/spec.md ist der Vertrag.
Lizenz
MIT.
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
- AlicenseBqualityCmaintenanceSecurity gateway that wraps any MCP server with per-tool policies, approval gates, and optional Ed25519-signed decision receipts. Shadow mode logs every tool call without blocking; enforce mode applies block, rate-limit, and minimum-tier rules. Receipts are independently verifiable offline with no accounts needed.54699MIT
- AlicenseNot gradedqualityBmaintenanceA least-privilege enforcement proxy for MCP servers. It sits between MCP clients and upstream servers, enforcing tool policies, hiding denied tools, requiring human approval for risky actions, and providing a structured audit trail.MIT
- AlicenseAqualityAmaintenanceAn MCP proxy that enforces policy on every tool call, blocking or flagging actions before they reach downstream MCP servers.1249MIT
- AlicenseNot gradedqualityAmaintenanceAn authorizing reverse proxy for MCP servers that enforces per-call policy rules on tool arguments with audit logging, dry-run, and rate limiting.Apache 2.0
Related MCP Connectors
Remote MCP for A2A caller identity, scope policy, verdict receipts, and audit history.
Runtime permission, approval, and audit layer for AI agent tool execution.
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
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/hishamalward/mcpclerk'
If you have feedback or need assistance with the MCP directory API, please join our Discord server