MCP Protocol
The Model Context Protocol (MCP) is the primary interface for AI agents interacting with Claw GRC. MCP provides a structured session-based protocol with authentication, authorization, tool invocation, and audit logging built in.
Protocol Overview
MCP follows a three-phase lifecycle:
Phase 1: Handshake
The handshake establishes a session and returns the available tools.
Request
POST /api/v1/mcp/handshake
Content-Type: application/json
X-API-Key: cgrc_...
{
"agent_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"protocol_version": "1.0",
"capabilities": ["grc.list_frameworks", "grc.create_finding"]
}
| Field | Type | Required | Description |
|---|---|---|---|
agent_id | string (UUID) | Yes | The registered agent's ID |
protocol_version | string | Yes | Must be "1.0" |
capabilities | string[] | Yes | Tools the agent intends to use |
Response (201 Created)
{
"session_id": "mcp_xK9mP2vB7nQ4wR8sT1uY3cE5fG6hJ",
"status": "active",
"supported_tools": [
"grc.list_frameworks",
"grc.get_compliance_score",
"grc.create_finding",
"grc.create_ticket",
"grc.list_findings",
"grc.trigger_scan",
"grc.call_agent",
"grc.discover_agents"
],
"expires_at": "2025-01-15T15:30:00Z"
}
Handshake Validation
The server validates:
- Authentication -- The API key must be valid and belong to an active agent
- Agent status -- The agent must be
active(notinactive) - Protocol version -- Must be
"1.0"(the only supported version) - Organization match -- The agent must belong to the authenticated organization
Error Cases
| Status | Error | Description |
|---|---|---|
| 400 | Agent not found | The agent ID does not exist in this organization |
| 400 | Agent is inactive | The agent has been deregistered |
| 400 | Unsupported protocol version | Only "1.0" is supported |
| 401 | Unauthorized | Invalid or missing API key |
Phase 2: Message (Tool Invocation)
Once a session is established, the agent sends tool invocations as messages.
Request
POST /api/v1/mcp/message
Content-Type: application/json
X-API-Key: cgrc_...
{
"session_id": "mcp_xK9mP2vB7nQ4wR8sT1uY3cE5fG6hJ",
"method": "grc.list_frameworks",
"params": {
"limit": 10,
"offset": 0
}
}
| Field | Type | Required | Description |
|---|---|---|---|
session_id | string | Yes | The session ID from the handshake |
method | string | Yes | The MCP tool to invoke |
params | object | Yes | Tool-specific parameters |
Response (200 OK)
Success:
{
"session_id": "mcp_xK9mP2vB7nQ4wR8sT1uY3cE5fG6hJ",
"result": {
"frameworks": [...],
"total": 11
},
"error": null
}
Tool error (authorization failure):
{
"session_id": "mcp_xK9mP2vB7nQ4wR8sT1uY3cE5fG6hJ",
"result": null,
"error": {
"code": "permission_denied",
"message": "Agent does not have capability for tool 'grc.trigger_scan'"
}
}
Message Validation
The server validates:
- Session exists -- The session must be in the database and not expired
- Session ownership -- The authenticated actor must be the session owner (prevents cross-session hijacking)
- Session not expired -- Sessions expire 1 hour after creation
- Method recognized -- The method must be one of the supported MCP tools
- Capability authorized -- The agent's registered capabilities must include the requested tool
- Payload size -- The
paramsfield must not exceed 64KB
Error Cases
| Status | Error | Description |
|---|---|---|
| 400 | Session not found or expired | The session has expired or does not exist |
| 400 | Unknown method | The tool name is not recognized |
| 403 | Caller does not own this session | Cross-session access attempt detected |
| 413 | Tool params too large | Payload exceeds 64KB limit |
Phase 3: Close
Close a session to release resources and record the closure.
Request
DELETE /api/v1/mcp/sessions/{session_id}
X-API-Key: cgrc_...
Response (204 No Content)
No body is returned. The closure is logged in the audit trail.
Error Cases
| Status | Error | Description |
|---|---|---|
| 404 | Session not found | The session does not exist or is already closed |
Session Management
Session Lifetime
Sessions expire 1 hour after creation. Each tool invocation extends the session activity timestamp, but the expiration is based on creation time, not last activity.
Listing Active Sessions
You can list all active sessions for your organization:
GET /api/v1/mcp/sessions
X-API-Key: cgrc_...
# Response
{
"sessions": [
{
"session_id": "mcp_...",
"agent_id": "uuid",
"status": "active",
"created_at": "2025-01-15T14:30:00Z",
"expires_at": "2025-01-15T15:30:00Z",
"last_active_at": "2025-01-15T14:45:00Z"
}
],
"total": 1
}
Tool Discovery
Agents can discover available tools before opening a session:
GET /api/v1/mcp/tools
X-API-Key: cgrc_...
# Response
{
"tools": [
{
"name": "grc.list_frameworks",
"description": "List available compliance frameworks for the organization",
"input_schema": {...},
"output_schema": {...}
}
],
"total": 8
}
Security Considerations
Session Ownership
MCP enforces strict session ownership. The session is bound to the actor who created it (identified by the API key). If a different actor attempts to use a session (e.g., due to a leaked session ID), the request is rejected with a 403 Forbidden error.
Per-Tool RBAC
Each tool invocation is checked against the agent's registered capabilities. An agent registered with ["grc.list_frameworks"] cannot invoke grc.create_finding, even if it knows a valid session ID.
Audit Logging
Every MCP operation (handshake, message, close) is logged to the agent_interactions table with:
- The interaction type (e.g.,
mcp.handshake,mcp.tool.grc.list_frameworks,mcp.session_closed) - The request and response payloads
- Duration in milliseconds
- A chain hash linking to the previous interaction
Payload Size Limits
The params field in message requests is limited to 64KB to prevent abuse. Requests exceeding this limit receive a 413 response.
Session Storage
MCP sessions are stored in PostgreSQL (not in-process memory), which means:
- Sessions survive Cloud Run restarts and scale-to-zero events
- Sessions are consistent across multiple service instances
- No sticky session routing is required