Terminal — ai coding agent — ~/project
~/project $ agent
 
ai-coding-agent v1.0.40
Model: a-random-sota-model via LLM Gateway
 
MCP Servers:
notion (remote — OAuth)
github (remote — OAuth)
tavily (remote — OAuth) — Not authenticated
 
You: Use the tavily MCP to search "what is the model context protocol"
 

Agent: I'll run that search for you.
 
tool search
{ "query": "what is the model context protocol" }
 
mcp tavily requires authentication
Server returned: 401 Unauthorized — Bearer token required
 
Agent: The tavily MCP server requires OAuth authentication.
Opening browser for SSO login...
 
◠ Waiting for OAuth callback on localhost:9876...
🔒 auth.example.com/login?client_id=tavily-mcp&response_type=code&redirect_uri=http://localhost:9876/callback
Tavily MCP Wrapper
Sign in to continue to MCP Authorization
● AWS Amazon Cognito Hosted UI
or
O Login with Company SSO Account
Click "Login with Company SSO" ↓
🔒 sso.example.com/app/tavily-mcp/sso/saml

Example Corp

Company Single Sign-On

SAML 2.0 · Federated Identity
🔒 Signing in to: tavily-mcp.example.com
Forgot password?
Verifying credentials & redirecting to Cognito...
Click "Verify & Continue" ↓
🔒 localhost:9876/callback?code=aBcDe12345&state=pkce_xyz

Authorization Successful

OAuth 2.0 token received via PKCE flow

User dev@example.com
Identity Provider O*ta SAML → Amazon Cognito
Access Token eyJhbG...Rk4x 🔒
Token Type Bearer (JWT)
Expires In 3600s
Scopes
openid tavily-mcp/search
✅ Token sent to AI Coding Agent on localhost:9876. You can close this browser tab.
Terminal — ai coding agent — ~/project
... (OAuth flow completed in browser)
 
oauth ✓ Token received from Cognito
User: dev@example.com
Scopes: openid, tavily-mcp/search
Expires: 3600s
 
MCP Servers:
notion (remote — OAuth)
github (remote — OAuth)
tavily (remote — OAuth) — Authenticated as dev
 

Agent: Great, I'm now authenticated. Let me run that search.
 
tool search
// params { "query": "what is the model context protocol" }
 
// output
{ "answer": "The Model Context Protocol (MCP) is an open standard that lets AI models connect to external tools and data sources through a uniform interface.", "results": [ { "title": "What is the Model Context Protocol?", "url": "https://www.databricks.com/blog/what-is-model-context-protocol" } ] }
200 ✓ Returned for dev@example.com (JWT validated)
 
Agent: Here's what I found:
MCP is an open standard for connecting AI models to external tools and data through a uniform interface.
 
You: Now use tavily to extract the full text of that page
 

Agent: I'll try the extract tool.
 
tool extract
// params { "url": "https://www.databricks.com/blog/what-is-model-context-protocol" }
 
// output
{ "error": "forbidden", "message": "dev@example.com does not have scope 'tavily-mcp/extract'", "required_scope": "tavily-mcp/extract", "user_scopes": ["openid", "tavily-mcp/search"], "status": 403 }
403 ✗ Forbidden — missing required scope
 
Agent: Access denied. Your token only grants tavily-mcp/search.
The extract tool requires tavily-mcp/extract, which your role doesn't include.
 
This is OAuth working as intended:
The AI agent can only call the tools your scopes allow. No more, no less.
 

 
⚠ Meanwhile, in the shared-API-key timeline...

💀 The "Old Way" — hardcoded credentials

Shared API key baked into every developer's mcp.json
Every call shares one identity — no per-user scope, no tool boundaries
Audit log says "api-key-prod"who actually made the call?
Someone leaves? Rotate key → break everyone
Key leaked in a repo? Full access until someone notices
 
// .mcp.json — the nightmare version { "tavily": { "type": "stdio", "command": "npx", "args": ["tavily-mcp"], "env": { "TAVILY_API_KEY": "tvly-SHARED-KEY-everyone-has-this" // 💀 on every laptop } } }
 
✓ With OAuth MCP
// .mcp.json — the OAuth version { "tavily": { "type": "http", "url": "https://<your-api>.execute-api.us-east-1.amazonaws.com/mcp" // That's it. No secrets. OAuth handles auth per-user. } }
 
Per-user identity — audit says exactly who
Scoped access — only what your role allows
Revoke one user — everyone else keeps working
No secrets in config — nothing to leak
SSO integration — same login as everything else
 
"If you can't do it in the UI, the agent can't do it via MCP"
Interactive demo: per-user OAuth in front of a shared-key MCP — source · talk slides
Scene 1 / 5 tavily MCP | OAuth 2.0 + PKCE ← p / n → · Space / Click