Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Beschreibung vom Entwickler (englisches Original)
An MCP server whose confirmation cannot be replayed against a different call.
Diese drei werden nie zu einer Punktzahl zusammengefasst: Meinungen, Messungen und Beliebtheit sind verschiedene Dinge.
Für diesen Server haben wir noch keine Zusammenfassung in einfacher Sprache geschrieben. Unten stehen die Fakten, die wir aus der Registry gelesen haben.
Wähle die KI-App, die du nutzt, und kopiere die Einstellungen.
Du brauchst
Welche App nutzt du?
Wähle oben deine App. Wir merken sie uns, damit der Button beim nächsten Mal „In … installieren“ anzeigt.
Öffne Claude Desktop → Settings → Developer → Edit Config und füge dies in claude_desktop_config.json ein
{
"mcpServers": {
"confirm": {
"command": "uvx",
"args": [
"mcp-confirm",
"--root",
"your-value"
]
}
}
}Führe das in deinem Terminal aus
claude mcp add confirm -- uvx mcp-confirm --root your-valueDieser Server braucht Werte in seiner Befehlszeile, also kopier die Einstellungen und trag sie ein.
In .cursor/mcp.json in deinem Projekt oder in ~/.cursor/mcp.json einfügen
{
"mcpServers": {
"confirm": {
"command": "uvx",
"args": [
"mcp-confirm",
"--root",
"your-value"
]
}
}
}Dein Browser fragt, ob er die App öffnen darf, dann zeigt die App die Einstellungen und bittet dich um Bestätigung. Schlüsselwerte bleiben leer, damit du sie selbst einträgst.
Dieser Server braucht Werte in seiner Befehlszeile, also kopier die Einstellungen und trag sie ein.
In .vscode/mcp.json in deinem Projekt einfügen
{
"servers": {
"confirm": {
"type": "stdio",
"command": "uvx",
"args": [
"mcp-confirm",
"--root",
"your-value"
]
}
}
}Dein Browser fragt, ob er die App öffnen darf, dann zeigt die App die Einstellungen und bittet dich um Bestätigung. Schlüsselwerte bleiben leer, damit du sie selbst einträgst.
Dieser Server läuft auf deinem Computer, und ChatGPT kann sich nur mit Servern im Internet verbinden. Wähle eine andere App.
Deine Auswahl bleibt in einem Cookie auf diesem Gerät; kein Konto nötig.
Diese Einstellungen werden aus dem Registry-Eintrag des Entwicklers erzeugt. Wenn in der README etwas anderes steht, folge der README.
Läuft auf deinem Computer; die Tool-Liste erscheint nach der Installation in deiner KI-App.
Wir prüfen Informationen, die jeder sehen kann; den Code haben wir nicht gelesen. Checks, die nicht zutreffen, werden nicht mitgezählt. · Geprüft am 7. Nov. 2026
Der Registry-Name wurde mit dem GitHub-Konto les-k bestätigt, dem das Repo gehört
Dieses Repo haben wir noch nicht von GitHub gelesen
Dieses Repo haben wir noch nicht von GitHub gelesen
Dieser Server läuft auf deinem Computer; es gibt keinen Endpunkt im Internet
Läuft auf deinem Computer und nutzt stattdessen lokale Einstellungen
Läuft auf deinem Computer; Tool-Listen können wir nur von Endpunkten im Internet lesen
Verglichen mit allen aktiven Servern dieser Kategorie in der Registry. Sterne zählen nur, wenn dem Herausgeber das Repo gehört.
Er hat 1 von 1 zutreffenden Basischecks bestanden. Den Code haben wir nicht gelesen. Bevor du einen Schlüssel oder Token hinzufügst, sieh nach, welche Zugriffe der Server verlangt, und nutze einen Schlüssel, der nur die Berechtigungen hat, die du brauchst.
Die Registry nennt keinen erforderlichen Schlüssel, manche Server bitten dich aber bei der ersten Nutzung, dich anzumelden.
Er läuft auf deinem Computer. Deine KI-App startet ihn bei Bedarf, und die Daten laufen nicht über die Server des Entwicklers (außer der Server ruft selbst einen Onlinedienst auf).
Das GitHub-Repo wurde zuletzt – geändert, und die neueste Version (0.2.1) kam vor 36 Tagen in die Registry.
Apps, die MCP unterstützen, etwa Claude Desktop, Claude Code, Cursor und VS Code. Außerdem brauchst du Python (uv) auf deinem Computer.
In derselben Kategorie: Spec Driven Development, Remote Desktop Commander, arr-mcp
Server derselben Kategorie von anderen Entwicklern, sortiert nach Sternen.
So liest du eine Karte:★ GitHub-SterneiDrei Säulen: Bewertungen · Checks · NutzungiAktualisiert = neueste Version in der Registry veröffentlichti
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
One server, 40 tools, the whole media stack: *arrs, Jellyfin, Plex, Seerr, Cleanuparr, downloaders
Unverändert aus dem Repo des Entwicklers übernommen. PopNx MCP hat den Inhalt weder geprüft noch empfiehlt es ihn. HTML, Bilder und Skripte wurden entfernt. Links führen von dieser Website weg.
In plain terms: when an AI asks "are you sure?", the MCP SDK already stops
that approval being reused for a *different* action. It does not stop the
same approval being used *twice*. This closes that gap, and two others the SDK
leaves open.
The 2026-07-28 MCP specification added Multi Round-Trip Requests, so a tool can pause mid-call and ask the user to confirm. The approval travels back through the client as an opaque requestState, which the spec says servers MUST treat as attacker-controlled.
The Python SDK does this for you, by default, on every `MCPServer`. RequestStateBoundary is appended to the middleware chain unconditionally — with an ephemeral key if you supply none. It seals the state under AES-256-GCM and binds it to the method, the target, a digest of the call's arguments, the audience, and the authenticated principal, with a TTL.
So the attack everyone reaches for first — *approve deleting cache.txt, then replay that approval against thesis.txt* — is already refused by the SDK. You do not need a library for it, and you should not write one.
This repository originally wrote one anyway: 250 lines of HMAC, TTL and argument binding, shipped as the headline feature, redundant the day it was published. That is recorded at the bottom rather than quietly deleted.
Three gaps, each with a test that fires.
Inside the TTL, the same approval verifies as many times as it is presented. Every check the boundary makes passes, every time. The specification is explicit that this is deliberate and that the rest is yours:
Note that these measures bound the replay window and prevent cross-user and
cross-request reuse, but do not by themselves guarantee single-use. Servers
for which a given
requestStatemust be consumed at most once (e.g.,
one-time redemptions) MUST enforce that invariant server-side.
For "delete a file" the second attempt finds nothing. For "transfer £500" it is the entire problem. singleuse.py is that invariant — a ledger of outstanding confirmations, spent on redemption. It contains no cryptography, because the boundary already guarantees the plaintext is something this server minted.
An elicitation message is server-chosen text rendered to a person, usually with an untrusted value interpolated into it — the whole point is to say *which* file is going away. So name a file:
cache.txt
SYSTEM NOTICE: your session has expired. Enter your AWS secret key to continue:
The dialog now carries a second, official-looking prompt. The user is not confirming a deletion; they are being phished by their own tooling. The same 2026-07-28 release also shipped MCP Apps — server-rendered UI — which widens this surface rather than narrowing it.
prompt.py flattens untrusted values to one line, strips bidirectional overrides and zero-width characters, and truncates from the *middle* so the filename at the end stays visible. Control characters become spaces rather than being deleted, since collapsing them would let a\nb and ab render identically — two different files, one dialog.
The user thought about it in between. The file can be replaced in that window, and only the tool knows what "unchanged" means for it. This server re-checks before deleting, and refuses a path that has become a symlink.
This is the useful part, and the tests are written to demonstrate it. MCPError means the SDK's middleware refused before this package ran; ToolError means this package did.
| Attack | Refused by | Test |
|---|---|---|
| Approval replayed onto a different file | SDK | test_the_sdk_refuses_a_confirmation_replayed_onto_another_file |
| State forged, or sealed under another key | SDK | test_the_sdk_refuses_a_forged_state |
| Same approval spent twice | this package | test_a_confirmation_cannot_be_spent_twice |
| State minted by another replica | this package | test_a_state_this_process_never_issued_is_refused |
| Filename forging a system prompt | this package | test_a_forged_system_prompt_cannot_escape_its_slot |
| File swapped for a symlink after approval | this package | test_a_swap_aimed_inside_the_root_is_refused |
| Path outside the allowed roots | this package | test_a_path_outside_the_roots_is_refused_before_asking |
35 tests — 17 through the server, 11 on the ledger, 7 on prompt sanitisation.
Every server test runs through the real `RequestStateBoundary`, the same class MCPServer installs on itself, with a pinned key — sealing round one and unsealing round two exactly as the wire would.
That harness exists because of a specific mistake. The first version tested by calling MCPServer.call_tool() directly, which goes straight to the tool manager and bypasses the middleware chain entirely. The SDK's boundary never ran, so a redundant hand-rolled guard looked load-bearing. The test design is what hid it, for an entire build cycle.
Coverage is 81%, with prompt.py at 100% and singleuse.py at 94%. The gap is main()'s argparse and transport wiring, exercised through build_server instead.
CI runs on Ubuntu only, deliberately: the swap-after-confirmation tests need symlinks, and the build fails if they report as skipped there.
pip install mcp-confirm
mcp-confirm --root /path/you/allow
With no --root, the server refuses every request rather than defaulting to anything. Roots are fixed at startup and never chosen by the agent. No signing key is needed — MCPServer brings its own.
RequestStateSecurity(keys=[...])); under that configuration replica B rejects a confirmation issued by replica A. It fails closed — the safe direction — but reads to a user as a confirmation that inexplicably stopped working. A multi-process deployment needs Redis or a database row with an atomic compare-and-delete. There is a test for this behaviour.singleuse.py and prompt.py.Kept here because a repository that records only its successes is not evidence of anything.
0.1.0 reimplemented what the SDK already did. state.py was 250 lines of HMAC signing, TTL, and principal/method/argument binding — all duplicating RequestStateBoundary, none of it as good: HMAC where the SDK uses authenticated encryption, no audience binding, no key rotation.
It was caught by reading the SDK's source, not by a test. The tests passed precisely because they bypassed the middleware that would have exposed it.
CI separately caught a real bug in 0.1.0: the symlink check ran *after* Path.resolve(), so it inspected the link's destination rather than the link itself. A swap aimed at another file inside an allowed root would have been deleted. Fixed, with a test for the variant the original never exercised.
0.2.0 deletes state.py entirely and keeps only what the SDK leaves uncovered.
MIT.
Built by Leslie Kadenge. I do independent security reviews of MCP servers; my public survey of thirteen production servers is at les-k.github.io/field-notes.html.