Building MCP Together: Arcade's Contribution to Secure Agent Auth

Building MCP Together: Arcade's Contribution to Secure Agent Auth

Nate Barbettini's avatar
Wils Dawson's avatar
Nate Barbettini & Wils Dawson
JULY 11, 2025
4 MIN READ
MCP
Rays decoration image
Ghost Icon

See URL Mode Elicitation in Action →
Watch our engineer Will Dawson walk through the new MCP proposal that's solving one of the biggest security gaps in AI tool-calling. In 15 minutes, you'll see how agents can finally handle OAuth flows, payment confirmations, and API keys without exposing sensitive data to the LLM.

Watch the technical walkthrough →

Your AI agent needs to search Gmail for that weekly report. You've built an MCP server, the tool definition, everything's wired up perfectly. One problem: there's no secure path in the protocol to get the OAuth 2.0 bearer token your agent needs to call the Gmail API.

This is the gap between MCP's design and production reality. While the protocol handles client-server authentication beautifully, it completely lacks a mechanism for servers to securely obtain third-party credentials. At Arcade.dev, we've been working to fix this fundamental limitation.

The Technical Problem: Credential Flow in Distributed Systems

Let's break down what's actually happening. Your MCP server needs to make authenticated requests to external APIs. But MCP has no secure credential gathering mechanism.

Current workarounds are all security anti-patterns for multi-user production systems:

  • Service account tokens with excessive scopes
  • Credentials hardcoded in server configs
  • Passing tokens through the MCP client (violating the principle of least privilege)
  • Client-side credential storage (hello, token exfiltration risks)

This isn't just bad UX—it's a fundamental security architecture flaw. MCP clients are often untrusted code running on user devices. They're OAuth 2.0 "public clients" that can't securely store secrets. Yet today, that's exactly what developers are forced to do.

Our Engineering Journey: Two Approaches to Secure Auth

PR #475: Adding User Interaction as a Client Capability

Our initial proposal introduced a new client capability for user interactions. The core insight: leverage the browser as a trusted security context, just like OAuth 2.0 has done successfully for 15+ years.

The implementation added a userInteraction capability:

interface UserInteractionRequest {
  method: "userInteraction";
  params: {
    prompt: string;
    url?: string;
    timeout?: number;
  };
}

This allowed servers to redirect users to secure endpoints for credential gathering, keeping sensitive data out of the client execution context entirely. The proposal sparked extensive discussion and security review with 50+ contributors examining attack vectors, CSRF protections, and state management.

But MCP 2025-06-18 shipped with  elicitation, a client capability for dynamically rendering forms and gathering data from the user. Elicitation via forms doesn't work for credentials or sensitive data, but could it be extended to enable secure user interactions?

PR #887: Extending Elicitation with URL Mode

Rather than having two similar-but-different client capabilities, we evolved our approach. PR #887 extends the elicitation framework with a new mode:

interface UrlElicitation {
  id: string;
  mode: "url";
  url: string;
  message: string;
  metadata?: {
    oauth_provider?: string;
    required_scopes?: string[];
    state?: string;
  };
}

This creates clear separation of concerns:

  • Form mode: Client-rendered UI for non-sensitive data (preferences, parameters)
  • URL mode: Direct browser navigation for sensitive flows (OAuth 2.0, payments, WebAuthn, SAML)

The security model is explicit: form elicitation flows data through the client, URL elicitation bypasses the client  entirely. But why does that matter?

Deep Dive: Why URL Elicitation Matters

Proper OAuth 2.0 Implementation

Consider implementing GitHub integration. With URL elicitation, you get proper OAuth 2.0:

# Server initiates OAuth flow
def handle_github_tool_call(params):
    if not has_valid_token(user_id):
        state = generate_secure_state()
        code_verifier = generate_code_verifier()
        
        auth_url = build_oauth_url(
            client_id=GITHUB_CLIENT_ID,
            redirect_uri=CALLBACK_URL,
            state=state,
            code_challenge=hash_verifier(code_verifier),
            scope="repo:read"
        )
        
        raise ElicitationRequired([{
            "id": f"github-auth-{state}",
            "mode": "url",
            "url": auth_url,
            "message": "Authorize GitHub access",
            "metadata": {
                "oauth_provider": "github",
                "required_scopes": ["repo:read"]
            }
        }])

Or, something other than OAuth entirely: a redirect to a payment portal, enterprise IDP login page, etc. The client just opens the URL. For the client, that means no token handling, no state management, no security responsibilities.

Respecting Security Boundaries

URL elicitation enforces proper security boundaries:

  1. Client (untrusted): Facilitates navigation, handles retry logic
  2. Server (trusted): Manages tokens, validates state, enforces scopes
  3. Auth provider (trusted): Handles user authentication, consent

This mirrors established web security patterns. The MCP client never touches credentials, preventing entire classes of attacks:

  • Token exfiltration via compromised clients
  • Scope escalation through client manipulation
  • The "confused deputy" problem

Real Implementation Benefits

From our research into production-ready MCP servers at Arcade:

// Before: Insecure token passing
const result = await mcp.callTool("search_gmail", {
  query: "weekly report",
  token: localStorage.getItem("gmail_token") // 🚨 Security nightmare
});

// After: Secure URL elicitation
try {
  const result = await mcp.callTool("search_gmail", {
    query: "weekly report"
  });
} catch (e) {
  if (e.code === "ELICITATION_REQUIRED") {
    // Client opens URL, user auths, server stores token
    window.open(e.elicitations[0].url);
      // Retry after auth completes
  }
}

This pattern mirrors what client apps already do to interact with services that require redirects for authorization.

Multi-Provider Authentication

Real agents need multiple auth providers. URL elicitation handles this elegantly:

// Server can request multiple authorizations
throw new ElicitationRequired([
  {
    id: "gmail-auth",
    mode: "url",
    url: getGoogleOAuthUrl(),
    message: "Authorize Gmail access"
  },
  {
    id: "slack-auth", 
    mode: "url",
    url: getSlackOAuthUrl(),
    message: "Connect Slack workspace"
  }
]);

What This Enables

With proper authorization, MCP servers are one step closer to being production-ready:

  • Scoped access: Request minimum necessary permissions
  • Token refresh: Handle expiry without user intervention
  • Audit trails: Track what actions were taken with which authorizations
  • Revocation: Users can revoke access anytime through the provider

The technical foundations matter. This is the difference between a demo and production infrastructure.

Implementation Timeline

PR #887 is under active review. For early adopters:

  1. Today: Arcade.dev tools already implement these patterns 
  2. Near term: URL elicitation standardizes the approach
  3. Future: The MCP ecosystem adopts these patterns in both clients and servers

Want to accelerate this?

  • Review PR #887 and stress-test the security model
  • Implement URL elicitation in your MCP server

Without a way to securely interact with the user, MCP is limited to servers that only connect to first-party APIs. By adding a mechanism that respects the security boundaries of the client (inspired by the battle-tested patterns used by OAuth), more powerful and interesting MCP servers are possible. We're excited about the future of MCP, what about you?


The Arcade.dev team has spent years hardening auth at Okta, Stormpath, and Redis. We're applying those lessons to make AI infrastructure production-ready.

Want to build AI agents that actually work in production? While we wait for authorization to land in MCP, Arcade already implements secure auth for 100+ integrations. No bot tokens, no security nightmares—just real OAuth flows that work.

Start building with Arcade → Sign Up.

SHARE THIS POST

RECENT ARTICLES

How Arcade Proactively Addressed The First Major Identity Vulnerability in Agentic AI

While building an AI demo has become trivially easy, production-grade deployments in enterprises have been stifled by performance issues, costs, and security vulnerabilities that their teams have been warning about. Today, we're addressing one of those vulnerabilities head-on. A new class of identity attack Security researchers at The Chinese University of Hong Kong recently identified new variants of COAT (Cross-app OAuth Account Takeover), an identity phishing attack targeting agentic AI a

TUTORIALS

New Year, New Agents to Make You More Productive

Most conversations about AI agents still start the same way: models, prompts, frameworks, followed by an incredible looking demo. Then someone asks, “Okay… when can it ship to production?” That’s where things get a little awkward. The naked truth in the fading demo afterglow is that agents are apps. Which means they need identity, permissions, real integrations, and a way to behave predictably when something goes sideways. Without these components, any agent can dazzle a boardroom, but it won

THOUGHT LEADERSHIP

5 Takeaways from the 2026 State of AI Agents Report

AI agents have moved quickly from experimentation to real-world deployment. Over the past year, organizations have gone from asking whether agents work to figuring out how to deploy enterprise AI agents reliably at scale. The 2026 State of AI Agents Report from the Claude team captures this shift clearly. Drawing on insights from teams building with modern LLM agents—including those powered by models from providers like Anthropic—the report offers a grounded view of how agentic systems are bein

Blog CTA Icon

Get early access to Arcade, and start building now.