mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

AI Agents

MCP as Auth Gateway: Why Model Context Protocol's Real Value Is Credential Isolation, Not Tool Discovery

MCP's server-side auth flow keeps credentials out of agent context windows. That's the protocol's killer feature, not its tool registry.

Source: simonwillison.net
MCP as Auth Gateway: Why Model Context Protocol's Real Value Is Credential Isolation, Not Tool Discovery

The Model Context Protocol debate usually centers on tool discovery and orchestration. Sean Lynch’s Hacker News comment reframes the conversation:

The real valuable capability MCP offers over skills/CLI is isolating the auth flow outside of the agent’s context window, and potentially out of the harness completely. […] Maybe the idealized form of MCP is just an auth gateway for the API and nothing else. That’d still be a win.

Not the tool registry, not the schema negotiation. The authentication boundary. This matters because most agent architectures leak secrets. CLI tools read environment variables. Function-calling systems pass API keys as parameters. Logs capture everything. MCP’s server-side auth flow creates a hard boundary that existing patterns can’t match.

The Credential Leakage Problem

When you give an agent access to external services, you face three bad options:

  1. Environment variables: The agent process inherits GITHUB_TOKEN, STRIPE_SECRET_KEY, and every other credential. One malicious prompt or logging misconfiguration exposes everything.

  2. Function parameters: You pass credentials as arguments to tool functions. Now they live in the LLM’s context window, training data risk surface, and every intermediate log.

  3. Config files: The agent reads ~/.aws/credentials or .env. Same problem as environment variables, plus filesystem access sprawl.

All three patterns put secrets in scope of the agent’s execution context. MCP isolates them on the server side.

MCP’s Authentication Architecture

MCP splits the world into clients (the agent harness) and servers (the service wrapper). The server holds credentials. The client never sees them.

Flow:

  1. Agent decides it needs to call GitHub API
  2. Client sends MCP request to GitHub server
  3. Server authenticates with GitHub using stored OAuth token
  4. Server returns data to client
  5. Agent sees results, never sees token

The protocol defines transport (stdio, HTTP, WebSocket) and message format (JSON-RPC 2.0). The critical piece is the trust boundary. The server process runs in a separate security context.

Minimal MCP server structure:

from mcp.server import Server
from mcp.server.stdio import stdio_server
import httpx

server = Server("github-mcp")

# Token lives here, not in agent context
GITHUB_TOKEN = os.environ["GITHUB_TOKEN"]

@server.call_tool()
async def fetch_repo(owner: str, name: str):
    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"https://api.github.com/repos/{owner}/{name}",
            headers={"Authorization": f"Bearer {GITHUB_TOKEN}"}
        )
        return response.json()

if __name__ == "__main__":
    stdio_server(server)

The agent process spawns this server via stdio. The token never crosses the boundary. Logs on the client side show tool calls and results, not credentials.

Comparison: MCP vs. Existing Auth Patterns

PatternCredential ScopeAgent VisibilityAudit Surface
Environment variablesAgent processFullProcess logs, memory dumps
Function parametersLLM context windowFullPrompt logs, training data
OAuth device flowUser browserPartial (refresh token in agent)Token storage, network logs
MCP serverSeparate processNoneServer logs only
API proxy with OAuthSeparate serviceNoneProxy logs, network

MCP and API proxies both isolate credentials. The difference is deployment shape. An API proxy is a long-running service with its own infrastructure. An MCP server is a subprocess the agent spawns on demand.

When MCP wins:

  • Local development (no proxy deployment)
  • Per-user credential isolation (each agent instance spawns its own server)
  • Dynamic service discovery (agent decides which servers to start)

When a proxy wins:

  • Centralized credential rotation
  • Rate limiting across multiple agents
  • Compliance logging requirements

The Minimal Implementation

If MCP is “just an auth gateway,” what does that look like?

Core components:

  1. Server process: Holds credentials, makes authenticated API calls
  2. Transport layer: stdio, HTTP, or WebSocket
  3. Message protocol: JSON-RPC 2.0 for tool calls
  4. Client library: Spawns server, routes tool calls

What you can skip:

  • Tool discovery (hardcode the tools you need)
  • Schema negotiation (use fixed schemas)
  • Resource subscriptions (poll instead)
  • Sampling (let the LLM handle retries)

A minimal implementation following this pattern demonstrates the core value. The security boundary is the process boundary. Credentials remain server-side throughout.

# Minimal client-side integration
# Production code requires proper JSON-RPC 2.0 framing, error handling, and process lifecycle management.
import subprocess
import json

def call_mcp_tool(server_path, tool_name, args):
    proc = subprocess.Popen(
        [server_path],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    
    request = {
        "jsonrpc": "2.0",
        "method": "tools/call",
        "params": {
            "name": tool_name,
            "arguments": args
        },
        "id": 1
    }
    
    proc.stdin.write(json.dumps(request).encode() + b"\n")
    proc.stdin.flush()
    
    response = json.loads(proc.stdout.readline())
    return response["result"]

This is 20 lines. The security boundary is the process boundary. The boundary holds: credentials stay in the server process.

Failure Modes

Server crashes: The agent loses access to that service. Retry logic lives in the client. If the server holds state (like an open database connection), you lose it on crash. Stateless servers are safer but require the agent to manage session context.

Credential rotation: The server needs a way to refresh tokens. Either restart the server with new credentials or implement a refresh mechanism. MCP doesn’t specify this. You’ll need to build token refresh into the server or accept manual restarts.

Multi-tenancy: If multiple agents share one server, credentials are shared across all agents. This is a feature (centralized auth) or a bug (unintended credential scope), depending on your threat model. The protocol supports session management (each client gets a session ID), but most implementations don’t use it. Shared servers introduce coordination overhead and require explicit decisions about credential scope.

Observability: Server-side logs are separate from agent logs. Correlating them requires trace IDs or request identifiers. The spec doesn’t mandate this, so you’ll implement it yourself or accept blind spots during debugging.

Network transport: stdio works for local servers. HTTP/WebSocket work for remote servers but reintroduce network attack surface. You’re back to securing an API endpoint, which means TLS, authentication, and rate limiting.

These failure modes inform the decision matrix for when MCP’s subprocess-based isolation is worth the operational complexity.

When MCP Adds Value vs. When It Doesn’t

Use MCP when:

  • You’re building local-first agent tools
  • Each user needs isolated credentials
  • You want subprocess-level security boundaries
  • You’re prototyping and need fast iteration

Skip MCP when:

  • You operate a centralized OAuth 2.0 gateway with token refresh, rate limiting, and audit logging (MCP adds subprocess overhead without additional security boundary)
  • You need compliance-grade audit trails that correlate all API calls across agents
  • Your agents run in untrusted environments where subprocess spawning is restricted or monitored
  • You’re integrating with services that don’t need auth (just call the API directly)

The protocol’s value is the security boundary, not the abstraction layer. If you can achieve the same boundary with a simpler pattern, do that instead.

Technical Verdict

MCP’s subprocess-based credential isolation closes a gap that OAuth device flow and environment variables leave open. By moving authentication into a separate process, the protocol ensures credentials never enter the agent’s execution context or LLM prompt logs.

Use it when you need per-user credential isolation in local agent deployments. The subprocess model works well for development and single-user tools. The minimal implementation is simple enough to justify the dependency.

Avoid it when you operate a centralized API gateway with OAuth 2.0 token management and audit logging. MCP adds subprocess coordination overhead without strengthening the security boundary in that architecture. Also skip it if your agents run in containerized or sandboxed environments where subprocess spawning introduces deployment friction or security review overhead.

The “auth gateway” framing is correct. MCP’s tool discovery and schema negotiation are useful but secondary. The credential isolation is the killer feature.