Skip to content

Odile Gate

by odilelabs.com · remote · no sign-in to list tools · v1.2.0 · published by com.odilelabs

Stop AI agents looping on or overreaching your API: app keys, approvals, safe retries, audit log

Changes · 1113 high findings

17 tools: 11 change things and 6 only read.

Scanned Oct 21, 2026

15 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http gate https://gate.odilelabs.com/mcp

Findings

Matches of fixed checks, with the text they matched.

13 high2 warn
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
Show 9 more findings
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

    What this check looks for
  • The input schema at properties.admin_key.description refers to ".env".

    Matched text

    inputSchema.properties.admin_key.description: "...uired with project_id. Read it from the .env; never print it."

    What this check looks for
  • The server marks "gate_run_tree" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"openWorldHint":true}; The name "gate_run_tree" says "run": a word for a change.

    What this check looks for
  • The server marks "gate_run_timeline" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"openWorldHint":true}; The name "gate_run_timeline" says "run": a word for a change.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

17 tools

Changes things 11Claude Code: ask
  • gate_add_appGive one app its own key and the calls it may make.1 finding

    Why it is in this group

    • The name "gate_add_app" says "add": a word for a change.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Give one app its own key and the calls it may make. Routes are rules like "GET /orders/:id", "POST /orders", "GET /users/{user}/orders" (per-user), or example calls like "GET /orders/42", which become rules. Returns the app key (shown once).

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • gate_add_approverCreate an approver key for the person who approves held actions (shown once).1 finding

    Why it is in this group

    • The name "gate_add_approver" says "add": a word for a change.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Create an approver key for the person who approves held actions (shown once). Give it to that person, never to an agent: once a project has an approver, the admin key can no longer approve.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • gate_auditThe most recent calls through the gateway (time, app, matched route, status, reason, duration), newest first, with totals by status and refusal reason.1 finding

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    The most recent calls through the gateway (time, app, matched route, status, reason, duration), newest first, with totals by status and refusal reason. Gate never stores bodies, query values or headers.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_audit_verifyRecompute a pasted export chain and project signature; returns intact or broken_at (one-based row position).1 finding

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Recompute a pasted export chain and project signature; returns intact or broken_at (one-based row position). Does not approve actions or change permissions.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_create_projectPut Odile Gate in front of an existing HTTPS API.No findings

    Why it is in this group

    • The name "gate_create_project" says "create": a word for a change.
    Description, as the server wrote it
    Put Odile Gate in front of an existing HTTPS API. Returns project_id, admin_key (shown once) and the gateway base URL apps call instead of the API.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • gate_create_runGate Actions: give one agent session narrow, expiring permission.1 finding

    Why it is in this group

    • The name "gate_create_run" says "create": a word for a change.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Gate Actions: give one agent session narrow, expiring permission. Actions are rules with {placeholders} bound by scope (e.g. "PATCH /customers/{customer}/tickets/:id" with scope {"customer":"A"}), each with an optional max and approval. Returns a run token (shown once) the agent sends as x-odile-run with its app key. Writes in a run need an Idempotency-Key. Give a write a check ("GET /bookings?idempotency_key={key}") and the agent can settle a lost answer with POST /g/<id>/_gate/recover.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • gate_delegate_runHand a narrower run to another active app in the same project.No findings

    Why it is in this group

    • The name "gate_delegate_run" says "run": a word for a change.
    Description, as the server wrote it
    Hand a narrower run to another active app in the same project. Uses the parent app key and run token, never the admin key. Scope, expiry, approvals and ancestor budgets stay enforced; maximum depth five.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: false
    • openWorldHint: true
  • gate_run_timelineRead call metadata, approvals and approver names, recovery outcomes and delegated children; no bodies or query values.2 findings

    Why it is in this group

    • The name "gate_run_timeline" says "run": a word for a change.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    • Warn

      The server marks "gate_run_timeline" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"openWorldHint":true}; The name "gate_run_timeline" says "run": a word for a change.

      What this check looks for
    Description, as the server wrote it
    Read call metadata, approvals and approver names, recovery outcomes and delegated children; no bodies or query values.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_run_treeRead a run and its delegated descendants without tokens.2 findings

    Why it is in this group

    • The name "gate_run_tree" says "run": a word for a change.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    • Warn

      The server marks "gate_run_tree" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"openWorldHint":true}; The name "gate_run_tree" says "run": a word for a change.

      What this check looks for
    Description, as the server wrote it
    Read a run and its delegated descendants without tokens.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_set_app_runsMake an app need a run: "writes" (every write needs x-odile-run), "all" (every call), or "off".1 finding

    Why it is in this group

    • The name "gate_set_app_runs" says "set": a word for a change.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Make an app need a run: "writes" (every write needs x-odile-run), "all" (every call), or "off".

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
  • gate_sync_declarativeMake a Gate project match an odile.yaml: creates the project (if no project_id) and missing apps and approvers, applies run mode, loop and learning settings and alerts.1 finding

    Why it is in this group

    • The name "gate_sync_declarative" says "sync": a word for a change.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...uired with project_id. Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Make a Gate project match an odile.yaml: creates the project (if no project_id) and missing apps and approvers, applies run mode, loop and learning settings and alerts. Never revokes or deletes; differences it cannot apply (an app's routes or rate limit) come back as drift. dry_run lists the steps without changing anything. New keys are shown once.

    Annotations the server declares

    • readOnlyHint: false
    • destructiveHint: false
    • idempotentHint: true
    • openWorldHint: true
Only reads 6Claude Code: allow
  • gate_audit_proofRead chained audit rows and their anchors with an HMAC-SHA256 signature.1 finding

    Why it is in this group

    • The description's first verb is "read": a word for reading.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Read chained audit rows and their anchors with an HMAC-SHA256 signature. Old rows before genesis are excluded; store_audit=false projects have no chain. Row-id range, up to 10,000 rows per page; follow next_from.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_explain_refusalWhat a Gate refusal means and how to fix it, from the x-gate-refused header value (e.g.No findings

    Why it is in this group

    • The name "gate_explain_refusal" says "explain": a word for reading.
    Description, as the server wrote it
    What a Gate refusal means and how to fix it, from the x-gate-refused header value (e.g. route_not_allowed).

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: false
  • gate_learn_suggestionsRead normalized routes and a suggested per-minute limit from an admin-enabled, time-boxed learning session.1 finding

    Why it is in this group

    • The description's first verb is "read": a word for reading.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Read normalized routes and a suggested per-minute limit from an admin-enabled, time-boxed learning session. Records only method, normalized path templates and counts per minute; no query values, raw ids, headers or bodies. Never enables learning or applies rules.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_list_actionsActions waiting for approval (or in another state), with the exact call.1 finding

    Why it is in this group

    • The name "gate_list_actions" says "list": a word for reading.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    Actions waiting for approval (or in another state), with the exact call. Approving is done by a person in the dashboard, not by a tool.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_list_appsThe project's apps with their allowed calls, limits and state.1 finding

    Why it is in this group

    • The name "gate_list_apps" says "list": a word for reading.

    Findings

    • High

      The input schema at properties.admin_key.description refers to ".env".

      Matched text

      inputSchema.properties.admin_key.description: "...ct admin key (ga_...). Read it from the .env; never print it."

      What this check looks for
    Description, as the server wrote it
    The project's apps with their allowed calls, limits and state.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: true
  • gate_validate_configParse and check a declarative Gate config (apps, routes, rate limits, run mode, plugins, alerts, approvers) without changing anything.No findings

    Why it is in this group

    • The name "gate_validate_config" says "validate": a word for reading.
    Description, as the server wrote it
    Parse and check a declarative Gate config (apps, routes, rate limits, run mode, plugins, alerts, approvers) without changing anything. Returns errors with their path, warnings, and the normalized config.

    Annotations the server declares

    • readOnlyHint: true
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 1.2.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http gate https://gate.odilelabs.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__gate__gate_list_apps",
      "mcp__gate__gate_list_actions",
      "mcp__gate__gate_explain_refusal",
      "mcp__gate__gate_learn_suggestions",
      "mcp__gate__gate_audit_proof",
      "mcp__gate__gate_validate_config"
    ],
    "ask": [
      "mcp__gate__gate_create_project",
      "mcp__gate__gate_add_app",
      "mcp__gate__gate_audit",
      "mcp__gate__gate_create_run",
      "mcp__gate__gate_set_app_runs",
      "mcp__gate__gate_add_approver",
      "mcp__gate__gate_delegate_run",
      "mcp__gate__gate_audit_verify",
      "mcp__gate__gate_run_tree",
      "mcp__gate__gate_run_timeline",
      "mcp__gate__gate_sync_declarative"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as gate. Review it before you use it.