← iamidentity.ai/blog
IAMIDENTITY.AI
Agentic AI MCP IBM Verify HashiCorp Vault

The MCP Server Is Your Security Perimeter

An identity pattern for MCP tool calls you can stand up in 30 minutes. No AWS account required.

Robert Graham 22 May 2026 ~10 min read
The MCP Server Is Your Security Perimeter: an AI agent layer forwards a user JWT to an MCP server (control plane, gateway, session context), which checks with IBM Verify as policy decision point and obtains a short-lived 5-minute credential from HashiCorp Vault for the data layer.

Seems like an easy question..... "Where does authorization live in your MCP server?"

"For your MCP server, where does authorization live? In the agent? In the API the MCP server wraps? In the model? Tell me which line of code does the deny."

Most MCP servers I have seen do not have an answer to that question at all. The agent has an API key in its environment file. The MCP server takes the API key and calls the upstream API. Whatever permissions the API key has, the agent has. Whatever permissions the agent has, every user of the agent has. The model decides which tool to call, the tool runs with the agent's full permission, and the only thing standing between a misbehaving prompt and your customer database is whatever the upstream API happens to enforce on its own.

That works fine for read-only side projects. It does not work for an agent that is supposed to read a clinician's patient panel and refuse to read the senator's chart without a phone tap. The instant you have two different authorization tiers, the API-key-in-env-file pattern collapses.

The fix is not another layer above the agent. The fix is to push authorization down into the MCP server where it can be per-call.

I just finished a 30-minute hands-on cookbook that lays that pattern out end to end.

→ Cookbook
github.com/iamidentity-ai/mcp-verify-vault
Verify decides · Vault mints · 5-min Postgres · ~30 min to stand up
This post is the why behind it. What the pattern is, what authority lives where, and what a security reviewer should look for when they audit an MCP server.
Architecture: agent transports the bearer to the MCP server, which calls IBM Verify for an OBO and HashiCorp Vault for an ephemeral PostgreSQL credential.
Figure 1. The agent transports. The MCP server asks the question. Verify decides. Vault mints. PostgreSQL serves the call as a credential that lives five minutes.

01Where authorization actually lives

In a normal three-tier app the security perimeter is the API. The user logs in, the app gets a token, the app passes the token to the API, the API decides. The app does not enforce business authorization on its own because the app is a transport. The user's identity flows through it.

In a typical MCP setup people do not apply that reasoning. They give the agent an API key, route every user's request through the same API key, and act surprised when one user can see another's data.

The pattern this cookbook ships flips that. The agent is the transport. The MCP server is the API. The user's IBM Verify access token rides on the request to the agent, the agent forwards it verbatim to the MCP server, and the MCP server runs every authorization decision through IBM Verify on a per-call basis. The agent makes no authorization decisions. The MCP server enforces request hygiene and protocol state, but the actual allow-or-deny decision comes from Verify.

That is not a marketing slogan. It is a property of the code. The cookbook's MCP server contains no homegrown authorization policy. It constructs an OAuth 2.0 Rich Authorization Request (RFC 9396) that describes the action the server is about to perform, and it makes an RFC 8693 Token Exchange call that asks IBM Verify whether the action is allowed. If Verify says yes, the MCP server presents the resulting OBO JWT to HashiCorp Vault and gets back a five-minute Postgres credential. If Verify says step-up MFA is required, the MCP server triggers a push to the user's phone and waits.

Seven-step identity chain from OIDC login to ephemeral Postgres credential.
Figure 2. One tool call, seven hops. The OBO is the cryptographic spine of the chain.

02Threat model: what actually goes wrong

The real risk in MCP is not that the model becomes magical or malicious. The real risk is that the call path quietly inherits a standing credential that is broader than any one user's intent. Once an agent or MCP server runs on a shared API key, every prompt rides the same authority unless an upstream system compensates for it.

Per-call Token Exchange changes that posture. Instead of handing the agent a long-lived credential, the MCP server assembles a structured question about this action, on this resource, for this subject, right now, and sends that to Verify as an RFC 9396 Rich Authorization Request. The OBO that comes back is time-bounded and scoped to the approved authorization_details, and Vault only mints a Postgres credential when it can validate that OBO against Verify's signing keys.

03Three guarantees Verify can provide

These are the assurances a security reviewer is looking for. None of them live in the MCP server, the agent, or the model. All three are properties of how IBM Verify enforces the access policy.

Guarantee 1 · Per-call

Per-call authorization, not per-session. Every single tool invocation runs its own Token Exchange. The MCP server cannot accumulate or reuse business authority across calls. A clinician who has read patient A0001 has not been pre-approved to read A0042. The next call goes through Verify again and gets a fresh evaluation.

Guarantee 2 · Step-up at policy time

Step-up MFA evaluated at policy time. When the cookbook's access policy fires ACTION_MFA_ALWAYS for VIP reads, IBM Verify returns scope: mfa_challenge instead of an OBO. The MCP server triggers a push at IBM Verify's /v1.0/authenticators/{factor_id}/verifications endpoint and polls until the clinician approves. Only then does Verify mint the real OBO. In the reference implementation, the only path to a database credential runs through that Verify decision.

Guarantee 3 · Cryptographically attested

Policy-attested authorization details. The Rich Authorization Request the MCP server sends to Verify is cryptographically attested on the way back. Verify signs the approved authorization_details into the OBO JWT it returns. HashiCorp Vault then validates that JWT signature against the Verify JWKS before it matches the RAR to a rar_mappings entry. If the MCP server tried to forge a wider RAR locally and present it to Vault directly, Vault would reject the signature check.

That third one is the load-bearing piece. Vault does not trust the RAR because the MCP server says so. Vault trusts the RAR because IBM Verify signed a JWT that contains the RAR, and Vault validates the JWT signature before it acts on the RAR. The MCP server is in the middle of the chain. It is not the source of authority.

Why Vault trusts the RAR: the happy path through Verify signing, and the attack path where a forged RAR is rejected at the signature check.
Figure 3. The MCP server is not the source of authority. Vault checks the signature, not the sender.

04What the MCP server is forbidden from doing

A technical person who picks up the cookbook's source will want to know what authorization decisions the MCP server is allowed to make unilaterally. The answer is: almost none. The forbidden-list is short and worth reading in full.

That list is what a security reviewer should grep the code for. If a future PR ever adds homegrown authorization decisions like allow-or-deny logic, or caches an OBO across calls, or holds a long-lived database password in the MCP server process, the reviewer should fail it. The pattern only works if the MCP server stays disciplined about what it is not allowed to do.

Where to look in the repo

The cookbook makes this concrete in three files under mcp-server/src/: the bearer-presence check at the HTTP boundary, the Rich Authorization Request builder, and the RFC 8693 + mfa_challenge handler that chooses between "mint OBO" and "trigger step-up and wait". Those three files together are the security story for the MCP server.

05What the agent is forbidden from doing

If the MCP server is "almost nothing" from a business authorization standpoint, the agent is literally nothing. The agent is a transport, not a security boundary.

The agent's job is to think and to route. A change of agent framework, host, or even programming language does not change the security chain. The cookbook's agent happens to be Python plus Strands plus FastAPI because Python is what the user told me they wanted. If you swap it for a Node agent, a Java agent, a Rust agent, or a managed agent platform you have already paid for, the chain still works. The MCP server is the security perimeter; the agent is just a different way to call it.

06Why this one is not the AWS cookbook

There is a companion cookbook at github.com/iamidentity-ai/agentcore-verify-vault that walks the same chain hosted on AWS Bedrock AgentCore Runtime. It is a great cookbook for customers who are already in AWS. It is a hard cookbook for a customer who wants to evaluate the identity pattern without standing up an AWS account first.

The MCP-focused cookbook this post is announcing covers the case where you want to host the MCP server and the agent yourself. The agent is a plain Python process. The MCP server is a plain Node process. The Vault and PostgreSQL containers are Docker. The default LLM is Anthropic direct because that is the lowest-friction path that does not couple the cookbook to a cloud vendor. The whole stack runs on a mac/linux OS.

Same chain, different hosts

The hosting decision is your customer's. The identity pattern is the same on either cookbook. Verify is the policy decision point. Vault is the credential broker. The MCP server is the security perimeter. The agent is the transport. None of that changes when you move the agent to AgentCore Runtime, or to Kubernetes, or to a VM, or anywhere else.

That is the point of separating the cookbooks. Your hosting decision should not shape your security posture.

07What an auditor should do in fifteen minutes

The other audience for this pattern is the person who has to sign off on it. The cookbook bakes in a path for them as well: a fifteen-minute audit that either passes cleanly or turns into a bug report.

The cookbook spells this out in two chapters specifically aimed at the audit. Chapter 2, "The identity chain," is the security story up front, before any implementation. Chapter 12, "Anatomy of an MCP call," opens the three load-bearing files inside mcp-server/src/ and walks the bearer-presence check, the per-call RAR construction, and the RFC 8693 + mfa_challenge two-leg handler line by line. Together they give a reviewer everything they need to audit the MCP server in fifteen minutes instead of an hour.

Anatomy of one tool call across three logs: IBM Verify policy event, HashiCorp Vault lease event, and PostgreSQL log_statement output, joined by the OBO jti.
Figure 4. Three independent logs. One join key. A reviewer can reconstruct any tool call end to end.

08What's next

→ Run the cookbook
Thirty minutes. No AWS account required.
github.com/iamidentity-ai/mcp-verify-vault

Try to break it. Read the "what the MCP server is forbidden from doing" list. Try the four scenarios it describes. Either the code holds the line or you have found a bug worth filing.

Read the audit chapters. Chapter 2 is the identity chain. Chapter 12 walks the three load-bearing files in mcp-server/src/ line by line. Together they give you everything you need to audit a real production MCP server, not just this cookbook's reference.

The credential follows the request, not the agent. The policy decision lives in Verify. The credential lives in Vault for five minutes and then it does not exist. The MCP server's job is to ask the question and stand aside.

That is what a security perimeter looks like for an MCP tool call. The cookbook makes it real.