Skip to main content
Glama
client.ts3.71 kB
import { type OAuthHelpers, type AuthRequest, } from '@cloudflare/workers-oauth-provider' import { createSchwabAuth as SchwabAuthCreatorFromLibrary, AuthStrategy, type TokenData, type EnhancedTokenManager, type EnhancedTokenManagerOptions, encodeOAuthState, } from '@sudowealth/schwab-api' import { type Context } from 'hono' import { type BlankInput } from 'hono/types' import { type ValidatedEnv, type Env } from '../../types/env' import { LOGGER_CONTEXTS } from '../shared/constants' import { logger } from '../shared/log' import { AuthErrors, formatAuthError } from './errors' import { mapTokenPersistence } from './tokenPersistence' // Create scoped logger for auth client const authLogger = logger.child(LOGGER_CONTEXTS.AUTH_CLIENT) /** * Creates a Schwab Auth client with enhanced features * * @param redirectUri OAuth callback URI * @param load Function to load tokens from storage * @param save Function to save tokens to storage * @returns Initialized Schwab auth client as EnhancedTokenManager */ export function initializeSchwabAuthClient( config: ValidatedEnv, redirectUri = config.SCHWAB_REDIRECT_URI, load?: () => Promise<TokenData | null>, save?: (tokenData: TokenData) => Promise<void>, ): EnhancedTokenManager { const clientId = config.SCHWAB_CLIENT_ID const clientSecret = config.SCHWAB_CLIENT_SECRET authLogger.debug('Using centralized environment for Schwab Auth client') authLogger.info('Initializing enhanced Schwab Auth client', { hasLoadFunction: !!load, hasSaveFunction: !!save, }) // Map our load/save functions to what EnhancedTokenManager expects const { load: mappedLoad, save: mappedSave } = mapTokenPersistence(load, save) // Build options for EnhancedTokenManager with MCP-specific defaults const tokenManagerOptions: EnhancedTokenManagerOptions = { clientId, clientSecret, redirectUri, load: mappedLoad, save: mappedSave, validateTokens: true, autoReconnect: true, debug: config.LOG_LEVEL === 'debug' || config.LOG_LEVEL === 'trace', traceOperations: config.LOG_LEVEL === 'trace', refreshThresholdMs: 5 * 60 * 1000, } // Configure auth with enhanced token manager const authConfig = { strategy: AuthStrategy.ENHANCED, oauthConfig: tokenManagerOptions, } const authClient = SchwabAuthCreatorFromLibrary(authConfig) return authClient } /** * Redirects the user to Schwab's authorization page * * @param c Hono context * @param config Validated environment configuration * @param oauthReqInfo OAuth request information * @param headers Optional headers to include in the response * @returns Redirect response to Schwab's authorization page */ export async function redirectToSchwab( c: Context< { Bindings: Env & { OAUTH_PROVIDER: OAuthHelpers } }, '/authorize', BlankInput >, config: ValidatedEnv, oauthReqInfo: AuthRequest, headers: HeadersInit = {}, ): Promise<Response> { try { const auth = initializeSchwabAuthClient(config) // Use SDK's OAuth state encoder const encodedState = encodeOAuthState(oauthReqInfo) const { authUrl } = await auth.getAuthorizationUrl({ state: encodedState, }) // Create redirect response with any additional headers if (Object.keys(headers).length > 0) { return new Response(null, { status: 302, headers: { Location: authUrl, ...headers, }, }) } else { return Response.redirect(authUrl, 302) } } catch (error) { const authError = new AuthErrors.AuthUrl( error instanceof Error ? error : undefined, ) const errorInfo = formatAuthError(authError, { error }) authLogger.error(errorInfo.message, { error }) return new Response(errorInfo.message, { status: errorInfo.status }) } }

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/sudowealth/schwab-mcp'

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