1. Updates docs to prefer `uv run server.py` instead of `arcade mcp` or `python -m arcade_mcp_server` 2. Found a bug with running stdio servers while updating the docs, so i snuck that in this PR
3.4 KiB
3.4 KiB
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
--8<-- "docs/examples/07_auth.py"
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