RBAC Design for MCP Tool Access in Regulated Enterprises
Dynamic tool discovery breaks static permission models designed for fixed resource inventories.

MCP (Model Context Protocol) lets AI agents discover and call tools at runtime instead of build time. That one design choice breaks the assumptions behind conventional role-based access control (RBAC), and any regulated enterprise rolling out MCP without rethinking permissions from scratch is carrying a risk most security teams haven't priced in yet.
The mechanism is simple enough to state in two steps. An agent connects to an MCP server, calls tools/list, and gets back whatever that server currently exposes. Then it calls tools/call over JSON-RPC to actually run something. Nothing in that flow checks whether the agent, or the person behind it, should even see a given tool in the first place. If you can connect to the server, you see everything it lists. An agent provisioned for one function can end up with visibility into tools meant for an entirely different role. The protocol's openness is the permission surface, and by default it's wide open.
Traditional RBAC was built for a different shape of problem. It binds a user or a service account to a fixed, countable resource: this file, this database row, this API endpoint. You provision the role once, and the resource list barely moves. MCP doesn't work that way. Tool registries grow. Servers change tool definitions on the fly. An agent might be talking to dozens of servers exposing hundreds of tools, and a role granted at 9 a.m. can be covering a completely different tool set by 2 p.m. You can't statically provision access to something that gets discovered mid-session.
Three problems fall out of this, and each one demands something RBAC, as traditionally built, just doesn't do. Tool-call depth means permissions can't stop at gating the server connection, they have to gate each individual call inside it. Agent identity means the thing making the request isn't a person with an HR record and a manager, it's an LLM session whose identity has to be built and passed along on purpose. And dynamic discovery means the list of available tools is a moving target, not a fixed inventory you check once and forget.
None of this makes RBAC the wrong tool. It means the unit of access has to shift, from "can this connect to that server" down to "can this specific call happen right now," and the decision has to get made outside the model itself.
What the MCP specification now actually says about identity and authorization
The MCP spec is upfront about what it doesn't do: it doesn't enforce security at the protocol level. That job belongs entirely to whoever deploys it. The spec's own history shows how much identity groundwork is already laid, and how much is still homework for the enterprise.
The June 2025 update formalized the OAuth 2.1 Authorization Code flow with PKCE. Under this model, MCP servers act as OAuth resource servers: they check tokens, they don't hand them out. That's a real shift on its own.
The November 2025 spec went further. PKCE became mandatory for every client, not optional. OAuth 2.0 Protected Resource Metadata (RFC 9728) became required for server discovery, and authorization servers now have to expose either OAuth 2.0 Authorization Server Metadata (RFC 8414) or OpenID Connect Discovery 1.0. Step-up authorization showed up for the first time too: if a request comes in without enough privilege, the server can respond with a 403 and a WWW-Authenticate header spelling out exactly which scopes are missing, instead of failing silently or, worse, letting it through.
That same November release introduced Client ID Metadata Documents (CIMD), where a client describes itself through a URL it controls, plus the Enterprise-Managed Authorization extension, which kills off per-app OAuth consent prompts by routing token issuance through the enterprise identity provider (IdP) instead.
By June 18, 2026, that extension was declared stable. Per Paul Carleton, a core maintainer on the project, adoption is already underway across Anthropic, Microsoft, Okta, and a growing list of MCP servers.
So what does this actually buy an RBAC designer? The enterprise IdP becomes the source of truth. A user logs in once, and the IdP provisions access to whichever MCP servers that user is entitled to. Every access decision lives in one admin console with one audit trail, instead of scattered across a dozen OAuth consent screens nobody remembers approving. This is also the seam where existing role assignments plug in: SSO groups map straight to server entitlements.
Read the fine print, though. None of this gets you tool-level scoping inside a server. It doesn't give you an agent identity distinct from the human user's identity. And it gives you no way to catch that a tool's definition changed after a role was granted. The spec hands enterprises solid identity plumbing. The RBAC architecture built on top of it is still the enterprise's job to build, and most haven't started.
How rug-pull attacks and tool poisoning expose the limits of one-time permission grants
MCP servers can update a tool's definition without telling the client, and most clients never notice. That's the crack both attack types climb through. A role approved at install time might be governing completely different tool behavior by the next session, and nothing in the architecture flags the change.
That's the rug-pull pattern in plain terms. A tool behaves exactly as advertised when it's first installed, earns trust and permissions, then quietly changes what it does. This isn't hypothetical: Disclosed vulnerabilities in production AI development environments have confirmed that tool approvals don't survive later server-side changes. You approve a tool once. The server changes it later. As far as the system's concerned, your approval still stands.
Tool poisoning is a related but separate problem. Invariant Labs demonstrated in April 2025 that a single poisoned tool description, just the metadata, not even the tool's actual function, could pull private repository contents and message histories out with zero user interaction required. The class of attack has been recognized across the security research community as carrying critical-level risk.
RBAC has no answer for either of these, and it's worth being blunt about why: it authorizes based on a role-to-tool binding made once, at grant time, with no built-in way to re-check whether the tool's definition still matches what got approved. Tool poisoning makes this worse because it lives in natural-language metadata, descriptions, embedded prompts, that kind of thing. RBAC's structured permission model was never built to read prose and judge intent. Firewalls and network boundaries don't help either, because these attacks work at the semantic layer, inside language, not at a network edge anyone's watching.
The scale of the exposure is worth sitting with. Research into real-world MCP servers has found attack success rates that are alarmingly high across tested deployments. That's not an edge case, that's a coin flip tilted the wrong way, and it means tool-level RBAC alone isn't enough. It has to be paired with ongoing checks that tool definitions haven't quietly shifted underneath the grant.
One mitigation already exists: the Enhanced Tool Definition Interface (ETDI) framework binds each tool definition to a signed token. Change the tool definition, even slightly, and the signature breaks. The rug-pull becomes visible instead of invisible.
Knowing how these attacks actually work is what tells you what the permission architecture needs to check continuously, not just what it needs to approve once.
The three-layer permission model MCP deployments actually need
Closing this gap takes three layers working together. Pick one and call it done, and you've built a system with a known hole in it.
Layer 1: server-level access. This answers who can connect to which MCP server, handled through the Enterprise-Managed Authorization extension. IdP group membership maps to server entitlements: engineering gets the GitHub and code-execution servers, finance gets the ERP integrations. SSO, SCIM group sync, and just-in-time provisioning do the actual work here, all managed from the IdP admin console.
Layer 2: tool-level access inside a server. This is where conventional RBAC has to stretch further than it's used to. A developer role might invoke both documentation tools and code-search tools, while a contractor role, connected to that exact same server, gets locked to documentation only. OAuth 2.1 scopes carry that distinction: token claims map to specific permitted tools and resources, and the MCP server checks those scopes at the moment of the call. Step-up authorization, from the November 2025 spec, lets the system escalate on the fly when a tool needs more privilege than the current token has, responding with an error that spells out exactly which scopes are missing instead of quietly failing or quietly succeeding. Neither the client nor the server should be holding the role logic directly. Both defer to the token.
Layer 3: tool-definition integrity. This layer checks that the tool actually being invoked is the same tool that got authorized in the first place. ETDI's signed JWTs do this by binding the tool definition under one signature. Change the tool server-side, and the signature breaks. A gateway or client catches the mismatch before the call executes, not after the damage is done.
Most MCP deployments today sit at Layer 1 alone, which means any agent that can connect to a server sees the entire tool catalog behind it. Add Layer 2 without Layer 3 and rug-pull attacks still walk right through, since a stale approval can't tell a changed tool from an honest one. Layer 3 without the other two just gives you integrity checks on tools nobody should have had access to in the first place. None of the three substitutes for the others.
Choosing the right authorization model for tool-call depth: RBAC, ABAC, and ReBAC
RBAC earns its keep when the tool surface holds still, roles map cleanly onto tool sets, and nobody needs record-level granularity. The developer-versus-contractor documentation split from Layer 2 is a textbook RBAC case: clean lines, stable roles, no ambiguity. But RBAC is also the model most teams reach for by default when it's the wrong fit, because it can't see inside a call. It says yes to the tool and hands out access it has no way to qualify further.
That's where ABAC picks up the slack, granting or denying access based on attributes instead of fixed roles. It pulls in context a role alone can't carry: attributes of the action itself (which command, which record), attributes of the requester (department, account status, role), and attributes of the environment (time of day, IP address, whether the device is trusted). For MCP specifically, that means the exact tool being called, the parameters passed into that call, and whatever intent the agent's session declared going in. In enterprise AI circles this often goes by PBAC, Policy-Based Access Control, and it borrows an idea already common in microservice API authorization: pull the decision logic out of the server and hand it to a dedicated Policy Decision Point (PDP).
ReBAC handles the layer below the tool boundary: the actual records, granting access based on relationships between users and resources. A Zanzibar-style check, run through something like OpenFGA or Okta FGA, sits at the gateway and asks a narrower question. Does this agent, acting for this particular user, have a relationship to this specific record that justifies this specific operation? A CRM tool might be entirely in-scope for a sales role at the tool level, but a ReBAC check can still say no to that role touching a particular account it doesn't own. This pattern is already being implemented in MCP gateway tooling, making it a present-day architectural option rather than a future one.
For a regulated enterprise, don't try to stand up all three at once, and don't treat them as competing choices, because they're not. Start with RBAC across Layers 1 and 2, mapping server entitlements and tool scopes through IdP groups. Layer in ABAC at the PDP once the authorization decision needs to account for call parameters, session state, or timing. Add ReBAC once individual record ownership or organizational hierarchy needs to gate what a tool can touch after it's already been cleared to run. A dedicated policy engine at the PDP layer can run a check against every tool call before it fires.
Why the MCP gateway is the only viable enforcement point for tool-call RBAC
A production agent might connect to dozens of MCP servers exposing hundreds of tools combined, and most setups today still run on one credential covering the whole fleet. Pushing enforcement down into each individual agent doesn't fix that, it just recreates the same fragmentation at a different layer.
A gateway sitting between the agent and every server it talks to does what neither the agent nor the individual server can pull off alone. It inspects every tools/list response before that list reaches the model, applying zero-trust screening to discovery itself, not just execution. It applies role-based allow-lists at the schema level, before the LLM ever sees a tool description, which matters because a poisoned description can't influence a model that never gets shown it. It runs hooks before and after each call: validating parameters against the JSON-RPC schema going in, sanitizing and redacting PII coming back out, scoring tool reputation in real time. And it enforces which MCP servers are allowed at all, centrally, so a developer's local config can't quietly open a door the security team never approved.
There's a performance argument here too, not just a security one. An agent holding access to an entire database schema doesn't just carry more risk, it performs worse. Extra tools sitting in front of an LLM increase cognitive load on the model and raise the odds it picks the wrong tool for the job. Gateways that trim the tool list down to what a given user's intent and session actually need cut down on both problems in the same move: tighter security, better accuracy, no tradeoff between them.
The architecture that holds up under audit looks like a deterministic governance layer sitting entirely outside the model. Identity and RBAC tokens get propagated through it, budget controls run on a sliding window, policy gets checked statically through something like OPA/Rego, and anything high-stakes gets routed to a human before it executes.
A handful of named tools are already building toward this pattern. Bifrost, from Maxim AI, is an open-source AI gateway doing tool filtering through virtual keys. Zuplo's MCP Gateway curates tools per route and offers a relationship-based access control model as a beta enterprise feature. Lasso Security runs an MCP Gateway of its own. Cisco AI Defense publishes mcp-scanner as an open-source project on GitHub. eqtylab's MCP Guardian, also open source, manages, proxies, and secures MCP server connections directly.
Evaluating any of these for a regulated environment comes down to three questions. Does it enforce at the level of the individual tool call, not just the server connection? Does it plug into the existing IdP through SSO and SCIM? And does it produce audit logs, tamper-proof ones, tied to specific tool invocations rather than just connection events?
Agent identity is not user identity, and RBAC designs that conflate them fail
This is where a lot of otherwise well-designed RBAC rollouts quietly break. A human logs in through SSO, and the agent that human launches inherits a broad credential built for that human's job function, not scoped down to the one task the agent is actually running, the session it's in, or the specific tools that task needs. The permission is shaped for the person. The thing exercising it is not the person, and treating the two as interchangeable is the mistake underneath almost every over-permissioned agent in production today.
An agent is a piece of software, not a user with a badge and a manager who can vouch for it. It's a session, spun up for a purpose, that should get exactly the access that purpose needs and nothing left over once the session ends. Get that distinction wrong, and no amount of policy sophistication at Layers 1 through 3 saves the design, because the token being checked was never scoped to the thing actually making the call.
Treat agent identity as a smaller, sharper version of user identity: scoped to the task, expiring with it, rebuilt fresh for the next session rather than inherited wholesale. Do that, and the rest of the permission model, all three layers of it, finally has something solid to enforce against.


