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

Rays decoration image
COMPANY NEWS

Why We Rebuilt Arcade's Pricing from the Ground Up

Today, we’re launching the second iteration of our pricing plan. We’re walking through the details so you can see how we’re making our authorization and tool management platform accessible to even more developers and their agents.  Our goal is to get your agents into production. This involves not just calling well-designed, LLM-consumable tools, but also authorizing many end users into your agent, which is not yet possible with MCP Servers. Our first pricing plan charged based on the number of

Rays decoration image
COMPANY NEWS

Arcade.dev Achieves SOC 2 Type 2: Because Agent Security Isn't Optional

Here's a fact that keeps enterprise CTOs up at night: 70% of AI agent projects never reach production. The primary killer? Security reviews that reveal agents can't be trusted with enterprise systems. Today, Arcade.dev achieved SOC 2 Type 2 certification. But unlike typical compliance announcements, this isn't about checking boxes. It's about solving the fundamental trust problem that blocks agent deployment (and we checked the boxes too). Why Agent Security Hits Different Traditional softwa

Rays decoration image
TUTORIALS

The 3-Agent Pattern: How Chex Built a Full-Stack Mental Health Assistant

Most AI agents are glorified chatbots. Chex just won a hackathon by building three specialized agents that actually book therapy appointments. Not suggest. Not recommend. Actually book — complete with calendar invites and email confirmations. Here's the pattern they discovered that you can steal for your own agent systems. Want to skip to the code? Check out our Quickstart or get your Arcade.dev API key to build authenticated agents in minutes. The Problem: Single Agents Hit Walls Traditio

Blog CTA Icon

Get early access to Arcade, and start building now.