Est.
MCP securityLong read

Principle of Least Privilege for MCP Server Permissions

Most MCP servers expose far more access than agents actually need to complete their tasks.

· 13 min read · Updated
Cover illustration for “Principle of Least Privilege for MCP Server Permissions”
MCP security · September 9, 2026 · 13 min read · 3,013 words

MCP servers let AI agents pull data and trigger actions across a company's tools, and right now, most of them hand out way more access than any single task needs. The Principle of Least Privilege has been standard practice in security for decades: give an account only what it needs, nothing more. Applying that idea to an AI agent is a different problem entirely, because the agent decides what to do at runtime, not at setup, and no human is standing there approving each move. This piece breaks down what least privilege actually requires when the actor making the call is a model, not a person, and where today's MCP deployments fall short of that standard.

Start with what MCP actually is. Released and open-sourced by Anthropic in November 2024, it's an open protocol built on JSON-RPC 2.0 that works over stdio or other transports like HTTP/SSE. It gives agents a standard way to discover and call tools across different services, which is exactly why it caught on so fast. But the same feature that makes MCP useful, letting an agent read internal data and take real actions, is what makes it risky. The moment an agent can touch a file system or fire off a database write, MCP stops being a convenience layer and becomes part of the control plane. That changes what's at stake if permissions are set wrong.

Three things separate this from a normal API or user-permissions problem. First, the model picks which tool to call and what parameters to pass, in real time, with no person clicking through a menu. Second, there's no dialog box moment, no pause where a human reviews the request before it fires. Third, an agent often talks to several MCP servers at once, so its real permission set isn't defined by any single server. It's the union of everything all of them expose, combined.

Early MCP implementations were built for connectivity, not defense. Security came later, almost as an afterthought, because the protocol assumed a mostly trusted local environment: one developer, one machine, low stakes. That assumption is gone. Enterprises now plug agents into file systems, production databases, cloud APIs, and SaaS platforms, so a misconfigured permission doesn't stay contained to a laptop. It reaches everything the server touches. Least privilege is still the right framework for this problem, but applying it to MCP means enforcing it at three levels at once: the server, the tool, and the exact moment a call gets made.

What least privilege actually means when the actor is an AI agent

The classic definition of least privilege is simple: give any account only the permissions it strictly needs to do its job, and nothing beyond that. Applied to an agent, this means giving it the minimum access required for the task in front of it, not the task it might have tomorrow. That last part is where things get complicated, because the task changes with every invocation. A permission scheme that made sense for last week's request might be dangerously broad for this one.

Least privilege has to be enforced at three distinct levels, and none of them substitute for the others.

At the server level, expose only the resources, prompts, and tools actually needed for the job, and default to read-only wherever the task allows it. At the tool level, scopes need to be defined per tool, not inherited automatically from the server, because a tool that reads files has no business carrying a scope that also lets it delete them. At the invocation level, authorization can't stop at login. Every single call needs its own check, because whatever the agent was cleared to do at the start of a session isn't a permanent grant for everything that follows.

The practical version of this is a progressive scope model. Agents should start with the smallest possible footprint and only request more when a task explicitly calls for it. Nobody should be front-loading broad permissions "just in case" the agent needs them later. That instinct, the same one that leads IT teams to hand new employees admin rights to save a support ticket, is exactly how MCP deployments end up over-permissioned by default.

The MCP specification gives implementers a lot of room to define how permissions work. That flexibility is a feature, not a flaw, but it comes with a catch: nothing about the spec narrows that flexibility automatically. Organizations have to do that work themselves, deliberately, or the default state is maximum access. Compare this to how permissions work for a human employee. A person's role might change once or twice a year, maybe with a promotion or a team move. An agent's effective role can change every few seconds, task by task. Static permissioning, the kind built for humans, was never designed to keep pace with that.

How badly the current permission baseline is failing in practice

Authentication is the floor underneath every other permission control, and right now that floor has holes in it across the industry.

Trend Micro found 492 MCP servers sitting exposed on the public internet with no authentication and no encryption at all, collectively exposing access to 1,402 tools. More than 90% of those allowed direct read access to whatever they connected to. Censys counted 12,520 internet-accessible MCP services, and most had no authentication in place. Knostic scanned 1,862 exposed MCP servers and found every single one had zero authentication. Not weak auth. Not misconfigured auth. None.

Zuplo's broader survey, covering more than 17,000 listed servers, found 41% still had no authentication as of February 2026. And of 3,012 MCP servers NimbleBrain analyzed, only 8.5% used OAuth. That's the authentication side of the picture, and it's bad enough on its own. But over-permissioning compounds it.

Most MCP servers ask for broad scopes because broad scopes are easier to build against. Full Gmail access instead of read-only. Full Google Workspace write permissions when the task only ever needed to read an email. Tokens tend to be long-lived and unscoped, and API keys typically default to full access unless someone specifically dials them back. CoSAI audited 17 MCP servers in 2026 and the group scored an average of 34 out of 100 on security.

The governance side isn't any better. Between 47% and 53% of organizations, per a Practical DevSecOps survey, have already had an AI agent exceed its permissions or cause a related incident. Only 23% of organizations have a formal identity strategy for AI agents at all. Just 14.4% of agents reach production with full security approval. And roughly half of organizations are actively experimenting with MCP servers, but only 11% have made it to production, according to industry surveys cited by Obot. That 39-point gap between experimentation and production is where most of the exposure sits right now: half-built deployments, temporary credentials that never got cleaned up, servers spun up for a demo and never locked down.

Gartner has predicted that 25% of enterprise breaches will trace back to AI agent abuse by 2028. That's not a distant hypothetical anymore. The window to fix the permission baseline before that prediction plays out isn't especially long.

The attack patterns that broad MCP permissions directly enable

Loose permissions don't just sit there as a theoretical risk. They enable specific, repeatable attack patterns, and several of them already have names and CVE numbers attached.

The confused deputy problem sits at the root of a lot of this. MCP doesn't inherently carry user context from the host application down to the server, so the server often can't tell one calling user from another. Everyone who reaches the server gets treated the same way, regardless of what that specific user was actually cleared to do upstream. A user with legitimate access to the server can end up invoking tools that exceed what they were ever supposed to touch. An agent calling a "delete contact" function succeeds even when the human it's acting for should only have read access to the CRM.

Tool poisoning is the sharper version of this problem, and two disclosed vulnerabilities from August 2025 show exactly how it works. CurXecute, tracked as CVE-2025-54135 and disclosed by AIM Security on August 1, 2025 with a CVSS score of 8.6, affected versions of Cursor before 1.3. A crafted Slack message, processed through an already-approved Slack MCP server, injected a payload that rewrote the global mcp.json config file and inserted a new, attacker-controlled server entry. Because Cursor auto-executed new MCP server entries without asking again, the payload ran on the very next IDE interaction. No further action needed from the victim.

MCPoison, CVE-2025-54136, disclosed by Check Point Research on August 5, 2025, hit teams through shared repository configs. It exploited a trust model that bound approval to a server's name rather than what the server actually contained. Once a team member approved a project-level config file, any later change to it, including swapping in a malicious server, inherited that original trust. No new prompt, no new approval. Both vulnerabilities point to the same root cause: broad, static trust grants are the precondition tool poisoning needs to work.

There's also the "rug pull" pattern that Simon Willison flagged in April 2025: MCP tools can redefine themselves after a user already approved them. A tool that looked safe on day one can quietly change its own behavior and start rerouting API keys to an attacker by day seven, with no re-approval step in between.

OWASP's Top 10 for LLM Applications names excessive agency as a critical risk category, and it maps onto MCP almost exactly — covering scenarios where agents have more functionality, broader permissions, or more autonomy than any given task warrants.

Credential sprawl adds another layer on top. Developers stash API keys in .env files, in mcp.json configs, in environment variables scattered across however many machines they've worked on. Static keys don't expire on their own, and when a developer leaves a company, their MCP credentials frequently just... stay active. GitGuardian's 2026 State of Secrets Sprawl report documented 28.65 million secrets exposed on public GitHub in 2025 alone, with a fivefold acceleration in that trend attributed specifically to AI agents.

And local STDIO servers carry no authentication by default. Any user who can prompt the AI can invoke any tool it has access to, unless someone has manually added controls on top. Security researchers have described these setups as effectively open to anyone in an organization who knows they're there. Across every one of these attack patterns, the common thread is identical: permissions got granted at a coarse level, once, and nobody ever went back to check them again.

What the MCP specification actually provides for permissions, and what it leaves to implementers

The spec has made real progress here, but progress isn't the same as coverage.

Tool annotations arrived in the March 26, 2025 revision of the spec, added through PR #185 and authored by Basil Hosmer at Anthropic. Annotations are metadata hints attached to a tool's definition, describing the kind of effect a tool has rather than what it literally does. There are five defined fields, though two matter most in practice: readOnlyHint, which flags whether a tool only reads data, and destructiveHint, which flags whether a tool might delete or overwrite something. A title field exists too, purely for display, with no security weight behind it.

Here's the catch, and it's a significant one: nothing in the spec stops a malicious server from lying about its own annotations. A server could mark a genuinely destructive tool as readOnlyHint: true and destructiveHint: false, and the protocol has no mechanism to catch that. Annotations inform whatever approval interface the host application builds. They don't enforce anything at the model layer, and they don't enforce anything at a sandbox layer either. Think of them as a risk signal, not a security control. Actual enforcement still has to come from somewhere else, usually a sandbox or a rules engine sitting outside the protocol entirely.

OAuth 2.1 got formalized as the authentication standard for remote MCP servers in the November 2025 spec release, version 2025-11-25, with PKCE made mandatory for every client. That's a genuine step forward for the protocol's security posture. But the 2026-07-28 release candidate, which adds stateless transport support and a handful of breaking changes, adds mandatory OAuth-related behaviors for remote servers, like RFC 9728 metadata discovery, without going as far as requiring authentication on every caller. Whether a given server actually enforces per-caller checks is still left up to whoever builds it. And formalizing the standard hasn't closed the adoption gap: that NimbleBrain figure from earlier, only 8.5% of analyzed servers using OAuth as of March 2026, comes after this formalization, not before it.

What the spec deliberately leaves out is the entire governance layer: per-tool authorization logic, RBAC, scope enforcement, session controls, behavioral monitoring. The protocol defines how agents and servers talk to each other. It doesn't define who gets to say yes.

Microsoft's approach with Windows 11 shows what it looks like when a platform decides to fill that gap itself. Announced at Microsoft Build on May 19, 2025 by David Weston, Corporate Vice President for Enterprise and OS Security, the design routes every MCP client-server interaction through a trusted Windows proxy rather than letting them talk directly. Tool-level authorization requires explicit approval per client and per tool, with granularity down to the specific resource being touched. Declarative capabilities and isolation boundaries limit how far damage can spread if something does go wrong. It's a useful illustration of the shape these controls take once an organization decides the spec's floor isn't high enough on its own, and builds the rest.

Tool-level RBAC: the most consequential control pattern in production MCP

Server-level access control alone doesn't cut it, and this is worth being blunt about. Granting a user access to an MCP server grants them access to every tool that server exposes, full stop. Without a separate layer of tool-level controls, a user who should only ever read data can still reach a write or delete function, simply because the server let them in the front door.

Tool-level RBAC fixes this by making each tool declare the scope or role it needs, and having the server check that before it ever executes anything. The ListTools handler is the enforcement point that matters most here: it should filter the tools shown to a user based on what that specific user is actually allowed to do. A read-only user shouldn't just be blocked from running a write tool. That tool shouldn't appear in their list at all. If someone only has read rights, write and admin-level tools need to be invisible to them, not merely unusable.

Session-level authentication isn't enough on its own either. Getting authorized at login doesn't mean every subsequent call in that session should be treated as pre-approved. Each individual tool call needs to check the caller's current entitlements against what that specific tool requires. This is the exact mechanism that closes the confused deputy gap described earlier: the server has to evaluate who is calling right now, not just confirm that someone, at some point, logged in successfully.

When an agent acts on behalf of a person, it needs to inherit a scoped-down, attenuated version of that person's permissions, never the full set and never more. The agent should never be able to do something the human it's acting for isn't authorized to do themselves. If a user can't approve a wire transfer without a second sign-off, the agent working on that user's behalf can't approve one either, no matter how convincing the prompt that triggered it looked.

None of this should live in a silo built just for AI agents. RBAC for agents needs to connect into the same SSO and identity infrastructure a company already uses for human employees, so role assignments don't have to be maintained twice. Done right, this closes the credential persistence gap directly: when an employee leaves, their agent permissions get revoked at the same moment their account does, automatically, without anyone remembering to go clean up a separate MCP config somewhere.

It works as a centralized gateway enforcing tool-level policy, maintaining a registry of MCP servers with verified identities attached, and turning "what can the AI actually do" into a decision an organization makes on purpose, rather than a default the protocol just happened to leave open.

Progressive scoping and dynamic privilege elevation during agent tasks

Setting broad permissions at deployment time, so the agent can "handle whatever comes up," is exactly how over-permissioning becomes the default state. It feels efficient at setup. In practice, it means the agent walks around carrying maximum access at all times, including the vast majority of the time its current task needs none of it.

The alternative is a progressive scope model, and it works in layers. Start every agent at the smallest possible footprint: discovery access, or read-only, as the resting state rather than the exception. Additional privileges get requested only when a task explicitly calls for them, never in advance, and never because it might be convenient later. When a task does need a more privileged action, that's handled through a targeted scope challenge: the agent requests elevation for that specific action, the system evaluates the request against context, and access gets granted narrowly, for that task, not broadly, forever.

This is the same logic that makes just-in-time access reviews work for human employees in a well-run security program, just compressed down to the timescale an agent actually operates on. A person requesting temporary admin rights to fix one server doesn't walk away with permanent admin rights afterward. An agent requesting elevated access to complete one task shouldn't either. The permission should expire the moment the task that justified it is done.

Static, standing access was never built for something that makes a new decision every few seconds. Progressive scoping is what least privilege actually looks like once it's applied to an actor that behaves this way: minimal by default, elevated on request, and never broader than the task in front of it demands.

Sources

  1. Securing the Model Context Protocol: Building a safer agentic future on Windows
  2. Agentic MCP Security Best Practices Guide
  3. owasp.org
  4. blog.modelcontextprotocol.io
Filed underMCP security

More in MCP security