Amit Kothari
Amit Kothari CEO of Tallyfy · Workflow AI Expert

Two layers of MCP security your team is missing

In brief

Most MCP deployments lock the entrance with OAuth and call it secure. That is perimeter authentication: it decides who connects. It says nothing about which tools on the server an authenticated agent can actually call. That second layer, per-tool authorization, is the one most teams skip, and skipping it hands every connected agent the keys to everything.

Summary

  • Authenticating an agent is not the same as authorizing it - a security review framed the split exactly: a gateway with OAuth solves “the perimeter problem - who can connect,” while a separate layer decides “what can they do once connected.”
  • Skip the second layer and one login unlocks every tool - an authenticated agent that can call anything the server exposes is the violation, because a single compromised session now reaches the whole surface, not one corner of it.
  • Even mature gateways admit the gap - Microsoft’s own MCP guidance for Azure API Management notes that its policies “apply to all API operations exposed as tools,” meaning auth lands at the server, not per tool.
  • Calling a process instead of a tool closes it for free - route the agent through a workflow and per-step access control comes from the system that already governs your people. See how Tallyfy structures that

Most MCP security stops at the perimeter. You put OAuth in front of the server, an agent authenticates, and the deployment gets called secure. It isn’t, or rather it’s only half secure, because letting an agent in and controlling what it can do once inside are two different jobs. The second one is the layer most teams never build.

Someone on a widely-read MCP security review drew the line cleanly. The gateway approach, OAuth plus role-based access, “solves the perimeter problem - who can connect,” while a separate layer governs “what can they do once connected.” Read that twice, because the whole post hangs on it. Authentication proves identity at the edge. Authorization decides, tool by tool, what that proven identity is actually allowed to invoke. They feel like the same control. They are not, and the distance between them is where most of the risk lives.

This is the part of the wider question of how AI earns a place in real work that buyers consistently underbuild: the door is loud and obvious, so it gets the attention, while the rooms behind it stay wide open.

Authentication at the door isn’t authorization inside

Start with the cleanest statement of the gap. As the team at Aembit put it in their writeup on MCP authentication and authorization patterns, “a user’s general authentication does not imply authorization for any specific client to act on their behalf.” An agent can present a perfectly valid token, proving it is who it claims to be, and that fact alone tells you nothing about whether it should be allowed to delete a record, move money, or read a file it was never meant to see. Identity is a question about the caller. Authorization is a question about the call. Conflate them and you’ve built a system where the only gate is the one at the entrance.

Solution Compliance & Finance
Compliance Management Software

Compliance Management Made Easy

Save Time On Compliance
Track & Delegate
Audit trails
Explore this solution

We covered the buyer’s side of this in the short checklist for vetting any MCP server before you connect it. This piece goes deeper on one line of that checklist, the one teams skip most: per-tool authorization. The reason it gets skipped is that perimeter auth is the satisfying part. You wire up OAuth, you test that an unauthenticated request bounces, and it feels finished. The work looks done because the obvious attack, a stranger with no credentials, is now blocked. What’s left is the harder, quieter question of what a credentialed agent can reach, and that question has no single satisfying moment of “now it’s locked.” You have to grind it out tool by tool.

Think about how your own building works. A badge gets you through the front door; it doesn’t get you into the server room, the finance floor, or the corner office. The badge proves you belong in the building. A separate set of rules decides which rooms you belong in once you’re inside. MCP deployments routinely build the badge reader and skip the room locks, then act surprised that everyone holding a badge can walk into everything.

The token at the perimeter is the badge. Per-tool authorization is the room locks. One without the other isn’t a security posture; it’s basically a lobby with an honor system past the turnstile.

An authenticated agent that can call everything is the bug

Here’s the failure shape, stated plainly. A server exposes forty tools. An agent authenticates once and now has all forty within reach, because the only check was at the door. Nothing scopes that agent to the six tools its actual job needs. That isn’t a misconfiguration waiting to be tightened later.

It’s the design, and the design is the bug.

So how much can a single authenticated session actually reach?

The principle being violated is the oldest one in security: a caller should hold the fewest permissions it needs to do its job, and not one more. An agent that authenticates and then sees the entire tool surface holds the most permissions, by default, with no narrowing. So when a session gets compromised, or a poisoned tool description steers the agent somewhere it shouldn’t go, the damage isn’t contained to one tool. It spans every tool the server offers, because the agent was never fenced. That spread is the blast radius, and it’s the difference between a contained incident and a company-wide one.

Run the failure forward. An agent connects with a valid token to do one narrow job, say, read open support tickets and draft replies. Because the server scopes nothing past the door, that same authenticated session can also reach the tools that close accounts, issue refunds, and export the customer table. Most days it never touches them, because its instructions don’t ask it to.

Then someone slips a hostile instruction into a ticket the agent reads, or the session token leaks, and suddenly the reach isn’t limited to drafting replies. It’s everything the server exposes, through a session that authenticated cleanly and looks perfectly ordinary in your logs. The compromise didn’t have to defeat your auth. It only had to get past a door that was the single lock in the building.

What makes this stubborn is that even mature infrastructure lands at the server level by default. Microsoft’s guidance for exposing an MCP server through Azure API Management is candid about it: the policies you configure “apply to all API operations exposed as tools in the MCP server.” You can rate-limit, you can require a token, you can trace the caller, and all of it covers the whole server uniformly. Tool-by-tool scoping is something you have to build on top, deliberately, because the platform won’t hand it to you for free. If a gateway as serious as Azure’s makes per-tool authorization your homework, the weekend MCP server somebody on your team cobbled together almost certainly never did it at all.

Three layers that do three different jobs

Stop thinking of MCP security as one wall and start thinking of it as three layers, each answering a different question. The first is the perimeter: who connects. OAuth, dynamic client registration, token validation, the work that proves an agent is allowed through the door. The second is per-tool authorization: what this specific agent, acting for this specific user, is allowed to call once inside. The third is per-call audit: a record of what actually happened, tool by tool, that you can read after the fact. Most deployments build the first, assume it covers the second, and bolt on a thin version of the third. All three are load-bearing.

Perimeter auth, per-tool authz, then per-call audit gate an agent request; skip a layer and nothing can deny or log it

Picture each layer doing its job. The perimeter layer is the OAuth handshake and token check that rejects anything without valid credentials, the part that feels like security because it stops the obvious stranger. Per-tool authorization comes next: the rule that says this agent, acting for this user, may call the read tools but not the delete tool, full stop, no matter what its prompt claims it needs. Last is the per-call layer, a line written to a log every time a tool fires, capturing who, when, and what changed. Drop the first and strangers get in. Skip the second and an authenticated insider gets everything. Lose the third and you can’t reconstruct what happened on the day you most need to.

What nobody warned us about when we built a production MCP server is how easy it is to ship the first layer, feel finished, and never notice the other two are missing until something forces the question. The perimeter passes its test on day one. The per-tool gaps stay invisible until an agent does something it was technically able to do and nobody intended, and the audit gap stays invisible until you go looking for a record that was never written. Each layer fails silently when it’s absent, which is exactly why teams skip the two that don’t announce themselves. Ask any agent-facing deployment a blunt question and watch the answer. Which tools can a given agent not call, and where would you look to prove what it did last Tuesday?

If either answer is a shrug, two of your three layers aren’t there.

Call a process, not a tool

There’s a move that closes the per-tool gap without making you rebuild authorization from scratch, and it comes from changing what the agent calls. Don’t expose raw tools and then try to police them one by one. Expose a process, and let the agent call a step inside it. The moment access runs through a defined workflow, per-step authorization stops being a new thing you maintain on the side and becomes the same access control that already governs which humans can do which steps. The agent doesn’t get the tool surface. It gets the steps it’s cleared for, checked against the roles your organization already trusts.

Here’s the before and after. Before: you stand up a server, expose forty tools, and now you owe yourself forty authorization decisions, which client can call which tool under which conditions, kept as a separate, messy rulebook that drifts the moment someone adds tool forty-one. After: you expose your processes, the agent calls a step, and whether this agent may do this is answered by the role the step already requires, the same role a person would need. You didn’t write a parallel rulebook. You reused the one your company already trusts and already audits. When a new capability ships, it arrives inside a process with its access rules attached, instead of as a naked tool waiting for someone to remember to scope it.

That’s the shape Tallyfy uses, and the reason it works is that the MCP server sits on top of the role-based access system that was already deciding who can touch what in the product. An agent reaching a step gets the same permission check a person reaches it through. No parallel, half-built notion of “what agents can do” living beside the real one, which is where the gaps that become incidents tend to creep in.

Concretely, the perimeter on that server is OAuth 2.1 with dynamic client registration, but a valid token only gets an agent inside. Which steps it can then run is decided by the role attached to each one, checked the same way the product already checks a person who holds that role. So when a security team asks what a given agent can reach, the answer is a role they’ve already reviewed, not a fresh per-tool access matrix nobody has audited. Add a step tomorrow and its role decides who runs it, with no separate agent-permission table to keep in sync.

Every call is a workflow step, so the audit layer isn’t bolted on either; it’s the running record of every action that the platform already keeps, with a person required to approve anything consequential. The agent supplies judgment on one bounded step. The structure supplies the scoping and the trail. Add a tool to a step and only the agents cleared for that step can reach it; nobody has to go back and write a fresh authorization rule, because the rule was the role all along. This is the same logic behind why it’s safer to box an agent into a workflow instead of letting it roam, applied to the authorization layer specifically: a process is naturally scoped in a way a raw tool never is.

Where this leaves your team

The takeaway isn’t “buy a second product.” It’s a way of looking at any MCP deployment you already run or are about to. Find the perimeter layer first, the OAuth, the token checks; that part is probably solid because it’s the part that feels like security. Then ask the two questions the perimeter can’t answer. Once an agent is authenticated, what stops it from calling tools outside its job? And when it calls one, where does that land in a log you can actually read?

Most teams have a confident answer to the first question and an awkward silence on the other two.

That silence is the work. It’s also the part the early MCP failures kept exposing, where a server trusted everything that got past the door and had no idea what an authenticated agent was doing with that trust. The thing is, perimeter auth is necessary and it is not enough, and the teams who learn that before an incident are the ones who built the per-tool and per-call layers on purpose, instead of discovering they were missing during the cleanup. Authentication asks who’s calling. Authorization asks what they can call. Audit asks what they did. Three questions, three layers, and a deployment that only answers the first is a deployment that’s one compromised session away from finding out why the other two mattered.

About the author

Amit is the CEO of Tallyfy. He has 25+ years of practical experience in technology, entrepreneurship, and operational efficiency. He's been hands-on with AI-first engineering and changing Tallyfy to AI-native workflow automation since Claude Code was first released. He's also an Entrepreneur in Residence at WashU's Skandalaris Center, created the OneDay (Woolf) AI curriculum for their accredited MBA and consults with clients who need help with AI via Blue Sheen. He graduated with a Computer Science degree from the University of Bath. He's originally British and lives in St. Louis, MO.

Find Amit on his website , LinkedIn , or GitHub . Read Amit's bio →

Automate your workflows with Tallyfy

Stop chasing status updates. Give people and AI a process to follow.