Skip to content

Instantly share code, notes, and snippets.

@bizrockman
Created March 27, 2026 17:56
Show Gist options
  • Select an option

  • Save bizrockman/712336de8bc84e7a7594b4460cf99a1f to your computer and use it in GitHub Desktop.

Select an option

Save bizrockman/712336de8bc84e7a7594b4460cf99a1f to your computer and use it in GitHub Desktop.
JUDGES_TESTING_GUIDE.md

MCS Auth Bridge -- Judges Testing Guide

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.


Table of Contents

  1. Prerequisites: Auth0 + Google Setup
  2. Use Case 1: CLI Agent (Interactive Chat)
  3. Use Case 2: OpenWebUI Tool
  4. Use Case 3: Claude Code Desktop (CoWork Skill)
  5. Troubleshooting
  6. Links

1. Prerequisites: Auth0 + Google Setup

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.

1.1 Google Cloud Console

Create OAuth 2.0 Credentials

  1. Go to Google Cloud Console > APIs & Services > Credentials
  2. Click + CREATE CREDENTIALS > OAuth client ID
  3. Application type: Web application
  4. Name: e.g. "MCS Gmail Agent"
  5. Under Authorized redirect URIs, add:
    https://YOUR-AUTH0-DOMAIN/login/callback
    
    (e.g. https://dev-abc123.us.auth0.com/login/callback)
  6. Click Create and note the Client ID and Client Secret

Enable Gmail API

  1. Go to APIs & Services > Library
  2. Search for Gmail API
  3. Click Enable

Configure OAuth Consent Screen

  1. Go to APIs & Services > OAuth consent screen
  2. Under Data Access (or Scopes), add:
    • https://mail.google.com/
    • https://www.googleapis.com/auth/gmail.readonly
    • https://www.googleapis.com/auth/gmail.send
    • https://www.googleapis.com/auth/gmail.modify
  3. 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.

1.2 Auth0 Dashboard

Create Application

  1. Go to Auth0 Dashboard > Applications > Applications
  2. Click + Create Application
  3. Name: e.g. "MCS Gmail Agent"
  4. Type: Regular Web Applications
  5. Click Create
  6. Note the Domain, Client ID, and Client Secret

Enable Grant Types

  1. Open your application > Settings > scroll to Advanced Settings > Grant Types
  2. Enable:
    • Authorization Code (should be on by default)
    • Refresh Token
    • Token Vault (this is the Token Exchange grant for federated access tokens)
  3. Click Save Changes

Add Google Social Connection

  1. Go to Authentication > Social
  2. Click Create Connection > Google / Gmail
  3. Enter the Google Client ID and Client Secret from step 1.1
  4. Under Purpose, enable both toggles:
    • Authentication -- ON
    • Connected Accounts for Token Vault -- ON
  5. Click Save
  6. Go to the Applications tab on the connection page
  7. Toggle your application ON

Important: If you only enable "Connected Accounts" without "Authentication", Google won't appear as a login option. You need both.

Create an API (if you don't have one)

  1. Go to Applications > APIs
  2. Click + Create API
  3. Name: e.g. "MCS API"
  4. Identifier: e.g. https://mcs-gmail/api (this becomes your audience)
  5. Click Create
  6. On the API settings page, enable Allow Offline Access

Enable MRRT (Multi-Resource Refresh Tokens)

MRRT allows a single refresh token to be exchanged for tokens for multiple APIs (your API + the My Account API for Connected Accounts).

  1. Open your application > Settings
  2. Scroll to Multi-Resource Refresh Token
  3. Click Edit Configuration
  4. Toggle the My Account API ON
  5. 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".

Checklist

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

Credentials Summary

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.


2. Use Case 1: CLI Agent (Interactive Chat)

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.

Install

pip install mcs-driver-mail[gmail] mcs-auth-auth0 mcs-auth-linkauth mcs-types-cache litellm rich python-dotenv

Configure

Clone 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 .env

Edit .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_...

Run

python main.py --auth0-linkauth --debug

Expected Flow

  1. The agent starts and shows a chat prompt
  2. Type: "Show me my last 5 emails"
  3. The agent calls list_messages -- this triggers authentication
  4. 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
    
  5. Open the URL in your browser, authenticate with Google
  6. Press Enter in the chat -- the agent polls, gets the token, and displays your emails
  7. All subsequent requests use the cached token -- no more authentication

What to Look For

  • The --debug flag 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"

3. Use Case 2: OpenWebUI Tool

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.

Prerequisites

Install the Tool

  1. Open OpenWebUI and navigate to Workspace > Tools
  2. Click the + button to create a new tool
  3. Open mcs_gmail_tool_auth0.py from the repo
  4. Copy the entire file contents into the tool editor
  5. Before saving, edit the class-level constants at the top of the Tools class:
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
  1. Click Save -- OpenWebUI auto-installs the pip dependencies from the metadata header

Activate and Test

  1. Start a new chat
  2. Click the + icon next to the chat input and enable the MCS Gmail Agent tool
  3. Type: "Show me my last 5 emails"

Expected Flow

  1. The LLM calls list_messages
  2. The tool returns an AuthChallenge message with a LinkAuth URL
  3. The LLM shows you the URL in the chat -- click it and authenticate with Google
  4. Send a follow-up message (e.g. "Try again" or "Now show my emails")
  5. The tool completes the auth flow and returns your emails

What to Look For

  • 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 AuthMixin pattern handles the challenge/retry loop transparently

4. Use Case 3: Claude Code Desktop (CoWork Skill)

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.

Prerequisites

  • Claude Code Desktop with a Pro, Max, Teams, or Enterprise plan
  • CoWork mode (the Code tab, not the Chat tab)

Install the Skill

  1. 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/
  2. In Claude Code Desktop, go to Settings > Skills > Import Skill

  3. Select mcs-gmail.zip

Configure

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.toml

Edit 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_..."

Configure Network Egress

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.org and files.pythonhosted.org (for pip install)

Note: You do NOT need to whitelist *.auth0.com. All Token Vault exchanges are proxied through the LinkAuth broker.

Test in CoWork Mode

  1. Open the Code tab (CoWork mode)
  2. Ask: "Read my last 5 emails"
  3. Claude will run the skill, which triggers pip install on first run

Expected Flow

  1. First invocation: The skill creates a LinkAuth session and returns an AuthChallenge. Claude shows you the URL and code.
  2. Click the link and authenticate with Google
  3. 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.
  4. Subsequent invocations: Tokens are served from cache -- instant, no auth needed.

What to Look For

  • Stateless persistence: Each invocation is a fresh Python process, but the FileCacheStore preserves 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

Known Limitation

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.


5. Troubleshooting

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

Clearing Auth State

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

6. Links

Source Code

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 --

Key Packages (PyPI)

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

Documentation


Built for the Auth0 AI Agent Hackathon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment