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-Tool | Description |
|---|---|
list_services | List all available integrations in the organization |
search_tools | Search for tools across all integrations by keyword |
describe_tools | Get detailed descriptions of specific tools |
execute_tool | Execute a tool on a specific integration |
activate_skill | Activate 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:
- Discover metadata:
GET /.well-known/oauth-authorization-server - Register client:
POST /register - Authorize: Redirect to
/mcp/authorizewith PKCE parameters - Token exchange:
POST /tokenwithgrant_type=authorization_code - Token refresh:
POST /tokenwithgrant_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"
}| Parameter | Lifetime | Notes |
|---|---|---|
| Access token | 8 hours | JWT, used in Authorization: Bearer header |
| Refresh token | 30 days | Opaque token, use to obtain new access tokens |
| ID token | 8 hours | JWT 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.instructionsandresult._airlock.skills, but only clients that forwardinitialize.result.instructionsto 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 dropresult.instructions, instruct the agent in its system prompt to callairlock-management/list_skills(viaexecute_tool) beforeactivate_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, ataskId, theapprovalUrl, and a human-readablemessage. Approvers are notified by email. To observe the decision, the agent polls theairlock/check_statustool with therequestId(a poll interval of ~15s is suggested). Clients that implement SEP-1686 tasks can instead polltasks/getwith the returnedtaskId, and clients that implement SEP-1036 elicitation can prompt the human user to open theapprovalUrldirectly.
Tool Mapping
OpenAPI operations map to MCP tools:
| OpenAPI | MCP Tool |
|---|---|
operationId: list_users | Tool name: list_users |
summary: List all users | Tool description |
| Request body schema | Tool inputSchema |
| Path parameters | Added to inputSchema.properties |
| Query parameters | Added 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
| Code | Meaning |
|---|---|
| -32700 | Parse error |
| -32600 | Invalid request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal 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.