Integrate the gate in your own code
The gate's contract pin running inside your own MCP server in a few lines, with the HOLD handled and the baseline persisted correctly for your language.
You do not have to run the standalone gate to get contract pinning. If you already have an authenticated MCP client session in your own code, the SDK wraps it so the pin runs in-path, with no per-server config and no token handling.
- 01
Install the SDK#
Pick your runtime:
# TypeScript npm i @mcp-index/sdk # Python pip install mcpindex-gate # or: uv add mcpindex-gate - 02
Wrap your session#
Wrap the session you already authenticated. The wrapper reuses its transport, so
list_tools/call_toolstay drop-in and no credentials pass through mcpindex.// TypeScript import { wrap, PreflightPin } from "@mcp-index/sdk"; const guarded = wrap(session, { pin: new PreflightPin(), serverId: "your-server" }); // use guarded.list_tools() / guarded.call_tool(...) exactly as before# Python from mcpindex_gate import wrap, PreflightPin session = wrap(session, pin=PreflightPin(), server_id="your-server") - 03
Handle a HOLD#
On a breaking contract change the gate holds before the tool runs, so the wrapped tool is never called on a hold. By default it surfaces the hold; pass a handler if you would rather intercept it.
// TypeScript - the guarded call REJECTS with a PreflightHold by default, // or route it to a handler: const guarded = wrap(session, { pin: new PreflightPin(), serverId: "your-server", onHold: (verdict) => { /* log, prompt a human, or re-pin */ }, });# Python - raises PreflightHold by default, or pass on_hold: session = wrap(session, pin=PreflightPin(), server_id="your-server", on_hold=lambda verdict: ...) - 04
Persist the baseline (this differs by language)#
A persisted baseline means drift that lands while your agent is offline is still caught on the next call. How you persist depends on the runtime, and this is the one place the two SDKs differ:
- Python: pass a path.
PreflightPin(path="~/.mcpindex/pins/your-server.json")loads a prior baseline on start and writes updates atomically. - TypeScript:
PreflightPinis in-memory only, it takes no path, so a fresh process re-pins from scratch. For durable pins in a TypeScript setup, run the tool behind the standalone gate/proxy instead, which keeps its own on-disk pin store.
If you only run inside a long-lived process, the in-memory pin is fine either way.
- Python: pass a path.
- 05
What else comes with it#
The blast-radius grade is on by default alongside the pin, labeling each call's action, reversibility, and egress. Separately, the advisory directory HTTP API (preflight, trust, screen) covers discovery and pre-wire screening, but that is not the in-path gate: the contract pin and diff always run locally.
Full SDK and API reference — the SDK section for the complete wrap() options, and 'Ways to use the directory' for the HTTP endpoints.
- Does the mcpindex TypeScript SDK persist the contract pin across restarts?
- No. In the TypeScript SDK, PreflightPin is in-memory only and takes no path argument, so a fresh process re-pins from scratch. For durable pins in TypeScript, run the tool behind the standalone gate/proxy, which keeps an on-disk pin store. The Python SDK does persist: pass PreflightPin(path=...).
- What happens on a HOLD when I use the SDK wrapper?
- The wrapped tool is never called. In TypeScript the guarded call rejects with a PreflightHold (or invokes your onHold handler); in Python it raises PreflightHold (or calls your on_hold callback). You then review the change and re-pin if it was expected.