Tune how strictly the gate holds

What you'll have · ~3 min

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.

  1. 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 gate
    posture
    pinned contract TOFU baseline
    make_report(
      title:    string,
      count:    integer[0..1000],
      mode:     enum[fast, full],
    )  // read-only
    apply a silent change to the tool
    contract-diff, not a safety verdictthis is the same deterministic gate that runs in your agent
  2. 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 (or monitor), ahead of the upstream server arguments.
    • The SDK: pass it to wrap(), for example posture: Posture.STRICT in TypeScript or posture=Posture.STRICT in 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.

  3. 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 Activitythe verdict column: under Monitor an unambiguously breaking change shows as ALLOW, where Guard or Strict would show DENY (or REVIEW).

  4. 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.

NextIntegrate the gate in your own code
Posture and ChangeKindA matrix of the thirteen surfaced ChangeKinds against the three postures, generated from the gate source. Monitor never blocks: every kind returns proceed-with-note. Guard, the default, holds the nine kinds that carry the safety bit, resolves annotation-flip-to-destructive and output-schema-changed to inconclusive because behaviour is the gate rather than a block, and lets the two provably benign kinds proceed. Strict matches guard except that it also holds the inconclusive pair; it does not hold every drift, because the benign auto-accept runs before the posture layer and re-pins a proven-benign change. An injection or exfiltration marker is a separate scan rather than a ChangeKind, so it is not a row, though guard blocks on it.GENERATED FROM THE GATE SOURCE — VERIFIED BY DRIVING IT AT ALL THREE POSTURESCHANGEKINDWHY IT LANDS HEREMONITORGUARD (DEFAULT)STRICTadded-required-paramcarries the safety bitnotifyHOLDHOLDconstraint-narrowedcarries the safety bitnotifyHOLDHOLDdeep-schema-undiffablecarries the safety bitnotifyHOLDHOLDenum-values-removedcarries the safety bitnotifyHOLDHOLDparam-mirrored-to-headercarries the safety bitnotifyHOLDHOLDremoved-paramcarries the safety bitnotifyHOLDHOLDrequired-set-expandedcarries the safety bitnotifyHOLDHOLDtool-removedcarries the safety bitnotifyHOLDHOLDtype-changedcarries the safety bitnotifyHOLDHOLDannotation-flip-to-destructivebehaviour is the gate, not a blocknotifyINCONCLUSIVEINCONCLUSIVEoutput-schema-changedbehaviour is the gate, not a blocknotifyINCONCLUSIVEINCONCLUSIVEadded-optional-paramproven benign - re-pinned, then proceedsproceedproceedproceedoutput-schema-addedproven benign - re-pinned, then proceedsproceedproceedproceedOf 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 aproven-benign change is re-pinned and proceeds under strict too. Monitor never blocks.An injection / exfil marker is a separate scan, not a ChangeKind, so it is not a row —but guard blocks on it, as it does on a risk escalation and any fail-closed error.
Fig. 07 · The gate reads a fixed table, not a judgement call - and strict does not hold every drift.
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

It held. Now what?A decision tree for a held call. If you expected the change, re-pin and the new contract becomes your baseline. If you did not expect it, ask whether it is breaking or destructive: if yes, reject the call, check the server changelog, and check the public ledger to see whether the crawler saw it too; if no, re-pin or move that server to the monitor posture. If the gate is holding too often, move from guard to monitor to notify and proceed, or to strict, which holds anything it cannot prove benign.HELDdid you expect this change?YESre-pin. the new contract becomes your baseline. done.NOis the change breaking or destructive?YESreject the call. check the server’s changelog, and check /ledger tosee whether the crawler caught the same drift.NOre-pin, or move that one server to the monitor posture.holding too often?guard → monitornotify and proceed. you still see every change.guard → stricthold on any drift, including benign.EVERY EXIT IS REVERSIBLE. A RE-PIN CAN BE RE-PINNED.
Fig. 06 · Every exit from a hold is reversible.
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

Questions
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.