Authentication

Better Auth

Connect Better Auth OAuth, sign in from an MCP client, and use ctx.user in tools.

Use this when Better Auth's OAuth 2.1 plugin is your authorization server. Better Auth owns registration, authorization, consent, and token issuance. bitmcp verifies JWT access tokens against Better Auth's JWKS endpoint.

Configure Better Auth

In your Better Auth app:

  1. Enable the OAuth 2.1 Provider plugin
  2. Expose the issuer URL including the auth base path (for example https://app.example.com/api/auth)
  3. Confirm JWKS is served at {authURL}/jwks

Set environment variables

BETTER_AUTH_URL=https://app.example.com/api/auth

Shared production vars: Installation → Environment variables.

Configure bitmcp

bitmcp.config.ts
import { defineConfig } from "bitmcp";
import { betterAuth } from "bitmcp/oauth/better-auth";

export default defineConfig({
  http: {
    path: "/mcp",
    allowedHosts: ["mcp.example.com"],
  },
  auth: betterAuth(),
});

Or inline:

bitmcp.config.ts
auth: betterAuth({
  authURL: "https://app.example.com/api/auth",
}),

Use ctx.user in tools

get-posts/tool.ts
export default defineTool({
  description: "Get recent blog posts for the signed-in user",
  async execute(_input, ctx) {
    return {
      id: ctx.user!.id,
      email: ctx.user!.email,
      sessionId: ctx.user!.sessionId,
      posts: [],
    };
  },
});

Verify

  1. Start your Better Auth app and the bitmcp server
  2. Connect from an OAuth-capable MCP client
  3. Complete login through Better Auth
  4. Call a tool and confirm ctx.user is populated
  5. Call /mcp without a token and confirm 401

Options

betterAuth(options?: {
  authURL?: URL | string;
  resource?: URL | string;
  requiredScopes?: string[];
  scopesSupported?: string[];
  resourceName?: string;
})
VariablePurpose
BETTER_AUTH_URLBetter Auth issuer base URL

MCP_URL: Installation → Environment variables.

ctx.user includes the same base fields as Supabase (id, email, name) plus picture, emailVerified, sessionId, isAnonymous, and roles.