UNPKG

questrade-mcp-server

Version:

MCP server for Questrade API integration

82 lines (70 loc) 2.23 kB
import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; interface TokenData { refreshToken: string; accessToken?: string; apiUrl?: string; lastUpdated: string; } export class TokenManager { private tokenFilePath: string; constructor() { let defaultTokenDir: string; if (process.env.QUESTRADE_TOKEN_DIR) { defaultTokenDir = process.env.QUESTRADE_TOKEN_DIR; } else { try { defaultTokenDir = path.join(os.homedir(), '.questrade-mcp'); } catch { defaultTokenDir = path.join(os.tmpdir(), 'questrade-mcp'); } } this.tokenFilePath = path.join(defaultTokenDir, 'tokens.json'); try { if (!fs.existsSync(defaultTokenDir)) { fs.mkdirSync(defaultTokenDir, { recursive: true }); } } catch { // Directory creation failed - will fall back to environment variables } } async loadTokens(): Promise<{ refreshToken: string; accessToken?: string; apiUrl?: string }> { try { if (fs.existsSync(this.tokenFilePath)) { const tokenData: TokenData = JSON.parse(await fs.promises.readFile(this.tokenFilePath, 'utf8')); return { refreshToken: tokenData.refreshToken, accessToken: tokenData.accessToken, apiUrl: tokenData.apiUrl }; } } catch (error) { // Fall back to environment variables on file read error } return { refreshToken: process.env.QUESTRADE_REFRESH_TOKEN!, accessToken: process.env.QUESTRADE_ACCESS_TOKEN, apiUrl: process.env.QUESTRADE_API_URL }; } async saveTokens(refreshToken: string, accessToken?: string, apiUrl?: string): Promise<void> { try { const tokenData: TokenData = { refreshToken, accessToken, apiUrl, lastUpdated: new Date().toISOString() }; await fs.promises.writeFile(this.tokenFilePath, JSON.stringify(tokenData, null, 2), 'utf8'); } catch (error) { // Token save failed - will continue using environment variables } } getTokenFilePath(): string { return this.tokenFilePath; } async hasTokenFile(): Promise<boolean> { return fs.existsSync(this.tokenFilePath); } }