Integration
AIControl integrates as a gateway. Your agent's MCP client points at
/mcp/{server_id}/... instead of the real downstream MCP server. AIControl
evaluates Cedar policy on every tools/list and tools/call, audits the
result, and forwards allowed calls to the real server.
The integration pattern
Admin registers the downstream server once
↓
POST /mcp-servers → {"id": "<server_id>", "status": "pending_review"}
↓
PATCH /mcp-servers/<server_id> {"status": "active"}
↓
Agent's MCP client points at /mcp/<server_id>/
↓
Agent calls tools/list or tools/call
↓
AIControl evaluates Cedar policy, writes the audit event
↓
allow → forwarded to the real downstream server, response returned
deny → JSON-RPC error result returned, never forwarded
review → a human has been notified (Slack, if configured); JSON-RPC error
result returned immediately — your agent does not waitEvery call — regardless of decision — is written to the audit log before the response is returned.
Registering a downstream server
Registration is admin-only and metadata-only — no credential is stored on the
row. Whatever Authorization header your agent sends on the gateway call is
forwarded to the downstream server unchanged (pure passthrough).
curl -X POST http://your-aicontrol-host:8001/mcp-servers \
-H "Authorization: Bearer $AICONTROL_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "invoicing-mcp", "base_url": "https://invoicing.internal/mcp", "approved_tools": ["get_invoice", "create_invoice"]}'Response 201:
{
"id": "3f2a1c8b-...",
"name": "invoicing-mcp",
"base_url": "https://invoicing.internal/mcp",
"status": "pending_review",
"approved_tools": ["get_invoice", "create_invoice"],
"created_at": "2026-09-09T10:00:00Z"
}New registrations start in status: "pending_review" and are not reachable via
the gateway until activated:
curl -X PATCH http://your-aicontrol-host:8001/mcp-servers/<server_id> \
-H "Authorization: Bearer $AICONTROL_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "active"}'status is one of pending_review, active, or blocked. The gateway
rejects any call to a server that isn't active with 403.
approved_tools on the server registration (separate from the per-agent
approved_tools set via PATCH /agents/{agent_id}/approved-tools) scopes
which of the downstream server's tools are visible/callable through this
gateway at all — an empty list means every tool the downstream server exposes
is reachable, subject to Cedar policy and the agent's own approved-tools list.
Environment setup
AICONTROL_URL=http://your-aicontrol-host:8001 # required
AICONTROL_TOKEN=eyJhbGc... # required — agent-scoped JWTGateway calls require an agent-scoped token — a token issued with
agent_id set (via scripts/onboard_agent.py or POST /tokens with
agent_id). An admin token, or an agent-role token issued without an
agent_id, is rejected with 403 — the gateway derives caller identity
entirely from the token, so it must be attributable to exactly one registered
agent.
Pointing your MCP client at the gateway
Configure your agent's MCP client with:
- URL:
http://your-aicontrol-host:8001/mcp/<server_id>/ - Auth header:
Authorization: Bearer <agent-scoped-token>
From there, standard MCP protocol calls apply.
The tools/list request
POST /mcp/{server_id}/tools/list
Authorization: Bearer <agent-scoped-token>
Content-Type: application/json{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}Response: the downstream server's own tools/list response, filtered to the
server registration's approved_tools if that list is non-empty.
If the downstream server is unreachable, AIControl returns a JSON-RPC error rather than forwarding a timeout or connection error upstream to your agent:
{"jsonrpc": "2.0", "id": 1, "error": {"code": -32000, "message": "Downstream MCP server unreachable"}}The call_tool request
POST /mcp/{server_id}/call_tool
Authorization: Bearer <agent-scoped-token>
Content-Type: application/json{
"jsonrpc": "2.0",
"id": 1,
"params": {
"name": "query_credit_bureau",
"arguments": {
"applicant_id": "A-10042",
"report_type": "full"
},
"session_id": "b3e1f9a2-...",
"sequence_number": 3,
"workflow": "loan_application_review",
"input_tokens": 812,
"output_tokens": 143,
"cost_usd": 0.0091
}
}Field (under params) | Type | Required | Notes |
|---|---|---|---|
name | string | yes | The tool being called — matched against policies |
arguments | object | yes | Full tool arguments; stored in the audit record |
session_id | UUID | yes | Groups all tool calls within one agent run. Missing or invalid returns a -32602 JSON-RPC error |
sequence_number | integer | yes | Call order within the session. Missing or invalid returns a -32602 JSON-RPC error |
workflow | string | no | Business-process workflow name. Defaults to "unassigned" if omitted |
input_tokens / output_tokens / cost_usd | number | no | Feed token_budget policy conditions — omit them and any such policy never fires for this call, since there's nothing to sum |
Generate session_id once per agent run, not per tool call — reuse it across
every call in that run so calls group correctly in the audit log and so
session-scoped rate-limit/budget policies accumulate correctly.
The call_tool response
Allowed, forwarded successfully — the downstream server's own
tools/call response is returned unchanged:
{
"jsonrpc": "2.0",
"id": 1,
"result": {"content": [{"type": "text", "text": "..."}]}
}Denied by an agent-level approved-tools gate, a Cedar policy, or a response
scan — a JSON-RPC result with isError: true, not an HTTP error:
{
"jsonrpc": "2.0",
"id": 1,
"result": {"content": [{"type": "text", "text": "Denied by policy: policy_matched:block_dangerous_tools"}], "isError": true}
}Routed to human review — same isError: true shape, with a message
naming the pending review; your agent does not receive a review_id field to
poll on today — check the dashboard's Reviews page for pending items instead:
{
"jsonrpc": "2.0",
"id": 1,
"result": {"content": [{"type": "text", "text": "Pending human review: policy_matched:require_review_for_external_calls"}], "isError": true}
}Malformed request (session_id or sequence_number missing/invalid) — a
JSON-RPC protocol-level error, not a result:
{"jsonrpc": "2.0", "id": 1, "error": {"code": -32602, "message": "Invalid params: session_id is required"}}Downstream server unreachable — same fail-closed error as tools/list:
{"jsonrpc": "2.0", "id": 1, "error": {"code": -32000, "message": "Downstream MCP server unreachable"}}Response scanning
After a call is forwarded and the downstream server responds, AIControl scans
the response before returning it to your agent (app/services/response_scanner.py
— the same deterministic, pattern-based scanner used elsewhere in the product,
not an LLM). A flagged response is blocked with isError: true even though
the downstream call itself already happened and was already audited as
allowed at the policy-evaluation step — the block is logged as a second audit
event with decision_reason: response_scan_flagged:<category>.
Handling responses in your agent
Check result.isError on every call_tool response. true means the tool
did not execute as your agent expects — treat it the same way you'd treat a
denied tool call from any policy engine: don't retry blindly, and surface the
text content (which names the policy or reason) to whatever is orchestrating
the agent.
Checklist: integration complete
✓ AIControl deployed and verify.sh passes
✓ Downstream server registered (POST /mcp-servers) and status set to "active"
✓ Agent-scoped token issued (scripts/onboard_agent.py or POST /tokens with agent_id)
✓ MCP client pointed at http://your-aicontrol-host:8001/mcp/<server_id>/
✓ session_id generated once per agent run, reused across tool calls
✓ sequence_number increments with each tool call in the session
✓ result.isError checked on every call_tool response
✓ First call verified — audit event visible in dashboardFramework and platform guides
For MCP-client configuration notes per framework (LangChain, CrewAI, LangGraph, and others) and for the four named agent-platform insertion points (Amazon Bedrock, Azure AI Foundry, Vertex AI, Microsoft Copilot Studio), see Platform & Framework Guide and Platform Discovery.