OAuth Adapters
Configure token storage with memory, file, or cloud adapters.
OAuth Adapters
OAuth adapters handle storage and retrieval of OAuth tokens for upstream MCP servers that require authentication (e.g., GitHub, Gmail, Slack).
Available Adapters
| Adapter | Use Case | Persistence | Multi-Process |
|---|---|---|---|
memoryAdapter | Testing, short-lived processes | No | No |
fileAdapter | CLI tools, local development | Yes | Limited |
cloudAdapter | Production, multi-instance | Yes | Yes |
Memory Adapter
Stores tokens in memory. Tokens are lost when the process exits.
import { RouterMCPClient } from '@routermcp/sdk';
import { memoryAdapter } from '@routermcp/sdk/oauth';
const client = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
oauth: {
adapter: memoryAdapter(),
},
});Only use the memory adapter for testing or short-lived processes. Tokens will be lost on restart.
File Adapter
Stores tokens as JSON files on disk. Compatible with the RouterMCP CLI's token storage.
import { RouterMCPClient } from '@routermcp/sdk';
import { fileAdapter } from '@routermcp/sdk/oauth';
// Default: ~/.routermcp/mcp-oauth/
const client = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
oauth: {
adapter: fileAdapter(),
},
});
// Custom path
const client2 = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
oauth: {
adapter: fileAdapter('/path/to/tokens'),
},
});File Structure
Tokens are stored as:
~/.routermcp/mcp-oauth/
{userId}/
{serverId}.jsonThe file adapter is compatible with the RouterMCP CLI. Tokens authorized via the CLI will be available to the SDK and vice versa.
Cloud Adapter
Stores tokens in RouterMCP Cloud via API. Ideal for production deployments with multiple instances.
import { RouterMCPClient } from '@routermcp/sdk';
import { cloudAdapter } from '@routermcp/sdk/oauth';
const client = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
oauth: {
adapter: cloudAdapter({
apiKey: 'rmc_...', // Your RouterMCP API key
}),
},
});
// Custom API endpoint
const client2 = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
oauth: {
adapter: cloudAdapter({
apiKey: 'rmc_...',
baseUrl: 'https://custom.routermcp.com',
}),
},
});Multi-User OAuth
For applications serving multiple users, each user needs their own OAuth tokens:
import { RouterMCPClient } from '@routermcp/sdk';
import { cloudAdapter } from '@routermcp/sdk/oauth';
const client = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
userId: 'default-user',
oauth: {
adapter: cloudAdapter({ apiKey: 'rmc_...' }),
autoRefresh: true,
},
});
await client.connect();
// Create sessions for different users
async function handleUserRequest(userId: string, toolName: string, args: object) {
const session = client.createSession({ userId });
await session.connect();
try {
const result = await session.callTool(toolName, args);
return result;
} finally {
await session.disconnect();
}
}
// Each user's OAuth tokens are stored separately
await handleUserRequest('user-1', 'gmail_send', { to: 'a@test.com', body: 'Hi' });
await handleUserRequest('user-2', 'slack_post', { channel: '#general', text: 'Hello' });OAuth Flow
When a tool requires OAuth and no valid token exists:
- The tool call returns an OAuth authorization URL
- Your application redirects the user to this URL
- User authorizes the application
- RouterMCP stores the tokens via your configured adapter
- Subsequent tool calls use the stored tokens
try {
const result = await client.callTool('gmail_send', { to: 'test@example.com' });
} catch (error) {
if (error instanceof OAuthError && error.authorizationUrl) {
// Redirect user to error.authorizationUrl
console.log('Please authorize:', error.authorizationUrl);
}
}Custom Adapters
Implement the OAuthAdapter interface for custom storage:
interface OAuthAdapter {
getTokens(userId: string, serverId: string): Promise<OAuthTokens | null>;
setTokens(userId: string, serverId: string, tokens: OAuthTokens): Promise<void>;
deleteTokens(userId: string, serverId: string): Promise<void>;
}
interface OAuthTokens {
accessToken: string;
refreshToken?: string;
expiresAt?: number;
tokenType: string;
}Example with Redis:
import { createClient } from 'redis';
function redisAdapter(redisUrl: string): OAuthAdapter {
const client = createClient({ url: redisUrl });
return {
async getTokens(userId, serverId) {
const key = `oauth:${userId}:${serverId}`;
const data = await client.get(key);
return data ? JSON.parse(data) : null;
},
async setTokens(userId, serverId, tokens) {
const key = `oauth:${userId}:${serverId}`;
await client.set(key, JSON.stringify(tokens));
},
async deleteTokens(userId, serverId) {
const key = `oauth:${userId}:${serverId}`;
await client.del(key);
},
};
}
const client = new RouterMCPClient({
url: 'https://gateway.routermcp.com/v1/mcp/my-project',
oauth: {
adapter: redisAdapter('redis://localhost:6379'),
},
});