Gate your Mastra agent's MCP tool calls

What you'll have · ~3 min

Your Mastra agent asks mcpindex whether an MCP tool is vetted before it invokes it, warning you (or blocking the call) on your terms, fail-closed.

By default a Mastra agent calls whatever tools an MCP server hands it, trusting each tool's own description. The @mcp-index/mastra package adds a second opinion at the moment of the call: a beforeToolCall hook that checks mcpindex's advisory screen first. It is a client of the advisory screen (has this tool been vetted?), not the in-path drift gate (did this contract change since I pinned it?).

  1. 01

    Install the package#

    Zero runtime dependencies; @mastra/core is an optional peer you already have.

    npm i @mcp-index/mastra
    
  2. 02

    Add the hook to your agent#

    Pass the mcpindex server id whose tools your agent calls. That is the whole integration.

    import { Agent } from "@mastra/core/agent";
    import { mcpindexGate } from "@mcp-index/mastra";
    
    const agent = new Agent({
      id: "gated-agent",
      name: "gated-agent",
      instructions: "You are a helpful assistant.",
      model: "openai/gpt-4o-mini",
      hooks: {
        beforeToolCall: mcpindexGate({ serverId: "your-mcp-server-id" }),
      },
    });
    

    In the default warn mode you now get a log line before every tool call with the tool's trust directive, and nothing about your agent's behavior changes.

  3. 03

    Choose warn or enforce#

    Two policies, and the default is deliberately the non-breaking one.

    mcpindexGate({ serverId: "your-mcp-server-id", policy: "warn" })    // default
    mcpindexGate({ serverId: "your-mcp-server-id", policy: "enforce" }) // fail-closed
    
    • warn never blocks a call. It logs and annotates. Pure visibility.
    • enforce is fail-closed: only an explicit ALLOW directive proceeds; DENY, REVIEW, and UNVERIFIED are blocked, and the model receives a short 'not cleared' message in place of the tool's output.
  4. 04

    Read the honest limit (important)#

    The mcpindex public advisory API is at verdict contract 1.0.0, and it does not yet emit ALLOW or DENY - every verdict today is REVIEW or UNVERIFIED. So today this is a visibility and early-warning tool, and warn is the sane default. enforce blocks every tool call right now, because nothing is ALLOW yet; that is correct fail-closed behavior, and it becomes a real allow-list the moment mcpindex ships ALLOW/DENY verdicts, with no code change on your side. If mcpindex is slow or unreachable, the check fails closed to UNVERIFIED rather than silently trusting.

  5. 05

    Direct lookups (optional)#

    Need the verdict without the hook? The client is exported.

    import { TrustClient } from "@mcp-index/mastra";
    
    const client = new TrustClient();
    const v = await client.checkTool("your-server-id", "send_email");
    console.log(v.directive, v.honest_limits);
    

    Full SDK and API referencethe 'Ways to use the directory' HTTP endpoints and the SDK section.

NextIs it safe to let an AI agent call an MCP tool?
Questions
Does @mcp-index/mastra block untrusted MCP tools?
In enforce mode it blocks any tool whose directive is not an explicit ALLOW. But note the mcpindex v1 public API only emits REVIEW or UNVERIFIED today (ALLOW/DENY are reserved), so today enforce blocks everything and warn (the default) is the useful mode: it flags unvetted tools without changing behavior. It becomes a real allow-list when ALLOW/DENY ship, with no code change.
What happens if mcpindex is unreachable?
It fails closed. A timeout, network error, non-2xx, or unparseable response resolves to an UNVERIFIED verdict, never a silent ALLOW. Under warn it proceeds and logs; under enforce it blocks.