Secured APIs as tools

Let agents call OAuth-secured APIs through a tool - two credentials that never meet.

An AI agent needs data from an enterprise API that requires OAuth - and giving the OAuth client's secret to the agent is exactly what must never happen. The configuration below gives the agent a tool instead: the agent authenticates to an MCP gateway with its own API key, the tool is a service, and the service calls the secured API through an outgoing connection whose OAuth credentials live in the platform. Two credentials, two directions, and neither side ever sees the other's secret.

Prerequisites. An OAuth-secured REST API to call - any API with a client_credentials token endpoint. The example uses a CRM at https://crm.internal.example.com.

The service

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class GetCustomerBalance(Service):
    """ Returns the outstanding balance of one customer account from the CRM.
    """
    name = 'example.crm.get-customer-balance'

    input = 'account_id'
    output = 'account_id', 'balance', 'currency'

    def handle(self):

        account_id = self.request.input.account_id

        # The connection injects the Bearer token it obtains and refreshes itself -
        # the OAuth client's id and secret never appear in service code.
        conn = self.rest['CRM API']
        response = conn.get(self.cid, params={'account_id': account_id})

        crm_data = response.data

        self.response.payload.account_id = account_id
        self.response.payload.balance = crm_data['balance']
        self.response.payload.currency = crm_data['currency']

The docstring and the declared I/O are what the agent's model sees - the tool schemas page explains the mapping.

The configuration

One enmasse file holds both credential paths:

security:

  # What the agent presents to the gateway - an API key, never the OAuth secret
  - name: crm.agent.key
    type: apikey
    username: crm-agent
    password: Zato_Enmasse_Env.CRM_Agent_Key

  # What the platform presents to the CRM - the OAuth client, never given to any agent.
  # The platform obtains and refreshes the Bearer tokens automatically.
  - name: crm.oauth.client
    type: bearer_token
    username: zato-crm-client
    password: Zato_Enmasse_Env.CRM_OAuth_Secret
    auth_endpoint: https://login.internal.example.com/oauth2/token
    grant_type: client_credentials

groups:
  - name: crm-agents
    members:
      - crm.agent.key

outgoing_rest:
  - name: CRM API
    host: https://crm.internal.example.com
    url_path: /api/v1/balance
    security: crm.oauth.client

mcp_gateway:
  - name: crm
    url_path: /mcp/crm
    services:
      - example.crm.get-customer-balance
    security_groups:
      - crm-agents
    validate_input: true
    is_audit_log_active: true

Connect the agent

claude mcp add --transport http crm http://localhost:17010/mcp/crm \
    --header "X-API-Key: the-agent-key-value"

Asking the agent about a customer's balance makes it call the example.crm.get-customer-balance tool and the reply carries the CRM's data - the CRM sees the platform's OAuth client and nothing else, and the agent holds its own API key and nothing else.

Failure behavior

Each credential fails separately:

  • An agent with a wrong or revoked API key gets HTTP 403 from the gateway and the CRM is never contacted - the rejection is in the server log and, as an auth-failed event, in the audit log.
  • When the OAuth client is the problem - an expired secret, a revoked grant - the tool call fails with isError and the agent sees that the tool failed, not why. The reason, with the CRM's response, is in the server log under the request's CID - to follow it end to end, see tracing one call.
  • Revoking one agent is removing its key from the crm-agents group - membership changes are live, with no effect on the OAuth side.

See also

FeatureWhat it does
MCP gateway securityThe credential types and groups agents authenticate with
Multi-agent isolationSeveral agents on one platform that cannot see each other
Tool selectionDocstrings and schemas that steer agents to the right tool