nextmcp-client-auth
v0.1.0
Published
Host-side OAuth client library for NextMCP - the authentication helper that makes MCP OAuth integration trivial
Maintainers
Readme
nextmcp-client-auth
The OAuth client library for MCP hosts - "Passport.js for the MCP ecosystem"
A host-side helper library that makes OAuth authentication with NextMCP servers trivial. This is the missing piece that lets hosts like Claude Desktop, Cursor, Windsurf, and others integrate authentication without writing a single line of OAuth code.
Why This Library Exists
MCP hosts don't want to learn your auth system. They want a tiny helper they can import that "just works".
This library provides exactly one function call to handle:
- ✓ Reading server auth metadata
- ✓ PKCE OAuth flow
- ✓ Redirect/callback handling
- ✓ Token storage
- ✓ Automatic token refresh
- ✓ Auth header injection
Think of it as: "One function call = authenticated MCP connection"
Installation
npm install nextmcp-client-authQuick Start
Node.js (with automatic loopback server)
import { connectWithNextMCPAuth } from "nextmcp-client-auth";
const connection = await connectWithNextMCPAuth({
serverUrl: "http://localhost:8000",
onAuthStart(url) {
console.log("Please visit:", url);
// Opens browser automatically in most terminals
},
});
// Use the authenticated connection
const response = await connection.transport.send({
method: "tools/list",
});
console.log("Tools:", response.result);Browser
import { connectWithNextMCPAuth } from "nextmcp-client-auth";
const connection = await connectWithNextMCPAuth({
serverUrl: "https://api.example.com",
onAuthStart(authUrl) {
// Redirect user to auth URL
window.location.href = authUrl;
},
});
// Make authenticated requests
const response = await connection.transport.send({
method: "tools/list",
});That's it. Zero OAuth code needed.
Features
🔐 Complete OAuth 2.0 Support
- PKCE Flow - Secure for public clients (browser, mobile, desktop)
- GitHub & Google - Works with standard OAuth providers
- Automatic Discovery - Fetches auth metadata from server
- State Validation - CSRF protection built-in
💾 Smart Token Management
- Automatic Storage - localStorage (browser) or
~/.nextmcp/(Node.js) - Auto-Refresh - Tokens refreshed transparently before expiration
- Multi-Server - Different tokens for different servers
🚀 Developer Experience
- TypeScript - Full type safety
- Cross-Platform - Works in browser, Node.js, Electron
- Debug Mode - Set
NEXTMCP_AUTH_DEBUG=1for detailed logs - Zero Dependencies - Uses built-in Web Crypto API
🎯 Production Ready
- Error Handling - Clear error types for all failure modes
- Timeout Protection - Configurable timeouts for auth flow
- Thread Safe - Handles concurrent token refreshes
- Memory Safe - No token leaks in logs
API Reference
connectWithNextMCPAuth(config)
The main function to establish an authenticated MCP connection.
Parameters:
interface ConnectConfig {
serverUrl: string; // MCP server URL
onAuthStart?: (authUrl: string) => void; // Called when auth flow starts
redirectUri?: string; // Custom redirect (optional)
tokenStore?: TokenStore; // Custom token storage (optional)
debug?: boolean; // Enable debug logs
loopbackPort?: number; // Port for callback server (Node.js)
}Returns:
interface AuthenticatedConnection {
transport: MCPTransport; // Use this to send MCP requests
tokens: OAuthTokens; // Current access/refresh tokens
metadata: AuthMetadata; // Server's auth requirements
disconnect(): Promise<void>; // Clean up and remove tokens
}Example:
const connection = await connectWithNextMCPAuth({
serverUrl: "http://localhost:8000",
debug: true,
onAuthStart(url) {
console.log("Auth URL:", url);
},
});
// Make authenticated requests
await connection.transport.send({ method: "tools/list" });
// Disconnect when done
await connection.disconnect();Token Storage
By default, tokens are stored in:
- Browser:
localStorage - Node.js:
~/.nextmcp/sessions/{host}.json
You can provide a custom store:
import { TokenStore, OAuthTokens } from "nextmcp-client-auth";
class CustomTokenStore implements TokenStore {
async saveTokens(serverUrl: string, tokens: OAuthTokens): Promise<void> {
// Your storage logic
}
async getTokens(serverUrl: string): Promise<OAuthTokens | null> {
// Your retrieval logic
}
async deleteTokens(serverUrl: string): Promise<void> {
// Your deletion logic
}
async clear(): Promise<void> {
// Clear all tokens
}
}
const connection = await connectWithNextMCPAuth({
serverUrl: "http://localhost:8000",
tokenStore: new CustomTokenStore(),
});Error Handling
The library throws specific error types:
import {
OAuthError,
PKCEError,
TokenRefreshError,
CallbackTimeoutError,
AuthMetadataError,
} from "nextmcp-client-auth";
try {
const connection = await connectWithNextMCPAuth({
serverUrl: "http://localhost:8000",
});
} catch (error) {
if (error instanceof OAuthError) {
console.error("OAuth failed:", error.message, error.code);
} else if (error instanceof CallbackTimeoutError) {
console.error("User didn't complete auth in time");
} else if (error instanceof AuthMetadataError) {
console.error("Server doesn't support OAuth");
}
}Advanced Usage
Custom Redirect URI
const connection = await connectWithNextMCPAuth({
serverUrl: "http://localhost:8000",
redirectUri: "http://localhost:3000/oauth/callback",
onAuthStart(authUrl) {
// Your app should handle the callback at /oauth/callback
window.location.href = authUrl;
},
});Manual Token Refresh
import { refreshAccessToken } from "nextmcp-client-auth";
const newTokens = await refreshAccessToken({
provider: metadata.providers[0],
refreshToken: currentTokens.refresh_token,
});PKCE Challenge Generation
import { generateVerifier, generatePKCE } from "nextmcp-client-auth";
const verifier = generateVerifier();
const pkce = await generatePKCE(verifier);
console.log("Challenge:", pkce.challenge);
console.log("Verifier:", pkce.verifier);How It Works
┌─────────────┐
│ Host App │
│ (Cursor,etc)│
└──────┬──────┘
│
│ 1. connectWithNextMCPAuth()
▼
┌─────────────────────────────────────────────────┐
│ nextmcp-client-auth Library │
│ │
│ 2. Fetch /.well-known/mcp-auth │
│ 3. Generate PKCE challenge │
│ 4. Open auth URL │
│ 5. Listen for callback │
│ 6. Exchange code → tokens │
│ 7. Store tokens │
│ 8. Return authenticated transport │
└──────┬──────────────────────────────────────────┘
│
│ 9. transport.send() + auto refresh
▼
┌─────────────┐
│ NextMCP │
│ Server │
└─────────────┘Examples
See the examples/ directory for complete examples:
- Node.js with loopback -
examples/node/simple.ts - Custom redirect URI -
examples/node/custom-redirect.ts - Browser -
examples/browser/index.html
Requirements
- Node.js 18+ or modern browser with Web Crypto API
- A NextMCP server with OAuth authentication configured
Development
# Install dependencies
npm install
# Build
npm run build
# Run tests
npm test
# Run examples
cd examples/node
npm install
npm run simpleFAQ
Q: Do I need to understand OAuth?
A: No. That's the point of this library. Just call connectWithNextMCPAuth().
Q: Does this work with all OAuth providers?
A: Yes, any OAuth 2.0 provider that the NextMCP server supports (GitHub, Google, etc.)
Q: What about security?
A: The library uses PKCE (Proof Key for Code Exchange), which is the recommended flow for public clients. Tokens are stored securely (httpOnly cookies recommended for browser production use).
Q: Can I use this in Electron?
A: Yes! It works in both the main and renderer process.
Q: How do I handle logout?
A: Call await connection.disconnect() to remove tokens and close the connection.
Q: Does this support DPoP?
A: Not yet, but it's on the roadmap.
Contributing
Contributions welcome! Please see CONTRIBUTING.md.
License
MIT © NextMCP Contributors
Related Projects
- NextMCP - The production-grade MCP server SDK this library is designed for
- Model Context Protocol - The protocol specification
Made with ❤️ for the MCP ecosystem
