Repository navigation
Releases: Prashant-thakur77/confirm-gate-mcp
Release list
confirm-gate-mcp 0.8.0
-
DynamoStore never mistakes an IAM refusal for a missing index. A policy covering the table but not its indexes made every lookup fall back, silently, to a full-table scan; the refusal is now raised.
-
confirm-gate demo: the gate in front of a built-in notes server with one read (list_notes) and one write (write_note), in memory, with nothing else to install. Likeserve, it prints the endpoint, the bearer token, the approval page and a pairing code, and then the steps to see a card. The README's "60 seconds" is built on it: install, runconfirm-gate demo, pair on/approve, callwrite_notefrom MCP Inspector, tap the card, and get a receipt. -
build_appis exported fromconfirm_gate.from confirm_gate.cli import build_appstill works. -
The package is typed: it ships
py.typed. -
uvicornis a declared dependency. The command line always imported it, but it used to arrive only throughmcp. -
Package metadata: project URLs (homepage, source, changelog, issues, docs) and classifiers (Python 3.12 and 3.13, Development Status 4 - Beta, Typing :: Typed).
-
Docs:
docs/API.mdcoversGatedServer,wrap_upstream,build_app,device_routes,Gate,DeviceRegistry, theStoreprotocol and its three stores, receipt fields and every CLI flag. The README has client configs for Claude Code,mcp.json(Cursor, VS Code), MCP Inspector and Strands, and showsserve --strictwith the official filesystem server. The install lines use the GitHub URL until the package is on PyPI. -
Community files:
CONTRIBUTING.md(setup, the failing-test-first rule for the gate, release steps with the trusted-publishing workflow),CODE_OF_CONDUCT.md,SECURITY.md(supported versions, private advisories), issue forms and a pull request template.
confirm-gate-mcp 0.7.2
- A lone high-risk card still asks twice. It used to open straight at the final yes/no, so one yes released it, unlike the same action offered beside other cards. Now every high-risk card is chosen first and then asks a second, separately nonced yes; a "no" still cancels at once. To open a set at the final question on purpose, pass
stage="final"topropose.
confirm-gate-mcp 0.7.1
- More time on the approval page: a signed device route,
POST /device/more-time {"pending_id"}, callsGate.extendfor the device's own user (404 for an unknown set or another user's, 409 for one no longer waiting or out of more time, 200 withexpires_in_sandextensions_left, never the nonce). The built-in/approvepage shows a live countdown with a large, keyboard-reachable More time button beside it, hidden once a set has no more time left, and a polite warning at 30 s: "30 seconds left. Choose More time to keep these cards." The route is not an MCP tool.
confirm-gate-mcp 0.7.0
- More time (WCAG 2.2.1 Timing Adjustable):
Gate.extend(pending_id, *, user_id, seconds=None)moves a waiting card set's deadline to now + its own time (120 s, or 60 s for the second yes; never earlier than it was), at mostGate.max_extensions(10) times per set. It refuses another user's set as unknown (KeyError) and an answered, withdrawn or expired one (NotWaiting), returns the public view withextensions_left(never the nonce), and emits anextendedevent. It is not an MCP tool ofGatedServerorwrap_upstream. Store.update(kind, key, change): a compare-and-swap rewrite, retried on conflict, in every store. A write landing between its read and its write (a nonce consumed) is never lost, and DynamoDB's one-time markers survive it.
confirm-gate-mcp 0.6.1
- The
evidenceevent carries the tap'sinput(touch, key or switch), so an activity log can say how the user answered.
confirm-gate-mcp 0.6.0
- Pairing codes made by a device (
start_pairing(user, minted_by=device_id)) stop working if that device is unpaired first, and the new device recordspaired_via. - Consent parser: negated auxiliaries ("wouldn't", "can't", "cannot"...) are a no; a question is still a question after a filler or a reflexive yes ("um, is two the fan"); a polite request ("can I have two") is not a question; "the number one" and "the option one" choose one.
/device/evidenceanswers 400 wheninputis not a string.
confirm-gate-mcp 0.5.0
- Receipts record how the user answered on the device:
submit_tap(..., input="touch" | "key" | "switch")(andinputon/device/evidence); the receipt'show.inputandevidence.inputname it, andto_textsays "your tap", "your key press" or "your switch". An unknown input is refused. - Consent parser, from a 7,093-case stress test: a transcript that starts like a question ("is two the fan", "kya do number…") chooses nothing, since recognisers drop the "?"; in "the/that ___ one" the "one" is a pronoun, never option one ("the to one"); "go ahead" is a yes as a phrase.
confirm-gate-mcp 0.4.1
- An Agent Skill,
skills/add-confirm-gate/SKILL.md(the open SKILL.md format): it teaches a coding agent to gate an MCP server, from choosing the proxy orGatedServerto checking that the agent's ownconfirmis refused.
confirm-gate-mcp 0.4.0
For gating a server you didn't write.
- Strict mode.
wrap_upstream(..., trust_annotations=False)andconfirm-gate serve --strictignore the upstream'sreadOnlyHint: only the tools you list as reads pass through, and everything else waits for the user. A server that marks a delete as read-only no longer slips past the gate. - Glob patterns in
reads,writesandhigh_risk(--reads "get_*,list_*" --high-risk "delete_*"). - The approval page shows a wrapped tool's call readably: the tool's name, then each argument on its own line, wrapped instead of running off the card. A lone high-risk card is labelled as the final check it is, rather than "asks twice".
examples/strands_agent.py: a Strands agent on Amazon Bedrock working through the gate.- CI builds the wheel, runs
twine check, and installs it to run the command.
confirm-gate-mcp 0.3.1
Third adversarial review, of 0.3.0 itself.
- Pairing budgets per source.
pair(code, source=...)takes one unit of a per-source budget (max_attempts, 5) and one of a global ceiling (global_max_attempts, 30) per window, so one guesser can no longer lock out the owner, and guessing from many addresses is still bounded.device_routes(client_ip=...)names the caller behind a proxy. DynamoStore.set_oncenever loses a concurrent write to another field of the same document (an optimisticdoc = :oldcondition, re-read on conflict). Before, a revocation landing between the read and the write could be dropped.set_transcriberis a one-time conditional write, so it can never undo a revocation; idempotent for the same recogniser.- Consent: on the final card only the card's fixed words may be said back, never its quoted free text (a message the agent wrote) or an unreadable word. Every question-shaped phrase counts, not just the first ("yes do it, is it the front door" is unclear). More hedges ("never mind", "scratch that", "rehne do", "chhodo", "sorry", "I suppose") and time phrases ("two seconds", "bas do second", "another second").