Tune how strictly the gate holds
You understand Monitor, Guard, and Strict by toggling them on the live demo, and you know how to set the one you want for the way you installed the gate.
The gate reaches a contract-diff verdict first, then a posture decides what to do with it. The verdict underneath never changes; the posture only sets how cautious the hold is. Guard is the default.
- 01
Meet the three postures#
Toggle the posture on the demo below and apply the same change to see how the decision shifts.
- Monitor notifies and proceeds (awareness, no friction).
- Guard (default) holds the unambiguously breaking and dangerous changes, and auto-accepts a proven-benign drift (an added optional param, a byte-identical description) so cosmetic churn never raises a false alarm.
- Strict holds anything it cannot prove benign. It is not "hold every drift": the benign auto-accept runs before the posture layer, so a proven-benign change (an added optional param, a first-time output schema) is re-pinned and proceeds under Strict too.
in-path drift gatedeterministic · client-side · contract-diffposturepinned contract TOFU baselinemake_report( title: string, count: integer[0..1000], mode: enum[fast, full], ) // read-onlyapply a silent change to the toolcontract-diff, not a safety verdictthis is the same deterministic gate that runs in your agent - 02
Set your posture#
How you set it depends on how the gate is installed:
- Claude Desktop bundle: choose the Protection posture in the install dialog. It sets the posture for you.
- Standalone proxy or manual wiring: pass a flag to the proxy:
mcpindex-proxy --posture strict(ormonitor), ahead of the upstream server arguments. - The SDK: pass it to
wrap(), for exampleposture: Posture.STRICTin TypeScript orposture=Posture.STRICTin Python. - Installed with the one-liner / config-wire: those launch under Guard by default.
Posture is per server (each wired server runs its own gate), so you can be stricter on a high-blast-radius server than on a read-only one.
- 03
Confirm which posture is active#
There is no separate 'show posture' command, and the posture name is not stored in your receipts. The reliable signal is its effect: under Monitor an unambiguously breaking change is logged ALLOW, where Guard or Strict would hold it and log DENY (or REVIEW, for a change that needs behavioral validation). So if a change you expected to be held shows ALLOW in your Gate Activity, you are running Monitor.
Check your Gate Activity — the verdict column: under Monitor an unambiguously breaking change shows as ALLOW, where Guard or Strict would show DENY (or REVIEW).
- 04
Which posture to pick#
Start on Guard, the default: it catches real breaking changes without nagging on cosmetic churn. Move to Strict when you want to review every drift yourself, for higher-stakes or production agents. Use Monitor when you want the signal but never a pause, awareness only.
Read Fig. 07 as text
ChangeKind MONITOR GUARD* STRICT
------------------------------------------------------------------
added-required-param notify | HOLD | HOLD
constraint-narrowed notify | HOLD | HOLD
deep-schema-undiffable notify | HOLD | HOLD
enum-values-removed notify | HOLD | HOLD
param-mirrored-to-header notify | HOLD | HOLD
removed-param notify | HOLD | HOLD
required-set-expanded notify | HOLD | HOLD
tool-removed notify | HOLD | HOLD
type-changed notify | HOLD | HOLD
annotation-flip-to-destructive notify ? INCONCL. ? INCONCL.
output-schema-changed notify ? INCONCL. ? INCONCL.
added-optional-param -> proceed -> proceed -> proceed
output-schema-added -> proceed -> proceed -> proceed
* guard is the default posture.
of 13 surfaced kinds: 9 HOLD under guard, 2 resolve to
INCONCLUSIVE (behaviour is the gate, not a block), 2 proceed as proven-benign.
STRICT DOES NOT HOLD EVERY DRIFT. the benign auto-accept runs BEFORE the posture
layer, so a proven-benign change (an added optional param, a first-time output
schema) is re-pinned and proceeds under strict too. strict holds everything it
cannot prove benign.
MONITOR never blocks: every kind returns PROCEED-with-note.
an injection / exfil MARKER found in a schema or description is a separate scan,
not a ChangeKind, so it is not a row here - but guard blocks on it, as it does on
a risk escalation, a description change, and any fail-closed error.
verified 2026-07-27 by driving the gate (corpus_eval/tooling/cse/gate.py) at all
three postures.Permalink, SVG & reuse · CC BY 4.0
Read Fig. 06 as text
|- HELD
|
+- did you expect this change?
| yes --> re-pin. the new contract becomes your baseline. done.
| no --> is it breaking or destructive?
| yes --> reject the call. check the server's changelog.
| check /ledger - did the crawler see it too?
| no --> re-pin, or move that server to the monitor posture.
|
+- holding too often?
guard --> monitor notify and proceed. you still see every change.
guard --> strict hold anything not PROVEN benign.
every exit is reversible. a re-pin can be re-pinned.Permalink, SVG & reuse · CC BY 4.0
- What is the default posture for the mcpindex gate?
- Guard. It holds the unambiguously breaking and dangerous contract changes and auto-accepts proven-benign drift (an added optional parameter, a byte-identical description) so cosmetic churn never raises a false alarm.
- How do I make the gate hold on every contract change?
- Run it in Strict posture. How you set that depends on the install: pass --posture strict to mcpindex-proxy, choose it in the Claude Desktop install dialog, or pass posture=Posture.STRICT to the SDK's wrap(). Config-wired installs run Guard by default.