Agent Security Architecture
What is Agent Security?
Agent Security delivers permissions-as-a-service for any Model Context Protocol (MCP) server. It acts as a proxy/gateway between AI agents and the MCP server resources they interact with, providing:
- Fine-grained ReBAC (relationship-based access control) powered by Permit.io (which uses OPA and OPAL under the hood)
- Authentication & authorization that binds user, agent, MCP server, and downstream service identities
- Comprehensive auditing covering every tool call, user, and agent
- Flexible deployment options (hosted gateway available), all using the same policy rules
A single URL switch yields consistent enforcement, instant visibility, and human-in-the-loop (HITL) approvals — no code changes to agents or servers.
System Architecture Overview
Key components:
- Platform (
app.agent.security): Admin interface for managing hosts, MCP servers, and user access - Edge Router (NGINX): Routes requests by path to Gateway or Consent Service
- Gateway (
*.agent.security/mcp): MCP proxy that enforces authorization on every tool call - Consent Service (
*.agent.security): Handles OAuth login, user consent, and upstream MCP OAuth - Permit.io PDP: Policy decision point for real-time authorization checks
- Redis: Session and host configuration store (accessed only by Gateway)
- PostgreSQL: User accounts, OAuth clients, and auth sessions
The Consent Service does not access Redis directly. All state persistence goes through the Gateway Admin API, centralizing Redis schema and logic in the Gateway.
Data Flow
The diagram below shows where data lives and how it flows between components:
| From | To | Protocol | Notes |
|---|---|---|---|
| ALB | NGINX | HTTP/1.1 | TLS terminated at ALB |
| NGINX | Gateway | HTTP/1.1 (port 8001) | Routes: /mcp, /oauth/*, /.well-known/* |
| NGINX | Consent Service | HTTP/1.1 (port 3000) | Routes: /api/auth/*, /api/consent/*, /api/mcp/*, /login, /consent |
| Consent Service | Gateway Admin API | HTTP/1.1 + Bearer (port 8002) | Sessions, OAuth states, pending tokens |
| Gateway | Redis | RESP (port 6379) | Only Gateway has direct Redis access |
| Consent Service | PostgreSQL | PostgreSQL (port 5432) | Users, sessions, OAuth clients |
| Gateway | Consent Service (JWKS) | HTTP (port 3000) | JWT signature verification |
| Gateway | Permit.io | HTTPS | Authorization checks (Cloud PDP) |
| Consent Service | Permit.io | HTTPS | Policy sync during consent |
| Gateway | Upstream MCP | HTTPS | Streamable HTTP with upstream OAuth tokens |
Integration Patterns
Agent Security is available as a hosted gateway deployment:
| Pattern | When to Use | How It Works |
|---|---|---|
| Hosted Gateway | Fastest rollout; SaaS workloads | Point agents/MCP clients to https://<host>.agent.security/mcp |
Policy Model
Trust-Level Access Control
Agent Security classifies each tool into a trust level based on its risk:
- Low trust — everything else (read-only by convention); this is the default for tools not matching medium or high patterns
- Medium trust — write operations (tools containing:
create,write,update,set,modify,edit,put,post,insert,add,send,execute,run,invoke,submit,push,publish,deploy,apply,patch) - High trust — destructive operations (tools containing:
delete,remove,destroy,drop,purge,erase,truncate,terminate,kill,revoke)
Trust levels are hierarchical: higher levels inherit all permissions from lower levels.
Policy Architecture
Agent Security automatically generates Google-Zanzibar-inspired ReBAC (Relationship-based Access Control) policies based on:
- Defined roles for users and agents
- MCP server resource instances
- Agent roles derived from the user's consent choices
- A
user_profileresource that links each user to the agents acting on their behalf, enabling relationship-based permission derivation through a 3-way chain: Agent --role on--> UserProfile --relation to--> MCP Server. The effective permission on a server is derived asmin(agent_role_on_profile, profile_relation_to_server)— meaning a human's profile relation acts as a ceiling on the trust level any agent can actually exercise, regardless of what trust level was granted during consent.
Each MCP server maps to a Permit resource type whose key is the server key (e.g., linear). The server's tools become actions on that resource, using slugified tool names (e.g., create_issue). There are no separate resource instances per tool — the server itself is both the resource type and instance.
The diagram below shows the logical relationship between agents and server resources. The actual Permit model uses a 3-way derived chain through a user_profile intermediary: Agent --role on--> UserProfile --relation to--> MCP Server, with effective permission = min(agent_role, profile_relation). See the Authorization: Trust Ceiling section below for the full model.
Authentication & Authorization
How it Works
Admin setup (one-time via Platform UI):
- Admin signs in to the Platform UI at app.agent.security and creates a host linked to a Permit environment
- Admin imports upstream MCP servers through the Platform, which configures the Gateway and syncs policies to Permit
- Admin grants specific users permission to connect to specific MCP servers via the Platform's Humans page
User connection (first time):
- The MCP client discovers the gateway's OAuth endpoints
- The user authenticates and signs in
- The user selects an MCP server from the list of servers the admin has granted them access to
- If the upstream MCP server requires OAuth, the user authorizes with the upstream provider
- The user chooses the trust level they want to grant their agent, up to the maximum the admin configured
- The gateway issues a JWT access token to the MCP client
On subsequent tool calls:
- The gateway verifies the JWT and identifies the agent
- The gateway checks Permit: "Can this agent call this tool on this MCP server?"
- Allowed calls are proxied; denied calls return a permission denied error
Identity format: The gateway constructs a user key for the Permit check based on the caller type:
- Human users:
human|{subject}— wheresubjectis the authenticated user's identity. This format is used by the consent service and platform for policy management (e.g., granting a user access to MCP servers). - Agents:
agent|{client_id}— whereclient_ididentifies the agent acting on behalf of the user. This format is used at runtime by the gateway for tool-call authorization checks.
Sequence: Admin Setup Flow
The admin creates a host through the Platform UI by selecting a Permit project and environment. The Platform resolves the environment's API key, provisions the host configuration in the Gateway, and stores it in Redis.
Sequence: User Consent Flow
When a user connects for the first time, the MCP client discovers OAuth endpoints, the user authenticates and consents, and if the upstream MCP server requires OAuth, that flow is handled transparently.
By default, users can only connect to MCP servers that the admin has pre-configured and granted them access to — the consent service validates that every upstream URL matches a server the user is authorized to use. However, if the admin enables Dynamic MCPs on the host, users can also enter arbitrary upstream MCP server URLs during the consent flow. See Dynamic MCPs below.
Sequence: Authorization Decision Flow
When a tool call arrives at the Gateway, it passes through a multi-step middleware chain before reaching the upstream MCP server.
The gateway returns all tools in list_tools responses regardless of the agent's trust level. Authorization enforcement happens exclusively at call_tool time — agents may see tools they cannot invoke.
Authorization: Trust Ceiling (min logic)
The effective permission on an MCP server is determined by the minimum of the agent's trust level and the human's profile relation to the server. This ensures a human's profile relation acts as a ceiling on what any agent can exercise.
How it works:
The system uses 9 derived role rules per MCP server to implement the min() logic through Permit's ReBAC:
| Agent role on profile | Profile relation to server | Effective server role |
|---|---|---|
{server}-high | high | high |
{server}-high | medium | medium (capped) |
{server}-high | low | low (capped) |
{server}-medium | high | medium |
{server}-medium | medium | medium |
{server}-medium | low | low (capped) |
{server}-low | high | low |
{server}-low | medium | low |
{server}-low | low | low |
The derived role then determines which tools are allowed:
- Low trust tools: available to
low,medium, andhighroles - Medium trust tools: available to
mediumandhighroles - High trust tools: available to
highrole only
Deployment
Agent Security is available as a hosted gateway at *.agent.security. Each host (tenant) gets a unique subdomain with isolated policies, users, and sessions.
Point your MCP clients to https://<host>.agent.security/mcp and the gateway handles the rest — authentication, authorization, and audit logging are all built in.
Key Advantages
- Single control point for authorization and audit
- Drop-in — no code changes, SDK optional
- Fine-grained ReBAC — captures true user-agent-resource relationships
- Policy-as-code — policies managed via UI and API, powered by OPA/Rego under the hood
- Short-lived creds — minimize blast radius
Agent Configuration Examples
Agent roles are automatically derived from the trust level selected during the user consent flow. The table below shows how different agents might be configured in practice.
Below is an example of how different agents end up with permissions based on the consent flow:
| Agent (MCP Client) | User | MCP Server | Trust Level Granted | Example Allowed Tools | Example Denied Tools |
|---|---|---|---|---|---|
| Cursor | alice | linear_mcp | Medium | get_issues, create_issue | delete_project |
| Claude Desktop | alice | github_mcp | Low | list_repos, get_file | create_issue, delete_repo |
| VS Code Copilot | bob | github_mcp | High | get_file, create_issue, delete_repo | (none — high includes all) |
| Claude Code | carol | slack_mcp | Medium | search_messages, send_message | remove_member |
Dynamic MCPs
Dynamic MCPs allow users to connect to any MCP server URL during consent, not just admin-provisioned servers. For setup instructions, see Platform: Dynamic MCPs.
How it works in Permit: The Consent Service creates per-user resource types for dynamic MCP servers, keyed as {serverKey}-{userId} with an mcp_server_type: "dynamic" attribute. The host-level toggle is enforced via a connect_dynamic_mcp action on the user_profile resource.
Glossary
| Term | Meaning |
|---|---|
| MCP | Model Context Protocol (tool/agent interoperability) |
| Originator | Human delegating authority |
| Agent | Autonomous MCP client acting on behalf of the user |
| Host | A named gateway instance with its own subdomain, policies, and sessions |
| Trust Level | Risk classification (low/medium/high) that determines which tools an agent can call |
| PDP | Policy Decision Point — evaluates authorization requests in real time |
| HITL | Human-in-the-loop |
| ReBAC | Relationship-based access control |
| OPAL | Open Policy Administration Layer |
| OPA | Open Policy Agent |