Skip to main content
Glama

MCP Spotify Server

by fborello
spotify-auth.ts5.01 kB
import SpotifyWebApi from 'spotify-web-api-node'; import { SpotifyConfig, SpotifyTokens } from '../types/index.js'; import fs from 'fs'; import path from 'path'; export class SpotifyAuth { private spotifyApi: any; private tokens: SpotifyTokens | null = null; private tokensFile: string; constructor(config: SpotifyConfig) { this.spotifyApi = new SpotifyWebApi({ clientId: config.clientId, clientSecret: config.clientSecret, redirectUri: config.redirectUri, }); this.tokensFile = path.join(process.cwd(), 'spotify-tokens.json'); this.loadTokens(); } /** * Gera URL de autorização para o usuário fazer login */ getAuthorizationUrl(): string { const scopes = [ 'user-read-private', 'user-read-email', 'user-read-playback-state', 'user-modify-playback-state', 'user-read-currently-playing', 'playlist-read-private', 'playlist-read-collaborative', 'playlist-modify-public', 'playlist-modify-private', 'user-library-read', 'user-library-modify', 'user-top-read', 'user-read-recently-played' ]; return this.spotifyApi.createAuthorizeURL(scopes, 'state'); } /** * Troca o código de autorização por tokens de acesso */ async exchangeCodeForTokens(code: string): Promise<SpotifyTokens> { try { const data = await this.spotifyApi.authorizationCodeGrant(code); const { access_token, refresh_token, expires_in } = data.body; this.tokens = { accessToken: access_token, refreshToken: refresh_token, expiresAt: Date.now() + (expires_in * 1000) }; this.spotifyApi.setAccessToken(access_token); this.spotifyApi.setRefreshToken(refresh_token); this.saveTokens(); return this.tokens; } catch (error) { throw new Error(`Erro ao trocar código por tokens: ${error}`); } } /** * Verifica se o token está expirado e renova se necessário */ async ensureValidToken(): Promise<string> { if (!this.tokens) { throw new Error('Usuário não autenticado'); } if (Date.now() >= this.tokens.expiresAt) { await this.refreshAccessToken(); } return this.tokens.accessToken; } /** * Renova o token de acesso usando o refresh token */ private async refreshAccessToken(): Promise<void> { if (!this.tokens?.refreshToken) { throw new Error('Refresh token não disponível'); } try { const data = await this.spotifyApi.refreshAccessToken(); const { access_token, expires_in } = data.body; this.tokens.accessToken = access_token; this.tokens.expiresAt = Date.now() + (expires_in * 1000); this.spotifyApi.setAccessToken(access_token); this.saveTokens(); } catch (error) { throw new Error(`Erro ao renovar token: ${error}`); } } /** * Define tokens existentes (útil para persistir sessão) */ setTokens(tokens: SpotifyTokens): void { this.tokens = tokens; this.spotifyApi.setAccessToken(tokens.accessToken); this.spotifyApi.setRefreshToken(tokens.refreshToken); } /** * Retorna a instância do SpotifyWebApi configurada */ getSpotifyApi(): any { return this.spotifyApi; } /** * Verifica se o usuário está autenticado */ isAuthenticated(): boolean { return this.tokens !== null; } /** * Limpa os tokens (logout) */ logout(): void { this.tokens = null; this.spotifyApi.setAccessToken(''); this.spotifyApi.setRefreshToken(''); this.saveTokens(); } /** * Salva os tokens em arquivo */ private saveTokens(): void { try { if (this.tokens) { fs.writeFileSync(this.tokensFile, JSON.stringify(this.tokens, null, 2)); } else { if (fs.existsSync(this.tokensFile)) { fs.unlinkSync(this.tokensFile); } } } catch (error) { console.error('Erro ao salvar tokens:', error); } } /** * Carrega os tokens do arquivo */ private loadTokens(): void { try { if (fs.existsSync(this.tokensFile)) { const data = fs.readFileSync(this.tokensFile, 'utf8'); const tokens = JSON.parse(data) as SpotifyTokens; // Verifica se o token não expirou if (tokens.expiresAt > Date.now()) { this.tokens = tokens; this.spotifyApi.setAccessToken(tokens.accessToken); this.spotifyApi.setRefreshToken(tokens.refreshToken); } else { // Token expirado, tenta renovar this.tokens = tokens; this.spotifyApi.setRefreshToken(tokens.refreshToken); this.refreshAccessToken().catch(() => { // Se não conseguir renovar, limpa os tokens this.tokens = null; this.spotifyApi.setAccessToken(''); this.spotifyApi.setRefreshToken(''); }); } } } catch (error) { console.error('Erro ao carregar tokens:', error); } } }

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/fborello/MCPSpotify'

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