Available

The MCP gateway

Put your tool servers behind your project's MCP gateway, grant tools to AI agents one by one, and see what the gateway checks on every call.

Your project has a gateway for the Model Context Protocol (MCP), the protocol AI agents use to call tools. It is at https://acme.authfi.io/mcp. Agents connect to it instead of to each tool server, and the gateway decides, call by call, whether this agent may call this tool with these arguments.

This guide shows you how to connect a tool server and grant its tools. It then describes what the gateway checks, returns and records. For a first call, start with Connect agents to tools.

Before you begin

You need:

  • Administrator access to the AuthFI console.
  • A registered agent with an access token for the gateway. See Give an AI agent an identity.
  • The URL of the tool server, and the bearer token it expects if it needs one.

Connect a tool server

  1. In the console, open Integrations > MCP Gateway and select the Servers tab.
  2. Choose Connect a server.
  3. Fill in the dialog, then choose Register.
FieldEnter
NamespaceOne short name: letters, digits and dashes. It prefixes every tool's name.
Server URLWhere the tool server is reached, for example https://mcp.example.com/mcp
Transport"Streamable HTTP", "SSE" or "Agent2Agent"
How it authenticates the gateway"Bearer token" or "No credential"
Whose credential"One shared credential" or "Each user's own". Asked for a bearer token.
CredentialThe token the tool server expects. Asked for one shared credential.

The console confirms that the server is registered. The gateway then reads the server's tools and lists each one as namespace.tool, for example github.create_issue. You see them on the Tools tab.

Grant tools

Nothing is callable until it is granted.

  1. On the Tools tab, choose Say who may call a tool.
  2. Choose the kind of caller: "An AI agent", "A person" or "A group".
  3. Under "Caller", choose the agent. Only active agents are listed.
  4. Under "May call", tick the tools. Use "Filter tools" to find them.
  5. Choose Grant 1 tool. The button counts the tools you ticked.

The console confirms that the caller may now call the tools. On the Tools tab, the "Who may call it" column shows the grant.

A grant is on one tool. Granting github.create_issue does not grant github.delete_repo. A grant to a group reaches every member of it, now and later.

You can also grant from the agent's own page: open the agent under Identity > AI Agents and choose Give it a tool.

Point the agent at the gateway

On the Overview tab, find "Where the agents connect" and copy the "Gateway" URL. For the example project it is https://acme.authfi.io/mcp. Configure the agent to call that URL, not the tool server.

Check that it works

List the tools as the agent. The gateway takes JSON-RPC over HTTP POST, with the agent's access token as a Bearer credential.

POST

/mcp
curl https://acme.authfi.io/mcp   -H "Authorization: Bearer $ACCESS_TOKEN"   -H "Content-Type: application/json"   -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

$ACCESS_TOKEN is the agent's access token. The result contains the tools of every server you added. Each tool looks like this:

{
  "name": "payments.refund",
  "description": "Refund a payment",
  "inputSchema": { "type": "object" },
  "annotations": { "io.authfi/governance": "may_require_approval" }
}

A tool this agent may call is marked no_policy_restriction.

After the agent calls a tool, open the Tape tab. The call is listed with its "Caller", "Tool" and "Verdict".

How tools are marked in the list

tools/list returns every tool, each marked with what would happen if this agent called it.

io.authfi/governanceMeaning
no_policy_restrictionThis agent may call it
may_require_approvalA person may have to approve, depending on the arguments
never_allowedThis agent's call is denied

An agent can use the mark to avoid tools it cannot call. The decision itself is made on each call, with its arguments.

What is checked on a call

For every tools/call, the gateway checks, in order:

  1. The token is a valid agent access token for this project.
  2. The agent has not been revoked.
  3. The agent is granted this tool.
  4. If the agent is acting for a person, that person is granted it too.
  5. The arguments pass the project's rules.

Only then does the gateway forward the call, with the tool server's own credential.

When a call is denied

A denied call is an ordinary tool result with isError set, so the model reads it and can change course.

{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "isError": true,
    "content": [{ "type": "text", "text": "Denied by policy: agent:agt_7f3a9c21 is not granted payments.refund" }]
  }
}

When a call needs approval

If a rule sends the call to a person, the result says so. It carries an approval ID and tells the model how to continue.

{
  "result": {
    "isError": true,
    "content": [
      {
        "type": "text",
        "text": "Approval required. A human must approve this action in the AuthFI console (approval 3f0c2b6e-…). Retry this call with an argument \"_authfi_approval_id\": \"3f0c2b6e-…\" once it is approved."
      }
    ]
  }
}

A person approves or denies the request on the Approvals page of the console. The agent then makes the same call again and adds the approval ID:

{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "tools/call",
  "params": {
    "name": "payments.refund",
    "arguments": { "payment": "pay_4821", "amount": 1200, "_authfi_approval_id": "3f0c2b6e-…" }
  }
}

The gateway checks the approval, removes _authfi_approval_id, and forwards the call. The tool server never sees the approval ID. An approval is good for 15 minutes and for that call.

For approvals outside the gateway, see Ask before a sensitive action.

How credentials are kept

The tool server's credential is sealed when you enter it and is never shown again. The gateway attaches it to each call it forwards. The agent never holds it, so the agent has nothing to leak, and revoking the agent needs no change at the tool server.

With "Each user's own" credential, each person connects their own account. On the Servers tab, the person chooses Connect my account on the server, enters "Your token" and chooses Connect. The gateway then makes each call with the account of the person the agent is acting for. A call with no person, or for a person who has not connected their account, is denied.

How an agent signs in to the gateway

An agent sends its access token as a Bearer credential. An agent access token requested with no resource is issued for the gateway by default.

A request with no token, or with a token that is expired or revoked, gets a 401, as RFC 9728 describes:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://acme.authfi.io/.well-known/oauth-protected-resource"

The document at that URL names the gateway and where to get a token for it:

{ "resource": "https://acme.authfi.io/mcp", "authorization_servers": ["https://acme.authfi.io"] }

Protocol reference

PropertyValue
TransportJSON-RPC 2.0 over HTTP POST to /mcp
Revision2025-06-18
Methodsinitialize, tools/list, tools/call
JSON-RPC errorMeaning
-32700The body is not valid JSON
-32601The method is not one of the three
-32602The parameters are wrong
-32000The tool server could not be reached

What is recorded

Every call, allowed or denied, is an entry in the audit record. The entry holds the agent, the person it acted for, the tool, the decision and its reason.

The Tape tab of Integrations > MCP Gateway lists the last 100 calls.

Its columns are "When", "Caller", "Tool", "Verdict", "Why" and "Acted for". Filter the list with "every call", "refused" or "allowed".

Troubleshooting

What you seeCauseFix
401 with a WWW-Authenticate headerThe token is missing, expired or revokedSign in again and send the new access token
A result that says the agent is not granted the toolThe agent has no grant on this toolGrant it with Say who may call a tool
A denied call to a server with "Each user's own" credentialThe call has no person, or the person has no account connectedThe person chooses Connect my account
JSON-RPC error -32000The tool server could not be reachedCheck that the server answers at its "Server URL"
JSON-RPC error -32601The method is not initialize, tools/list or tools/callUse one of the three methods

Next steps