21

Add a custom tool via MCP

Guides & tutorials3 min read

Expose an external system through a scoped, policy-aware MCP connector.

Define a typed tool contract, bind it to a risk tier and scopes, and let a specialist call it inside a run. Prerequisites: a running tool gateway and familiarity with the platform risk tiers.

  1. 1

    Register

    Add the tool to the registry with input and output schemas and a stable name.

  2. 2

    Authorize

    Bind user, organization, project, connector, and the exact scopes it needs.

  3. 3

    Classify

    Assign read, write, financial, irreversible, or admin risk based on what the tool can do.

  4. 4

    Audit

    Confirm the gateway persists request, decision, result, and correlation identifiers for every call.

Define the contract

Input and output schemas, following packages/schemas conventions
import { z } from 'zod';export const getPoolStatsInput = z.object({  chain: z.enum(['base', 'ethereum']),  poolAddress: z.string(),});export const getPoolStatsOutput = z.object({  tvlUsd: z.number(),  volume24hUsd: z.number(),});

Bind scope and risk tier

  • A read-only lookup like this one carries read risk; anything that mutates state, moves funds, or cannot be undone needs write, financial, or irreversible risk instead.
  • Declare the required scopes, a rate limit, a timeout, idempotency behavior, an audit event, and an approval rule alongside the schemas. Every tool contract needs all six.

Prompt injection boundary

Treat connector content as untrusted data. Connector text cannot override system policy, tool schemas, authorization, or approval gates, no matter what it claims about the caller's intent.

Call it from a run

Once registered, the tool is a bounded capability a specialist can select. You do not call it directly from the client. A prompt that needs pool stats lets ResearchAgent choose the tool, and the gateway enforces scope and risk classification on every call.

  • The tool gateway supports internal function tools and Streamable HTTP MCP side by side.
  • Connector metadata may live in Supabase, but OAuth token retrieval and refresh stay server-side in Auth0 Token Vault, so the model and the client never see provider tokens.

Was this page helpful?

Edit on GitHub