Skip to content

MCP Protocol

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 servers in your organization through meta-tools:

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

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:

json
{
  "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}
json
{
  "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:

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

Response:

json
{
  "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:

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

Response:

json
{
  "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:

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

Response (success):

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

Response (approval required):

json
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"status\": \"PENDING_APPROVAL\", \"requestId\": \"abc123\", \"statusUrl\": \"https://control-room.air-lock.ai/requests/abc123\", \"approvalUrl\": \"https://control-room.air-lock.ai/requests/abc123\", \"pollIntervalSeconds\": 15, \"message\": \"This operation requires approval. An approver has been notified.\"}"
      }
    ]
  }
}

TIP

The approval response contains a structured JSON object with URLs for checking status and a suggested pollIntervalSeconds. Approvers are notified by email; the agent observes the decision by polling the status URL or, if the client implements SEP-1686 tasks, by polling tasks/get with the returned taskId. Clients that implement SEP-1036 elicitation can prompt the human user to open the approval URL 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:

json
{
  "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

Organizations have monthly request limits. When exceeded:

json
{
  "jsonrpc": "2.0",
  "id": 3,
  "error": {
    "code": -32603,
    "message": "Rate limit exceeded"
  }
}

Built with VitePress