MCP dynamic client registration with Auth0 on Amazon Bedrock AgentCore Runtime
MCP servers expose tools that AI agents consume. In development, running them without authentication works fine. In production, every MCP…
MCP dynamic client registration with Auth0 on Amazon Bedrock AgentCore Runtime

MCP dynamic client registration with Auth0
MCP servers expose tools that AI agents consume. In development, running them without authentication works fine. In production, every MCP server endpoint needs access control — only authorized clients invoke your tools.
Dynamic Client Registration (DCR) is the OAuth 2.0 mechanism that lets MCP clients register themselves with an authorization server automatically. Combined with Auth0 as the identity provider and AgentCore Runtime as the hosting platform, this creates a fully authenticated MCP deployment: clients discover the server, register dynamically, authenticate via browser-based OAuth, and invoke tools with JWT tokens.
In this tutorial, deploy an MCP server to AgentCore Runtime with Auth0 JWT authorization, then build an OAuth client that handles the full DCR flow automatically.
The full source code is available in the amazon-bedrock-agentcore-samples repository.
What you build
- An MCP server with three tools deployed to AgentCore Runtime with JWT authorization
- Auth0 tenant configuration with an API and application supporting DCR
- An OAuth client that handles dynamic registration, browser-based authorization, token management, and MCP tool invocation
How DCR works with AgentCore Runtime
The authentication flow has four steps:
- Discovery: The MCP client fetches the OpenID Connect discovery document from Auth0 to learn the authorization, token, and registration endpoints
- Registration: The client registers itself with Auth0 using the DCR endpoint, receiving a client ID and secret
- Authorization: The user authenticates in the browser. Auth0 redirects back with an authorization code.
- Token exchange: The client exchanges the authorization code for a JWT access token. All subsequent MCP requests include this token in the Authorization header.
AgentCore Runtime validates the JWT using the customJWTAuthorizer configuration — checking the audience, issuer, and signature against Auth0's JWKS endpoint.
. . .
Prerequisites
- An Auth0 account (free tier works)
- An active AWS account with credentials configured
- Python 3.10 or later installed
- Docker running locally
- IAM permissions:
BedrockAgentCoreFullAccess
Set up Auth0
Step 1: Create an API
In the Auth0 dashboard, create a new API:
- Name: AgentCore Runtime API (or any descriptive name)
- Identifier:
ac-runtime-api(this becomes theaudienceparameter) - Signing algorithm: RS256
Step 2: Create an application
Create a new application in Auth0:
- Type: Regular Web Application
- Allowed callback URLs:
[http://localhost:3030/callback](http://localhost:3030/callback) - Grant types: Authorization Code, Refresh Token
Step 3: Note the discovery URL
DISCOVERY_URL="https://<your-auth0-tenant>.us.auth0.com/.well-known/openid-configuration"
AUDIENCE="ac-runtime-api"
Create the MCP server
Step 4: Define the server
Create server.py — the same FastMCP server from the MCP hosting tutorial:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(host="0.0.0.0", stateless_http=True)
@mcp.tool()
def add_numbers(a: int, b: int) -> int:
"""Add two numbers together"""
return a + b
@mcp.tool()
def multiply_numbers(a: int, b: int) -> int:
"""Multiply two numbers together"""
return a * b
@mcp.tool()
def greet_user(name: str) -> str:
"""Greet a user by name"""
return f"Hello, {name}! Nice to meet you."
if __name__ == "__main__":
mcp.run(transport="streamable-http")
The server code stays identical. Authentication is handled by AgentCore Runtime, not the server itself.
Deploy with JWT authorization
Step 5: Configure and launch with Auth0 authorizer
from bedrock_agentcore_starter_toolkit import Runtime
from boto3.session import Session
boto_session = Session()
region = boto_session.region_name
agentcore_runtime = Runtime()
# Configure JWT authorization with Auth0
auth_config = {
"customJWTAuthorizer": {
"allowedAudience": [AUDIENCE],
"discoveryUrl": DISCOVERY_URL,
}
}
response = agentcore_runtime.configure(
entrypoint="server.py",
auto_create_execution_role=True,
requirements_file="requirements.txt",
region=region,
agent_name="mcp_dcr_sample",
authorizer_configuration=auth_config,
protocol="MCP",
memory_mode="NO_MEMORY",
deployment_type="direct_code_deploy",
runtime_type="PYTHON_3_13",
)
launch_result = agentcore_runtime.launch()
Key details:
customJWTAuthorizertells AgentCore Runtime to validate incoming JWT tokensallowedAudiencematches the Auth0 API identifierdiscoveryUrlpoints to Auth0's OIDC discovery document for JWKS key resolutionprotocol="MCP"configures the endpoint for MCP RPC messagesdeployment_type="direct_code_deploy"deploys source code directly without Docker
. . .
Build the OAuth client
Step 6: Create the authenticated MCP client
The client uses the MCP SDK’s OAuthClientProvider to handle the full OAuth flow:
from mcp.client.auth import OAuthClientProvider, TokenStorage
from mcp.client.session import ClientSession
from mcp.client.streamable_http import streamablehttp_client
from mcp.shared.auth import OAuthClientMetadata, OAuthToken
class InMemoryTokenStorage(TokenStorage):
"""Simple in-memory token storage."""
def __init__(self):
self._tokens = None
self._client_info = None
async def get_tokens(self): return self._tokens
async def set_tokens(self, tokens): self._tokens = tokens
async def get_client_info(self): return self._client_info
async def set_client_info(self, client_info): self._client_info = client_info
async def connect_with_auth(server_url, auth0_audience):
"""Connect to an authenticated MCP server."""
client_metadata = OAuthClientMetadata.model_validate({
"client_name": "MCP Auth0 Client",
"redirect_uris": ["http://localhost:3030/callback"],
"grant_types": ["authorization_code", "refresh_token"],
"response_types": ["code"],
})
oauth_auth = OAuthClientProvider(
server_url=server_url,
client_metadata=client_metadata,
storage=InMemoryTokenStorage(),
redirect_handler=lambda url: webbrowser.open(url),
callback_handler=wait_for_browser_callback,
)
async with streamablehttp_client(
url=server_url,
auth=oauth_auth,
timeout=timedelta(seconds=60),
) as (read_stream, write_stream, get_session_id):
async with ClientSession(read_stream, write_stream) as session:
await session.initialize()
# List available tools
tools = await session.list_tools()
for tool in tools.tools:
print(f" - {tool.name}: {tool.description}")
# Invoke a tool
result = await session.call_tool(
"add_numbers", {"a": 2, "b": 2}
)
print(f"Result: {result.content[0].text}")
The OAuth flow happens automatically:
- The MCP SDK discovers Auth0’s endpoints from the discovery URL
- The client registers itself using DCR
- A browser window opens for user authentication
- The callback server captures the authorization code
- The SDK exchanges the code for a JWT access token
- All MCP requests include the JWT in the Authorization header
Test the authenticated MCP server
Step 7: Run the client
import mcp_auth0_client as mcp_client
agent_arn = launch_result.agent_arn
base_endpoint = f"https://bedrock-agentcore.{region}.amazonaws.com"
await mcp_client.main(agent_arn, base_endpoint, AUDIENCE)
The client connects, authenticates via browser, and invokes all three tools on the deployed server.
Step 8: Clean up
agentcore_runtime.destroy()
. . .
Reference
- amazon-bedrock-agentcore-samples — Full sample repository
- MCP DCR tutorial — Source notebook for this tutorial
- Amazon Bedrock AgentCore documentation — Official service documentation
- Model Context Protocol specification — Official MCP specification
- Auth0 documentation — Identity provider documentation
What’s next
- Full MCP server end-to-end — Complete MCP server deployment with all production patterns
- AgentCore Gateway — Route requests across multiple agents with the Gateway service
- AgentCore Memory — Add short-term and long-term memory to your agents
- AgentCore Observability — Monitor and trace agent executions in production
메타데이터
- post_id
- b7bb68ca4ac6
- slug
- mcp-dynamic-client-registration-with-auth0-on-amazon-bedrock-agentcore-runtime-b7bb68ca4ac6
- url
- https://medium.com/@thecraftman/mcp-dynamic-client-registration-with-auth0-on-amazon-bedrock-agentcore-runtime-b7bb68ca4ac6
- canonical_url
- https://medium.com/@thecraftman/mcp-dynamic-client-registration-with-auth0-on-amazon-bedrock-agentcore-runtime-b7bb68ca4ac6
- author_url
- https://medium.com/@thecraftman
- status
- ok
- fetched_at
- 2026-06-09 15:37:30