07 - OAuth Tools
Learn how to create tools that require OAuth
Prerequisites
Before running this example, you need to authenticate with Arcade:
# Install the Arcade CLI (if not already installed)
uv pip install arcade-mcp
# Login to Arcade
arcade login
Running the Example
- Run HTTP:
uv run examples/07_auth.py
- Run stdio:
uv run examples/07_auth.py stdio
Source Code
#!/usr/bin/env python3
"""
07_auth.py - Using tools with OAuth
This example demonstrates how to create and use tools that require OAuth.
Tools that require auth will automatically prompt users to authorize the action when called.
Prerequisites:
1. Install arcade-mcp: uv pip install arcade-mcp
2. Login to Arcade: arcade login
3. Run this server: uv run 07_auth.py
To run:
uv run examples/07_auth.py
uv run examples/07_auth.py stdio # For Claude Desktop
"""
import sys
from typing import Annotated
import httpx
from arcade_mcp_server import Context, MCPApp
from arcade_mcp_server.auth import Reddit
# Create the app
app = MCPApp(name="auth_example", version="1.0.0", log_level="DEBUG")
# To use this tool, you need to use the Arcade CLI (uv pip install arcade-mcp)
# and run 'arcade login' to authenticate.
@app.tool(requires_auth=Reddit(scopes=["read"]))
async def get_posts_in_subreddit(
context: Context, subreddit: Annotated[str, "The name of the subreddit"]
) -> dict:
"""Get posts from a specific subreddit"""
# Normalize the subreddit name
subreddit = subreddit.lower().replace("r/", "").replace(" ", "")
# Prepare the httpx request
# OAuth token is injected into the context at runtime.
# LLMs and MCP clients cannot see or access your OAuth tokens.
oauth_token = context.get_auth_token_or_empty()
headers = {
"Authorization": f"Bearer {oauth_token}",
"User-Agent": "mcp_server-mcp-server",
}
params = {"limit": 5}
url = f"https://oauth.reddit.com/r/{subreddit}/hot"
# Make the request
async with httpx.AsyncClient() as client:
response = await client.get(url, headers=headers, params=params)
response.raise_for_status()
# Return the response
return response.json()
# Run with specific transport
if __name__ == "__main__":
# Get transport from command line argument, default to "http"
transport = sys.argv[1] if len(sys.argv) > 1 else "http"
print(f"Starting auth example server with {transport} transport")
print("Prerequisites:")
print(" 1. Install: uv pip install arcade-mcp")
print(" 2. Login: arcade login")
print("")
# Run the server
# - "http" (default): HTTP streaming for Cursor, VS Code, etc.
# - "stdio": Standard I/O for Claude Desktop, CLI tools, etc.
app.run(transport=transport, host="127.0.0.1", port=8000)
OAuth Authentication Features
1. Requiring Authentication
Use the requires_auth
parameter with an auth provider to require OAuth:
from arcade_mcp_server.auth import Reddit
@app.tool(requires_auth=Reddit(scopes=["read"]))
async def get_posts_in_subreddit(
context: Context,
subreddit: Annotated[str, "The name of the subreddit"]
) -> dict:
"""Get posts from a specific subreddit."""
# OAuth token is automatically injected into context
oauth_token = context.get_auth_token_or_empty()
# Use the token to make authenticated API requests
2. Specifying OAuth Scopes
Different tools may require different scopes:
# Read-only access
@app.tool(requires_auth=Reddit(scopes=["read"]))
async def read_only_tool(context: Context) -> dict:
"""Tool that only reads data."""
pass
# Multiple scopes for more permissions
@app.tool(requires_auth=Reddit(scopes=["read", "identity"]))
async def identity_tool(context: Context) -> dict:
"""Tool that accesses user identity."""
pass
3. Accessing OAuth Tokens
OAuth tokens are securely injected into the context at runtime:
# Get the token (returns empty string if not authenticated)
oauth_token = context.get_auth_token_or_empty()
# Use token in API requests
headers = {
"Authorization": f"Bearer {oauth_token}",
"User-Agent": "my-app",
}
4. Making Authenticated API Requests
Use the OAuth token with httpx or other HTTP clients:
import httpx
async with httpx.AsyncClient() as client:
response = await client.get(
"https://oauth.reddit.com/api/endpoint",
headers={"Authorization": f"Bearer {oauth_token}"}
)
response.raise_for_status()
return response.json()
Available Auth Providers
The arcade_mcp_server.auth
module provides several OAuth providers:
Authentication Flow
- User runs
arcade login
: Authenticates with Arcade and stores credentials - Tool is called: MCP client calls a tool that requires authentication
- Authorization Required: If the user has not authorized the required scopes, then they are prompted to go through an OAuth flow
- Token injection: Arcade injects the OAuth token into the tool's context
- API request: Tool uses the token to make authenticated API requests
- Response: Tool returns data to the MCP client
The LLM and MCP clients never see the OAuth tokens - they are securely injected server-side.
Security Best Practices
- Never log tokens: OAuth tokens should never be logged or exposed
- Use appropriate scopes: Request only the scopes your tool actually needs
Key Concepts
- OAuth Integration: Arcade handles OAuth flows and token management
- Secure Token Injection: Tokens are injected into context at runtime
- Scope Management: Specify exactly which permissions your tool needs
- Provider Support: Multiple OAuth providers available out of the box
- User Privacy: LLMs and MCP clients never see OAuth tokens