DEV Community

Rhumb
Rhumb

Posted on • Originally published at rhumb.dev

Tool-Level Permission Scoping in MCP: Why Server Authentication Isn't Enough

When teams first secure an MCP server, they focus on the front door: who can connect. OAuth, API keys, TLS — the authentication layer. It feels complete. The question "is this agent allowed to use this server?" has an answer.

But there's a second question they haven't asked: "Which tools on this server is this agent allowed to call?"

These are different problems. And conflating them is how you end up with a research agent that can accidentally trigger a deployment.

The Single Permission Boundary Problem

Most MCP server implementations today treat auth as binary. An agent authenticates → it gets access to the full tool surface. Every tool the server exposes is available to every authenticated client.

This works fine in a single-agent setup. It starts breaking down the moment you add heterogeneous agents — systems where a research agent, a deployment agent, and a data pipeline agent all talk to the same MCP server.

Each of those agents has a different job. Different blast radius. Different risk profile.

A research agent should be able to read, query, and summarize. It should not be able to push code, trigger deployments, or delete records.

A deployment agent probably needs write access to infrastructure tools. It should not need access to customer data or financial APIs.

If your permission model is "authenticated = full access," you've created a lateral movement problem by design. A prompt injection attack that compromises a research agent now has access to every tool the server exposes — including the ones your research agent never needed.

What Per-Tool Scoping Looks Like

The fix is conceptually simple: separate tool access from server access.

Instead of:

Agent authenticates → access granted → all tools available
Enter fullscreen mode Exit fullscreen mode

You want:

Agent authenticates → role/scope attached → tools filtered by role
Enter fullscreen mode Exit fullscreen mode

In practice this means:

  • Tool manifests are role-aware. What the server returns when an agent calls list_tools (or equivalent) reflects that agent's permitted surface, not the full server capability.
  • Tool calls are validated against scope. An agent calling a tool outside its permitted set gets a clean error, not execution.
  • Roles are defined at server config, not per-agent credentials. You manage "what can a research agent do" once, centrally, not per-agent-deployment.

The AN Score evaluation framework measures this explicitly: does the server's access model allow granular tool restriction by caller role? Most current MCP server implementations score low here — it's a genuine gap in the ecosystem.

Why Tool Visibility Matters for Containment

There's a subtler point beyond just enforcing restrictions: agents should only see the tools they're allowed to use.

If a research agent can see (but not call) deployment tools in its tool manifest, an adversarial prompt can still reference those tools by name, reason about them, and potentially attempt calls that fail at execution time. The attack surface is the knowledge of what's available, not just the execution.

MCP servers that handle this well suppress the tool surface at the discovery layer — the agent's view of available tools is scoped to its role. It can't reason about tools it doesn't know exist.

This is a defense-in-depth principle that's easy to implement server-side and hard to retrofit once agents are in production with a mental model of the full tool surface.

The Audit Trail Dependency

Per-tool scoping doesn't exist in a vacuum. It requires a parallel investment: structured audit logging that captures tool calls with caller identity attached.

Without this, scoping becomes unverifiable. You think you're enforcing per-role access. You have no way to confirm it's working, detect violations, or reconstruct a security incident.

At single-agent scale, audit logs feel optional. With multi-agent MCP coordination, they're required infrastructure. The question changes from "did an agent do something wrong?" to "which of my 12 concurrent agents did this, when, and with what parameters?"

The servers that skip structured audit logs are making the same mistake as the servers that skip tool scoping: they're designing for the happy path.

What This Means for MCP Evaluation

When evaluating MCP servers for production use, the questions to ask:

  1. What's the tool surface on first authentication? Does the server return all tools, or does it scope visibility to the caller's role?
  2. Is per-tool restriction configurable without forking the server? Or do you need to maintain a custom fork to implement role-based tool access?
  3. What audit data does the server emit per tool call? Structured logs with caller identity, timestamp, tool name, parameters?
  4. How does the server handle unauthorized tool calls? Clean rejection with a typed error, or silent failure, or (worst) execution anyway?

Most MCP servers in production today score well on authentication at the server level and poorly on everything below it. The security model was designed for single-agent, single-role use cases. Production multi-agent coordination is revealing the gap.

The AN Score data reflects this: credential and auth model scores for MCP-integrated services have higher variance than almost any other dimension. The spread isn't about whether auth exists — it's about how deep the trust model goes.

What "Secure by Design" Means at the Tool Layer

The framing from the previous post in this series — security as design intent, not bolt-on — applies directly here.

Per-tool permission scoping is not a feature you add after deployment. It's an architecture decision that shapes how the server is built, how tool manifests are generated, how errors are typed, and how audit data flows.

Teams that build MCP servers assuming single-agent consumers, then try to add role-based tool access later, almost always end up with incomplete implementations. The "add it later" approach typically means adding a middleware check in front of tool execution, without touching visibility, without adding audit structure, and without testing the edge cases (what happens when an agent calls a tool it shouldn't know about?).

Design it in. Tool-level scoping should be in the server spec before you write the first tool handler.


Key Takeaways

  • Server authentication and tool authorization are different layers. Conflating them creates lateral movement risk.
  • Agents should see only the tools they're permitted to use, not just be blocked from calling the ones they shouldn't.
  • Multi-agent MCP deployments need structured audit logs with per-tool, per-caller granularity.
  • Per-tool scoping is a design decision, not a retrofit. Build it into the server architecture, not the deployment layer.
  • AN Score data shows this as a consistent gap: MCP servers score well on "auth exists" and poorly on "how deep does the trust model go."

This is part of Rhumb's MCP security series for production operators.

Previous: Why Prompt Injection Hits Harder in MCP: Scope Constraints and Blast Radius

Top comments (0)