Auth0 AI Agent Hackathon Submission
This guide walks you through testing the MCS Auth Bridge in three environments: a local CLI agent, an OpenWebUI tool, and a Claude Code Desktop (CoWork) skill. All three use the same SDK, the same Auth0 Token Vault integration, and the same LinkAuth device-flow UX.
Time estimate: ~30 min for Auth0 setup + ~10 min per use case.
- Prerequisites: Auth0 + Google Setup
- Use Case 1: CLI Agent (Interactive Chat)
- Use Case 2: OpenWebUI Tool
- Use Case 3: Claude Code Desktop (CoWork Skill)
- Troubleshooting
- Links
You need an Auth0 tenant and a Google Cloud project. If you already have both configured for Token Vault, skip to the Checklist to verify.
- Go to Google Cloud Console > APIs & Services > Credentials
- Click + CREATE CREDENTIALS > OAuth client ID
- Application type: Web application
- Name: e.g. "MCS Gmail Agent"
- Under Authorized redirect URIs, add:
(e.g.https://YOUR-AUTH0-DOMAIN/login/callbackhttps://dev-abc123.us.auth0.com/login/callback) - Click Create and note the Client ID and Client Secret
- Go to APIs & Services > Library
- Search for Gmail API
- Click Enable
- Go to APIs & Services > OAuth consent screen
- Under Data Access (or Scopes), add:
https://mail.google.com/https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.sendhttps://www.googleapis.com/auth/gmail.modify
- Under Test users, add the Gmail address you want to test with
Note: While your Google app is in "Testing" mode, only explicitly added test users can authenticate. For production, you'd need to go through Google's OAuth verification process.
- Go to Auth0 Dashboard > Applications > Applications
- Click + Create Application
- Name: e.g. "MCS Gmail Agent"
- Type: Regular Web Applications
- Click Create
- Note the Domain, Client ID, and Client Secret
- Open your application > Settings > scroll to Advanced Settings > Grant Types
- Enable:
- Authorization Code (should be on by default)
- Refresh Token
- Token Vault (this is the Token Exchange grant for federated access tokens)
- Click Save Changes
- Go to Authentication > Social
- Click Create Connection > Google / Gmail
- Enter the Google Client ID and Client Secret from step 1.1
- Under Purpose, enable both toggles:
- Authentication -- ON
- Connected Accounts for Token Vault -- ON
- Click Save
- Go to the Applications tab on the connection page
- Toggle your application ON
Important: If you only enable "Connected Accounts" without "Authentication", Google won't appear as a login option. You need both.
- Go to Applications > APIs
- Click + Create API
- Name: e.g. "MCS API"
- Identifier: e.g.
https://mcs-gmail/api(this becomes youraudience) - Click Create
- On the API settings page, enable Allow Offline Access
MRRT allows a single refresh token to be exchanged for tokens for multiple APIs (your API + the My Account API for Connected Accounts).
- Open your application > Settings
- Scroll to Multi-Resource Refresh Token
- Click Edit Configuration
- Toggle the My Account API ON
- Click Save
Note: If you don't see this section, MRRT may need to be enabled at the tenant level. Go to Settings > Advanced and look for "Multi-Resource Refresh Tokens".
Before proceeding, verify all of these are in place:
- Google Cloud: OAuth 2.0 credentials created with correct redirect URI
- Google Cloud: Gmail API enabled
- Google Cloud: Test user added to OAuth consent screen
- Auth0: Regular Web Application created (Confidential Client)
- Auth0: Grant Types include Authorization Code, Refresh Token, and Token Vault
- Auth0: Google Social Connection with Authentication AND Connected Accounts enabled
- Auth0: Google connection linked to your application
- Auth0: API created with Allow Offline Access enabled
- Auth0: MRRT configured with My Account API
You'll need these values for all three use cases:
| Value | Where to find it | Example |
|---|---|---|
AUTH0_DOMAIN |
Auth0 > Applications > Your App > Settings | dev-abc123.us.auth0.com |
AUTH0_CLIENT_ID |
Same page | aB1cD2eF3gH4iJ5kL6 |
AUTH0_CLIENT_SECRET |
Same page (click to reveal) | xYz... |
AUTH0_AUDIENCE |
Auth0 > Applications > APIs > Your API | https://mcs-gmail/api |
LINKAUTH_BROKER_URL |
Your LinkAuth broker deployment | https://broker.yourdomain.com |
LINKAUTH_API_KEY |
Your LinkAuth broker API key | la_... |
LinkAuth Broker: All examples use LinkAuth, a self-hosted credential broker. You need your own deployment. For this hackathon demo, we provide a hosted instance at
broker.linkauth.io-- contact us for an API key if you'd like to test without self-hosting.
A fully interactive chat client that reads and sends email through any LLM. The agent discovers Gmail tools automatically, and authentication happens transparently via LinkAuth's device-flow UX.
pip install mcs-driver-mail[gmail] mcs-auth-auth0 mcs-auth-linkauth mcs-types-cache litellm rich python-dotenvClone the repo and set up the .env file:
git clone https://github.com/modelcontextstandard/python-sdk.git
cd python-sdk/mcs-examples/gmail_agent
cp .env.example .envEdit .env:
# LLM API key (any LiteLLM-compatible provider)
OPENAI_API_KEY=sk-...
# Auth0 credentials
AUTH0_DOMAIN=dev-abc123.us.auth0.com
AUTH0_CLIENT_ID=aB1cD2eF3gH4iJ5kL6
AUTH0_CLIENT_SECRET=xYz...
AUTH0_AUDIENCE=https://mcs-gmail/api
# LinkAuth broker
LINKAUTH_BROKER_URL=https://broker.yourdomain.com
LINKAUTH_API_KEY=la_...python main.py --auth0-linkauth --debug- The agent starts and shows a chat prompt
- Type: "Show me my last 5 emails"
- The agent calls
list_messages-- this triggers authentication - A LinkAuth URL and code appear in the chat:
Authentication required for 'gmail'. Please open https://broker.yourdomain.com/connect/ABCD-1234 and enter code: ABCD-1234 - Open the URL in your browser, authenticate with Google
- Press Enter in the chat -- the agent polls, gets the token, and displays your emails
- All subsequent requests use the cached token -- no more authentication
- The
--debugflag shows the full auth chain: LinkAuth session creation, Token Vault exchange, Gmail API calls - The agent code itself has zero auth logic -- it's all handled by
AuthMixin - Try different commands: "Search for emails from Amazon", "Send an email to test@example.com"
The same Gmail agent runs inside OpenWebUI as a drop-in Python tool. No server setup, no callback URLs -- paste one file and it works.
- A running OpenWebUI instance (Docker quickstart)
- Admin access to create tools
- Open OpenWebUI and navigate to Workspace > Tools
- Click the + button to create a new tool
- Open
mcs_gmail_tool_auth0.pyfrom the repo - Copy the entire file contents into the tool editor
- Before saving, edit the class-level constants at the top of the
Toolsclass:
class Tools:
AUTH0_DOMAIN = "dev-abc123.us.auth0.com" # Your Auth0 domain
AUTH0_CLIENT_ID = "aB1cD2eF3gH4iJ5kL6" # Your client ID
AUTH0_CLIENT_SECRET = "xYz..." # Your client secret
AUTH0_AUDIENCE = "https://mcs-gmail/api" # Your API audience
LINKAUTH_BROKER_URL = "https://broker.yourdomain.com"
LINKAUTH_API_KEY = "la_..." # Your broker API key- Click Save -- OpenWebUI auto-installs the pip dependencies from the metadata header
- Start a new chat
- Click the + icon next to the chat input and enable the MCS Gmail Agent tool
- Type: "Show me my last 5 emails"
- The LLM calls
list_messages - The tool returns an
AuthChallengemessage with a LinkAuth URL - The LLM shows you the URL in the chat -- click it and authenticate with Google
- Send a follow-up message (e.g. "Try again" or "Now show my emails")
- The tool completes the auth flow and returns your emails
- The tool auto-discovers all 9 Gmail tools from the MCS
MailDriver - Auth challenges appear naturally as chat messages -- the LLM presents them to the user
- The
AuthMixinpattern handles the challenge/retry loop transparently
This is the hardest environment: a sandboxed container where every skill invocation is a fresh process. No persistent memory, no browser, restricted network egress. The FileCacheStore, LinkAuth session persistence, and broker proxy make this work.
- Claude Code Desktop with a Pro, Max, Teams, or Enterprise plan
- CoWork mode (the Code tab, not the Chat tab)
-
Download the skill zip from the repo:
mcs-examples/skills/mcs-gmail/Or create the zip yourself:
cd python-sdk/mcs-examples/skills zip -r mcs-gmail.zip mcs-gmail/ -
In Claude Code Desktop, go to Settings > Skills > Import Skill
-
Select
mcs-gmail.zip
After importing, find the skill directory and create config.toml:
# The skill will be at ~/.claude/skills/mcs-gmail/ or similar
cp config.toml.example config.tomlEdit config.toml:
auth0_domain = "dev-abc123.us.auth0.com"
auth0_client_id = "aB1cD2eF3gH4iJ5kL6"
auth0_client_secret = "xYz..."
auth0_audience = "https://mcs-gmail/api"
linkauth_broker_url = "https://broker.yourdomain.com"
linkauth_api_key = "la_..."In Claude Code Desktop settings, whitelist these domains for network egress:
broker.yourdomain.com(your LinkAuth broker -- handles auth AND proxies Auth0 Token Vault calls)gmail.googleapis.com(Gmail API data access)pypi.organdfiles.pythonhosted.org(for pip install)
Note: You do NOT need to whitelist
*.auth0.com. All Token Vault exchanges are proxied through the LinkAuth broker.
- Open the Code tab (CoWork mode)
- Ask: "Read my last 5 emails"
- Claude will run the skill, which triggers
pip installon first run
- First invocation: The skill creates a LinkAuth session and returns an
AuthChallenge. Claude shows you the URL and code. - Click the link and authenticate with Google
- Second invocation: Claude retries automatically. The skill restores the session from
~/.mcs/cache/mcs-gmail.json, polls the broker, gets the refresh token, exchanges it via Token Vault (through the broker proxy), and calls the Gmail API. - Subsequent invocations: Tokens are served from cache -- instant, no auth needed.
- Stateless persistence: Each invocation is a fresh Python process, but the
FileCacheStorepreserves RSA keys, sessions, and tokens between runs - No auth0.com access needed: Token Vault exchanges go through
broker.yourdomain.com/v1/proxy - Automatic retry: Claude handles the AuthChallenge pattern naturally -- it shows the link, waits for you, then retries
Google blocks user-data API access (Gmail, Drive, Sheets) from Anthropic's cloud egress IP range (Issue #11897). This affects the Chat tab (remote execution). The CoWork/Code tab (local execution) works because requests originate from your local machine.
| Error | Cause | Fix |
|---|---|---|
federated_connection_refresh_token_not_found |
Token Vault can't find a Connected Account | Verify the checklist -- especially "Connected Accounts for Token Vault" toggle and MRRT |
403 Forbidden (HTML page, not JSON) |
Google blocks the request at infrastructure level | CoWork mode: check domain whitelist. Chat mode: known Google IP block (#11897) |
403 Forbidden (JSON Insufficient Permission) |
OAuth token lacks Gmail scopes | Ensure Gmail API is enabled in Google Cloud and scopes are configured on the Auth0 connection |
TypeError: unexpected keyword argument '_token_cache' |
Old package version installed | Run pip install mcs-auth-linkauth>=0.4.1 mcs-types-cache>=0.1.1 |
AuthChallenge loops forever |
Session state lost between invocations | Check that ~/.mcs/cache/ is writable. FileCacheStore raises OSError at construction if not. |
OSError: Cache directory not writable |
Cache path is on a read-only filesystem | Set MCS_CACHE_DIR=/tmp/mcs-cache or another writable path |
ConnectionError: BLOCKED by network restriction |
Domain not whitelisted in sandbox | Add the domain to allowed network egress |
| Token expired (works once, then 403) | Cached access token TTL expired | Delete ~/.mcs/cache/mcs-gmail.json -- a fresh token exchange will happen on next call |
To start fresh (e.g. to re-test the full auth flow):
# Remove cached tokens
rm ~/.mcs/cache/mcs-gmail.json
# For CLI agent, also check:
rm mcs-examples/gmail_agent/.mcs_token_cache 2>/dev/null| Component | Repository | PyPI |
|---|---|---|
| MCS Python SDK | modelcontextstandard/python-sdk | Multiple packages |
| LinkAuth Broker | LinkAuth/LinkAuth | -- |
| Gmail Agent (CLI) | mcs-examples/gmail_agent | -- |
| Gmail Tool (OpenWebUI) | mcs-examples/openwebui | -- |
| Gmail Skill (Claude Code) | mcs-examples/skills/mcs-gmail | -- |
mcs-driver-mail==0.1.2 # Composite mail driver
mcs-driver-mailread==0.2.0 # Gmail read adapter
mcs-driver-mailsend==0.2.0 # Gmail send adapter
mcs-auth==0.3.0 # CredentialProvider base
mcs-auth-auth0==0.4.1 # Auth0 Token Vault provider
mcs-auth-linkauth==0.4.1 # LinkAuth connector
mcs-types-cache==0.1.1 # CachePort + FileCacheStore
mcs-adapter-http==0.3.0 # HTTP transport
Built for the Auth0 AI Agent Hackathon.