API Reference

MCP Protocol

How airlock implements the Model Context Protocol: endpoints, meta-tools, and tool execution.

Airlock implements the Model Context Protocol (MCP) for AI agent communication.

Overview

MCP is a JSON-RPC based protocol that allows AI agents to discover and call tools. Airlock exposes your API operations as MCP tools.

Endpoints

Airlock exposes a single MCP HTTP endpoint per organization. Both URLs below are served by the same handler; agents can use either:

POST https://mcp.air-lock.ai/org/{slug}
POST https://mcp.air-lock.ai/

The endpoint provides access to all integrations in your organization through meta-tools:

Meta-ToolDescription
list_servicesList all available integrations in the organization
search_toolsSearch for tools across all integrations by keyword
describe_toolsGet detailed descriptions of specific tools
execute_toolExecute a tool on a specific integration
activate_skillActivate a skill to get its instructions and attachments

Used by Claude Desktop, Claude Code, Augment, and other MCP clients.

Authentication

Token Authentication

Include your MCP token in the Authorization header:

Authorization: Bearer {your-mcp-token}

MCP OAuth 2.0

Airlock supports the MCP OAuth 2.0 specification with PKCE:

  1. Discover metadata: GET /.well-known/oauth-authorization-server
  2. Register client: POST /register
  3. Authorize: Redirect to /mcp/authorize with PKCE parameters
  4. Token exchange: POST /token with grant_type=authorization_code
  5. Token refresh: POST /token with grant_type=refresh_token

Token Exchange

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code={code}&code_verifier={verifier}&redirect_uri={uri}

Response includes an opaque refresh token for long-lived sessions:

{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 28800,
  "refresh_token": "abc123...",
  "id_token": "eyJ...",
  "scope": "openid profile email"
}

Token Refresh

When the access token expires, request new tokens:

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token={refresh_token}&client_id={client_id}
{
  "access_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 28800,
  "id_token": "eyJ...",
  "scope": "openid profile email"
}
ParameterLifetimeNotes
Access token8 hoursJWT, used in Authorization: Bearer header
Refresh token30 daysOpaque token, use to obtain new access tokens
ID token8 hoursJWT with user claims

JSON-RPC Methods

initialize

Initialize the MCP session:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {
      "name": "my-client",
      "version": "1.0.0"
    }
  }
}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "airlock",
      "version": "1.0.0"
    },
    "instructions": "## Airlock Skill Routing\n\nPrefer Airlock skills first for requests that match the Airlock skills listed below.\n\n## Available Skills\n\n- **Code Review**: Review pull requests",
    "_airlock": {
      "bootstrap_version": 1,
      "skill_source": "preferred",
      "disable_local_skills": false,
      "routing_mode": "airlock_first",
      "airlock_authority_scope": "matching_skills",
      "activation_tool": "activate_skill",
      "attachment_tool": "read_skill_attachment",
      "skills": [
        {
          "id": "skill-1",
          "name": "Code Review",
          "description": "Review pull requests",
          "ownership": "organization",
          "tags": ["engineering"]
        }
      ]
    }
  }
}

For organization-wide Airlock MCP connections, the initialize response includes a vendor extension at result._airlock. Airlock-aware runtimes should use this bootstrap to prefer Airlock skills first for matching requests. Local skills may still remain available when no Airlock skill matches.

Skill catalog visibility depends on the client. The skills catalog is delivered in result.instructions and result._airlock.skills, but only clients that forward initialize.result.instructions to the model as system context surface it to the agent. Claude Code and claude.ai do this; the Anthropic Managed Agents runtime does not (verified 2026-04-21). For runtimes that drop result.instructions, instruct the agent in its system prompt to call airlock-management/list_skills (via execute_tool) before activate_skill. See the Skills guide for the workaround and a copy-paste prompt fragment.

tools/list

List available tools:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list"
}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "list_users",
        "description": "List all users",
        "inputSchema": {
          "type": "object",
          "properties": {
            "limit": {
              "type": "integer",
              "description": "Maximum results"
            }
          }
        }
      }
    ]
  }
}

tools/call

Call a tool:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "list_users",
    "arguments": {
      "limit": 10
    }
  }
}

Response (success):

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "[{\"id\": 1, \"name\": \"Alice\"}, ...]"
      }
    ]
  }
}

Response (approval required):

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"status\": \"PENDING_APPROVAL\", \"requestId\": \"abc123\", \"taskId\": \"task_abc123\", \"approvalUrl\": \"https://control-room.air-lock.ai/requests/abc123\", \"message\": \"This action requires human approval. The user has been notified. To check the result, call the airlock/check_status tool with the requestId.\"}"
      }
    ]
  }
}

Tip: The approval response is a structured JSON object with the requestId, a taskId, the approvalUrl, and a human-readable message. Approvers are notified by email. To observe the decision, the agent polls the airlock/check_status tool with the requestId (a poll interval of ~15s is suggested). Clients that implement SEP-1686 tasks can instead poll tasks/get with the returned taskId, and clients that implement SEP-1036 elicitation can prompt the human user to open the approvalUrl directly.

Tool Mapping

OpenAPI operations map to MCP tools:

OpenAPIMCP Tool
operationId: list_usersTool name: list_users
summary: List all usersTool description
Request body schemaTool inputSchema
Path parametersAdded to inputSchema.properties
Query parametersAdded to inputSchema.properties

Error Handling

Errors are returned as JSON-RPC errors:

{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32602,
    "message": "Invalid params",
    "data": {
      "field": "limit",
      "reason": "must be positive integer"
    }
  }
}

Error Codes

CodeMeaning
-32700Parse error
-32600Invalid request
-32601Method not found
-32602Invalid params
-32603Internal error

Rate Limiting

Airlock does not enforce a request-count cap on the MCP endpoint — request counts are tracked for analytics only (surfaced on the Usage and Analytics pages). Runtime spend is instead bounded per integration by token budgets: when an integration's hard token limit is crossed, its tool calls return an error until the budget resets or is raised.