Skip to main content
Glama

OpenAPI MCP Server

auth-provider-guide.md6.86 kB
# AuthProvider Usage Guide The `@ivotoby/openapi-mcp-server` now supports dynamic authentication through the `AuthProvider` interface. This is particularly useful for APIs that require token refresh or have authentication tokens that expire. ## Basic Usage ### Static Authentication (Backward Compatible) ```typescript import { OpenAPIServer } from '@ivotoby/openapi-mcp-server' const config = { name: 'my-api-server', version: '1.0.0', apiBaseUrl: 'https://api.example.com', openApiSpec: './api-spec.yaml', specInputMethod: 'file', headers: { 'Authorization': 'Bearer your-static-token', 'X-API-Key': 'your-api-key' }, transportType: 'stdio', toolsMode: 'all' } const server = new OpenAPIServer(config) ``` ### Dynamic Authentication with AuthProvider ```typescript import { OpenAPIServer, AuthProvider } from '@ivotoby/openapi-mcp-server' import { AxiosError } from 'axios' class MyAuthProvider implements AuthProvider { private accessToken: string | null = null private tokenExpiry: Date | null = null async getAuthHeaders(): Promise<Record<string, string>> { // Check if token is still valid if (!this.accessToken || this.isTokenExpired()) { throw new Error('Token expired. Please provide a new token.') } return { 'Authorization': `Bearer ${this.accessToken}`, 'X-Client-Version': '1.0.0' } } async handleAuthError(error: AxiosError): Promise<boolean> { // Check if this is an authentication error if (error.response?.status === 401 || error.response?.status === 403) { // Try to refresh the token (if you have refresh logic) try { await this.refreshToken() return true // Retry the request } catch (refreshError) { // If refresh fails, ask user for new token throw new Error('Authentication failed. Please provide a new access token.') } } // Not an auth error, don't retry return false } setToken(token: string, expiresIn: number = 3600) { this.accessToken = token this.tokenExpiry = new Date(Date.now() + expiresIn * 1000) } private isTokenExpired(): boolean { return !this.tokenExpiry || this.tokenExpiry <= new Date() } private async refreshToken(): Promise<void> { // Implement your token refresh logic here // This might involve calling a refresh endpoint throw new Error('Token refresh not implemented') } } // Usage const authProvider = new MyAuthProvider() authProvider.setToken('your-initial-token', 3600) const config = { name: 'my-api-server', version: '1.0.0', apiBaseUrl: 'https://api.example.com', openApiSpec: './api-spec.yaml', specInputMethod: 'file', authProvider: authProvider, // Use AuthProvider instead of headers transportType: 'stdio', toolsMode: 'all' } const server = new OpenAPIServer(config) ``` ## AuthProvider Interface ```typescript interface AuthProvider { /** * Get authentication headers for the current request * This method is called before each API request to get fresh headers * * @returns Promise that resolves to headers object * @throws Error if authentication is not available (e.g., token expired) */ getAuthHeaders(): Promise<Record<string, string>> /** * Handle authentication errors from API responses * This is called when the API returns authentication-related errors (401, 403) * * @param error - The axios error from the failed request * @returns Promise that resolves to true if the request should be retried, false otherwise */ handleAuthError(error: AxiosError): Promise<boolean> } ``` ## Key Features ### 1. Dynamic Headers per Request Unlike static headers that are set once, `getAuthHeaders()` is called before each API request, allowing for: - Token refresh - Dynamic header generation - Token validation before requests ### 2. Authentication Error Handling When the API returns 401 or 403 errors, `handleAuthError()` is called, allowing you to: - Attempt token refresh - Prompt users for new credentials - Decide whether to retry the request ### 3. Automatic Retry Logic If `handleAuthError()` returns `true`, the request is automatically retried with fresh headers from `getAuthHeaders()`. The retry only happens once to prevent infinite loops. ### 4. Backward Compatibility Existing code using static headers continues to work unchanged. The system internally creates a `StaticAuthProvider` when headers are provided without an `AuthProvider`. ## Example: Manual Token Updates For APIs like Beatport where automatic refresh isn't possible, you can create an AuthProvider that prompts for new tokens: ```typescript class ManualTokenAuthProvider implements AuthProvider { private token: string | null = null private tokenExpiry: Date | null = null async getAuthHeaders(): Promise<Record<string, string>> { if (!this.token || this.isTokenExpired()) { throw new Error( 'Token expired. Please get a new token from your browser and update it using the updateToken command.' ) } return { 'Authorization': `Bearer ${this.token}` } } async handleAuthError(error: AxiosError): Promise<boolean> { // For manual token management, we can't auto-retry // Throw a helpful error message instead throw new Error( 'Authentication failed. Please get a new access token from your browser:\\n' + '1. Go to https://api.example.com\\n' + '2. Open browser dev tools\\n' + '3. Copy the Authorization header\\n' + '4. Use the updateToken command to set the new token' ) } updateToken(token: string, expiresIn: number = 3600): void { this.token = token this.tokenExpiry = new Date(Date.now() + expiresIn * 1000) console.log('✅ Token updated successfully') } private isTokenExpired(): boolean { if (!this.tokenExpiry) return true return this.tokenExpiry <= new Date(Date.now() + 60000) // 1 minute buffer } } ``` ## Error Handling Best Practices 1. **Clear Error Messages**: Provide actionable error messages that tell users exactly what to do 2. **Graceful Degradation**: Don't crash the server when tokens expire 3. **User Guidance**: Include step-by-step instructions for token renewal 4. **Retry Logic**: Only retry when it makes sense (e.g., after successful token refresh) ## Migration from Static Headers To migrate existing code: **Before:** ```typescript const config = { // ... other config headers: { 'Authorization': 'Bearer token' } } ``` **After:** ```typescript const authProvider = new MyAuthProvider() authProvider.setToken('token') const config = { // ... other config authProvider: authProvider // Remove the headers property } ``` The AuthProvider approach provides much more flexibility and better error handling for modern APIs with dynamic authentication requirements.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ivo-toby/mcp-openapi-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server