MCP security and authorisation
How to secure an MCP server: OAuth 2.1, protected resource metadata, audience-bound tokens, least privilege, approvals, validation, limits, audit and prompt-injection handling.

An MCP server turns business capabilities into tools an AI model can call. That makes it a new front door to your data, and it needs the same care as any API, plus controls for risks specific to AI clients, such as instructions hidden in data. This page sets out a security and tool-authorisation architecture based on the MCP authorisation specification and its security best practices.
This is a reference design. We validate identity providers, scopes, vendor permissions and data handling for each implementation, and GeekMidst can design and implement it through MCP server development. It is not legal or compliance advice; check obligations with your legal adviser.
Business context
The risks are concrete: a token accepted by the wrong server, a server forwarding a client's token downstream, a tool that runs any query it is given, a model persuaded by text in a record to call a write tool, or a runaway loop of calls. Each one has a control, and the controls work best when designed together.
MCP security and authorisation reference architecture
Reference architecture: a reusable pattern, not a live client integration
Select a component to see what it is responsible for and how data moves to and from it.
Components and data flows (text version)
| Component | Type | Responsibility |
|---|---|---|
| Usersigns in and consents | People | A named person who authorises the client and confirms sensitive actions. |
| AI host and MCP clientOAuth client | AI and agents | Discovers the authorisation server, runs the OAuth flow with PKCE and sends the bearer token on every request. |
| Authorisation serverOAuth 2.1 with PKCE | Identity, policy and governance | Issues access tokens bound to the MCP server's URI as audience, with only the requested scopes. |
| Protected resource metadataRFC 9728 | Identity, policy and governance | A document the MCP server publishes that lists at least one authorisation server. |
| MCP serverOAuth resource server | Integration layer | Validates token audience, expiry and scope, the Origin header and tool inputs before any tool runs. |
| Tool policyread/write, limits | Identity, policy and governance | Allowlists tools per role, keeps read and write tools separate, and applies rate limits, timeouts and idempotency. |
| Secrets storeserver-side only | Identity, policy and governance | Holds downstream credentials. Secrets never appear in tool results, prompts or logs. |
| Human confirmationwrite tools | People | Shows a named person what will change and records their decision before a write runs. |
| Downstream API clientown credentials | Integration layer | Calls product APIs with narrow, parameterised requests using the server's own credentials, never the client's token. |
| Audit logwho, what, outcome | Identity, policy and governance | Records caller, tool, decision, outcome and timing, without storing secrets. |
| Product APIsSalesforce, Braze, others | External or custom system | Business systems behind the server, each with its own permissions and limits. Databases are never exposed directly. |
Data flows
- User → AI host and MCP client: request. The user asks the host to do something.
- User → Authorisation server: sign-in and consent. The user signs in and approves the requested scopes.
- AI host and MCP client → Protected resource metadata: discover metadata. After a 401, the WWW-Authenticate header points to the metadata, which names the authorisation server.
- AI host and MCP client → Authorisation server: auth code with PKCE. The client sends the resource parameter (RFC 8707) so the token is bound to this server.
- AI host and MCP client → MCP server: Bearer token. Sent in the Authorization header on every request, never in the query string.
- MCP server → Protected resource metadata: publishes. The server serves its metadata at a well-known path.
- MCP server → Tool policy: validated request. Only requests with a valid, correctly scoped token, a valid Origin and schema-valid input reach the policy.
- Tool policy → Human confirmation: write tool call. Write and destructive tools wait for a person to confirm.
- Human confirmation → Tool policy: decision. Approval lets the call continue; rejection returns a tool error.
- Tool policy → Downstream API client: permitted call. Calls run with timeouts and an idempotency key so a retry does not repeat a change.
- Secrets store → Downstream API client: downstream credential. The API client fetches its own credential at call time; it is never passed to the model.
- Tool policy → Audit log: decision log. Every allow, deny and approval is logged.
- Downstream API client → Product APIs: scoped API call. Narrow, parameterised requests. Vendor errors and rate limits are returned as tool errors.
Controls and what they prevent
| Control | What it prevents | How |
|---|---|---|
| OAuth 2.1 resource server | Anonymous or shared access | Servers act as resource servers; clients use PKCE |
| Protected resource metadata (RFC 9728) | Misconfigured clients | Publish metadata listing the authorisation server |
| Audience-bound tokens | Tokens reused at other servers | Validate that the token was issued for this server (RFC 8707) |
| No token passthrough | Bypassed server controls and a lost audit trail | Never accept or forward tokens not issued for this server |
| Least privilege | Over-broad access | Minimal scopes; separate read and write scopes |
| Read and write separation | Accidental changes | Separate tools; writes off by default |
| Human confirmation | Unreviewed changes | Preview and approve each write |
| Input schema validation | Malformed or injected arguments | JSON Schema with additionalProperties false |
| Rate limits, timeouts, idempotency | Runaway loops and duplicate writes | Per-user limits; idempotency keys |
| Secrets server-side | Credential leaks to the model | Secrets store; never in results |
| No database credentials or unrestricted SQL | Bulk data extraction | Narrow, parameterised tools only |
| Origin validation | DNS rebinding | 403 on an invalid Origin; local servers bind to 127.0.0.1 |
| Prompt-injection handling | Instructions hidden in data | Treat tool output as data; confirm writes |
| Audit logging | Unaccountable actions | Log caller, tool, outcome and timing |
Data flow, step by step
- The client calls without a token and gets 401 with a
WWW-Authenticateheader pointing to the protected resource metadata. - The client reads the metadata and finds the authorisation server.
- The user signs in and consents; the client completes the flow with PKCE and the
resourceparameter. - The client sends the token as
Authorization: Beareron every request. - The server validates audience, expiry and scope (401 for invalid or expired tokens, 403 with
insufficient_scope), the Origin header and the tool input. - The policy decides: is the tool allowed for this user, is it read or write, is the caller within limits?
- Writes wait for confirmation from a named person.
- The API client calls the product with its own credential and an idempotency key.
- Everything is logged.
Trust boundaries and authentication
The client side is untrusted from the server's point of view, including the model's choice of tools and arguments. The server boundary holds tokens, policy, secrets and audit. Product APIs sit beyond it, each enforcing its own permissions. Vendors show the same principles: Salesforce Hosted MCP Servers use per-user OAuth with PKCE through an External Client App with the mcp_api scope, enforce CRUD, field-level security and sharing, and have no anonymous service accounts. The Braze MCP server uses OAuth with the user's Braze login, needs a "Use MCP Server" permission that is off by default, and Braze advises against client "auto-mode".
The public MCP server on this website shows a different, deliberate choice: it is read-only and unauthenticated because it serves only published content, and it is rate limited per address with Origin validation for browser clients.
Failure scenarios and how to handle them
| Failure | Effect | How to handle it |
|---|---|---|
| Token for another server presented | Possible misuse | Reject unless the audience matches this server |
| Token expired | 401 | Client refreshes; server never falls back to a shared key |
| Scope too narrow | 403 insufficient_scope | Client requests a step-up scope with consent |
| Model calls a write tool unexpectedly | Unwanted change | Approval required; deny by default |
| Retry after timeout | Duplicate write | Idempotency key per change |
| Injected text in a record | Model misled | Output treated as data; writes confirmed by a person |
Operational monitoring
Monitor authentication failures, denied calls, approval rates, write volume per user and latency. Alert on bursts of denials or writes. Review scopes, allowlists and approvers regularly, and rotate downstream credentials on a schedule.
Alternative approaches and trade-offs
OAuth per user gives accountability but needs an identity provider and consent design. Service credentials are simpler but hide who acted; keep them for read-only, low-risk tools. Local stdio servers take credentials from the environment and suit a single developer, not shared use. Central enforcement in a gateway keeps policy in one place; per-server enforcement keeps it close to the data. Many designs use both; see the MCP host, client and server pattern.
Implementation checklist
- 01
Choose the authorisation server
OAuth 2.1 with PKCE and Client ID Metadata Documents or pre-registration
- 02
Publish protected resource metadata
At the well-known path for your endpoint
- 03
Validate every token
Audience, expiry and scope on every request
- 04
Separate read and write tools
Read-only first; writes behind approval
- 05
Define input schemas
Strict schemas and clear tool errors
- 06
Keep secrets server-side
Secrets store and rotation
- 07
Set limits
Per-user rate limits, timeouts and idempotency keys
- 08
Log and review
Audit log, alerts and regular access reviews
Related services and solutions
MCP security and governance
Our governance resource
→MCP server development
Designing and building secure servers
→MCP architecture pattern
Hosts, clients, gateway and adapters
→Enterprise AI integration
Connecting AI to business systems
→Security and governance
Salesforce security services
→Responsible AI
How we approach AI use
→Questions we hear
Is authorisation required by MCP?
Can our MCP server forward the user's token to Salesforce?
Should we let the AI run SQL?
Is this based on a client system?
Sources
- https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization
- https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/authorization-server-discovery
- https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices
- https://developer.salesforce.com/blogs/2026/04/salesforce-hosted-mcp-servers-are-now-generally-available
- https://www.braze.com/docs/developer_guide/mcp_server/setup/
Review your MCP security design
Tell us what your MCP server will expose and to whom. We can review the authorisation design, tool policy and approval steps.




