Table of Contents
The authorization model for MCP with Descope
Model Context Protocol (MCP) servers are quickly becoming the control plane for AI systems–the place where models, users, tools, tenants, and real-world systems intersect. With that potential comes a hard requirement: you must know who is calling your server, what they’re allowed to do, and which external systems they can access.
That’s why we built the Descope Python MCP SDK–a simple way to integrate Descope authentication and authorization with MCP servers built in Python. This SDK adds to our suite of capabilities in the Agentic Identity Hub to help MCP server developers securely connect their MCP servers with MCP clients.
The SDK is not just a token validator. It’s a bridge between modern identity, policy-driven authorization, and agent infrastructure.
And if you’re already using Descope as your customer identity provider, it’s the fastest way to bring your existing roles, permissions, SSO integrations, and security policies directly into your MCP servers. Visit the SDK docs to get started, or keep reading to learn more about what the Python MCP SDK provides!
The authorization model for MCP with Descope
In an MCP-based system:
Descope acts as a hosted Authorization Server (AS)
MCP clients register with Descope and obtain access tokens
MCP servers validate those access tokens
MCP servers use validated access tokens to retrieve external tokens when needed
Descope is the system of record for identity, policy, and credentials. MCP servers never create or manage external credentials themselves.
What the Descope Python MCP SDK provides
The Descope Python MCP SDK is designed to sit directly on the security boundary of your MCP server. It gives you three core capabilities that every production MCP service needs:
Validate who is calling
Enforce what they’re allowed to do
Safely access external systems on their behalf
Instead of building custom auth logic into every tool, you use the SDK as a single, consistent authorization layer.
Function | What it does | Why it matters |
|---|---|---|
| Verifies the MCP access token using Descope’s keys and config | Ensures the caller is real, trusted, and targeting the right MCP server |
| Enforces fine-grained permissions and raises MCP-spec errors | Prevents unauthorized tool execution |
| Exchanges the MCP access token for an external app token | Gives you secure, policy-approved access to third-party APIs |
Together, these functions let your MCP server act on behalf of a user without ever storing secrets or hardcoding permissions.
See the full setup instructions, including MCP server configuration and .well-known URLs in the Descope Python MCP SDK Documentation.
The SDK is intentionally focused. It does not replace MCP frameworks or tool execution layers. Instead, it concentrates on the authorization primitives every MCP server needs in order to safely access external systems.
Token validation with scopes and audience enforcement
The SDK provides first-class validation of Descope-issued access tokens. MCP servers can validate that an access token:
Is authentic and unexpired
Contains a required subset of scopes
Is issued for the correct audience
The audience is configured when the SDK is initialized and ensures that:
Tokens are bound to a specific MCP server or deployment
Cross-server token replay is prevented
Authorization decisions remain context-aware
User-level and tenant-level external tokens
The SDK supports retrieving external application tokens at the two levels required by real MCP deployments:
User-level external tokens, optionally scoped and tenant-aware
Tenant-level external tokens, representing tenant-wide access
External tokens can be requested:
With explicit scope requirements
With refresh or force-refresh semantics
As fully typed responses including expiration and metadata
This enables MCP servers to safely power both interactive user tools and automated workflows without ever handling raw credential storage.
Policy-enforced access to external tokens
A core guarantee of the SDK is: When an MCP access token is exchanged for an external application token, Descope policies are enforced. More precisely:
External tokens are stored and managed by Descope in the Connections vault
MCP servers request access to those tokens using an MCP access token
Descope evaluates user, tenant, application, and scope policies at request time
Only policy-approved external tokens are returned
Revocations and policy changes take effect immediately
The MCP server acts as a policy-enforced accessor, not merely a token issuer.
Why this matters for MCP servers
MCP servers are security boundaries.
They frequently execute actions with real-world impact, call external services on behalf of users, and return sensitive data. Without strong guarantees around how external tokens are accessed, authorization flaws become inevitable.
The Descope Python MCP SDK ensures that:
External credentials are never embedded in tools
Access to external tokens is always policy-checked
Authorization logic is centralized and auditable
User identity, tenant identity, and client identity remain clearly separated
A complete example
Below is a real MCP server tool that:
Validates the caller
Enforces the
calendar.readscopeRetrieves a Google Calendar OAuth token from Descope
Calls the Google Calendar API on the user’s behalf
from mcp.server import FastMCP
from mcp_descope import DescopeMCP, validate_token, require_scopes, get_connection_token, InsufficientScopeError
import requests
# Initialize SDK
DescopeMCP(
well_known_url="https://api.descope.com/v1/apps/agentic/<Descope Project ID>/<Descope MCP Server URL>/.well-known/openid-configuration",
mcp_server_url="https://your-mcp-server.com"
)
mcp = FastMCP("calendar-server")
@mcp.tool()
async def get_calendar_events(
max_results: int = 5,
mcp_access_token: str = None
) -> str:
"""
Get upcoming calendar events for the authenticated user.
Requires 'calendar.read' scope.
"""
if not mcp_access_token:
return {"error": "Authentication required"}
try:
# 1. Validate the MCP access token
token_result = validate_token(mcp_access_token)
# 2. Enforce required scopes
require_scopes(token_result, ["calendar.read"])
# 3. Resolve the user identity
user_id = token_result.get("sub") or token_result.get("userId")
# 4. Retrieve a policy-approved Google token
google_token = get_connection_token(
user_id=user_id,
app_id="google-calendar",
scopes=["https://www.googleapis.com/auth/calendar.readonly"],
access_token=mcp_access_token
)
# 5. Call Google Calendar API
from datetime import datetime
now = datetime.utcnow().isoformat() + "Z"
url = "https://www.googleapis.com/calendar/v3/calendars/primary/events"
params = {
"timeMin": now,
"maxResults": max_results,
"orderBy": "startTime",
"singleEvents": True
}
response = requests.get(
url,
headers={"Authorization": f"Bearer {google_token}"},
params=params
)
if response.status_code != 200:
return {"error": f"Google API error: {response.status_code}"}
return response.json()
except InsufficientScopeError as e:
# MCP spec-compliant error response
return e.to_json()
except Exception as e:
return {"error": str(e)}How this complements FastMCP
FastMCP already enforces tool-level access controls. The Descope Python MCP SDK extends that boundary by adding:
Secure access to external credentials
Policy-backed scope enforcement
Together, FastMCP handles how tools run, while Descope handles who is allowed to act and what they can access. That separation is what makes MCP servers safe to use in production.
For Express and TypeScript teams: Descope Express MCP SDK
Not building your MCP server in Python? You don’t have to wait for the same security and policy guarantees.
Descope already provides an Express MCP SDK for teams building MCP servers in Node.js and TypeScript. It brings the same core principles of the Python MCP SDK to the JavaScript ecosystem:
Policy-enforced access to external tokens
User- and tenant-level credentials
Scope and audience validation
Compatibility with MCP servers built on Express and the generic MCP SDK
This means you can standardize on Descope as your identity and authorization layer across both Python and Node-based MCP servers while keeping a single source of truth for roles, permissions, scopes, and policies.
Together, the Python MCP SDK and the Express MCP SDK give you a consistent, cross-language security foundation for your entire MCP deployment.
Closing thoughts
MCP servers don’t just execute tools — they represent users, tenants, and businesses in the real world. That means your authorization model is not an implementation detail. It is your security boundary.
With Descope, your MCP server inherits everything you already trust:
Enterprise SSO
Role and permission models
Policy enforcement
Secure credential governance
Auditable access control
The Descope Python MCP SDK makes it effortless to bring that identity foundation into the MCP world — so your agents can act with power, and your security team can still sleep at night. Sign up for a free account and visit the SDK docs to get started. Have questions about our platform? Book a demo with our team.

