Skip to main content

Core Philosophy

When Auth Matters

Authentication in MCPs shines when you already have:
  • An existing API with user accounts
  • A database with access control
  • Scopes and permissions defined
  • A working SaaS with authenticated users
The goal: expose the same access control to MCP users that your existing app users have. Same scopes, same permissions, same data boundaries.
Don’t create a separate auth system for MCPs. Use your existing OAuth provider — same client ID, same tenant, same everything.

The Architecture


Setting Up Authentication

Install @leanmcp/auth:

Provider-Specific Dependencies


Provider Setup

Clerk is the easiest option, especially if you plan to add payments later.
Environment variables:

AWS Cognito

If you’re using Amazon Amplify, use the same client ID and user pool:

Auth0


Protecting Tools

Method-Level Protection

Class-Level Protection

Protect all methods in a service:

The authUser Object

When using @Authenticated, a global authUser variable is injected containing the decoded JWT:

Client-Side: Passing Tokens

Clients pass tokens via _meta.authorization:
Raw MCP request:

Adding Payments

The Challenge

Previously, you’d pass Stripe session data to your frontend via API. With MCPs, you need to:
  1. Create a payment session
  2. Return the payment URL via MCP
  3. Let the agent show it to the user

Using Elicitation for Payments

Trigger payment flows with elicitation:

Handling Webhooks

Webhooks remain unchanged. Your existing Stripe webhook handler works the same:

Checking Subscription Status


Complete Example


Error Handling


Summary

Auth Examples

See working auth examples

Elicitation Guide

Learn about elicitation

OAuth Client

Browser-based OAuth flows with PKCE

OAuth Server

Build authorization servers with provider proxy