Skip to main content
Glama

MCP Spotify Server

by fborello
index.ts9.3 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { SpotifyAuth } from './auth/spotify-auth.js'; import { SpotifyTools } from './tools/spotify-tools.js'; import { SpotifyConfig } from './types/index.js'; import dotenv from 'dotenv'; import open from 'open'; // Carregar variáveis de ambiente dotenv.config(); const config: SpotifyConfig = { clientId: process.env.SPOTIFY_CLIENT_ID || '', clientSecret: process.env.SPOTIFY_CLIENT_SECRET || '', redirectUri: process.env.SPOTIFY_REDIRECT_URI || 'http://localhost:3000/callback', }; if (!config.clientId || !config.clientSecret) { console.error('❌ SPOTIFY_CLIENT_ID e SPOTIFY_CLIENT_SECRET são obrigatórios'); console.error('Crie um arquivo .env baseado no env.example'); process.exit(1); } const spotifyAuth = new SpotifyAuth(config); const spotifyTools = new SpotifyTools(spotifyAuth); // Criar servidor MCP (SDK recente usa um único objeto de config) const server = new Server({ name: 'spotify-mcp-server', version: '1.0.0', capabilities: { tools: {}, }, }); // Listar ferramentas disponíveis server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'spotify_auth', description: 'Inicia o processo de autenticação com o Spotify', inputSchema: { type: 'object', properties: {}, }, }, { name: 'spotify_set_tokens', description: 'Conclui a autenticação com o código recebido do Spotify', inputSchema: { type: 'object', properties: { code: { type: 'string', description: 'Código de autorização retornado pelo Spotify após login', }, }, required: ['code'], }, }, { name: 'spotify_search', description: 'Busca por músicas, artistas, álbuns ou playlists no Spotify', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Termo de busca (nome da música, artista, etc.)', }, type: { type: 'string', enum: ['track', 'artist', 'album', 'playlist'], description: 'Tipo de conteúdo para buscar', }, limit: { type: 'number', description: 'Número máximo de resultados (padrão: 20)', }, }, required: ['query', 'type'], }, }, { name: 'spotify_play', description: 'Toca uma música específica no Spotify', inputSchema: { type: 'object', properties: { track_id: { type: 'string', description: 'ID da música no Spotify', }, device_id: { type: 'string', description: 'ID do dispositivo (opcional)', }, }, required: ['track_id'], }, }, { name: 'spotify_pause', description: 'Pausa a reprodução atual', inputSchema: { type: 'object', properties: { device_id: { type: 'string', description: 'ID do dispositivo (opcional)', }, }, }, }, { name: 'spotify_resume', description: 'Retoma a reprodução pausada', inputSchema: { type: 'object', properties: { device_id: { type: 'string', description: 'ID do dispositivo (opcional)', }, }, }, }, { name: 'spotify_next', description: 'Pula para a próxima música', inputSchema: { type: 'object', properties: { device_id: { type: 'string', description: 'ID do dispositivo (opcional)', }, }, }, }, { name: 'spotify_previous', description: 'Volta para a música anterior', inputSchema: { type: 'object', properties: { device_id: { type: 'string', description: 'ID do dispositivo (opcional)', }, }, }, }, { name: 'spotify_current_playing', description: 'Obtém informações sobre a música que está tocando', inputSchema: { type: 'object', properties: {}, }, }, { name: 'spotify_devices', description: 'Lista dispositivos disponíveis para reprodução', inputSchema: { type: 'object', properties: {}, }, }, { name: 'spotify_playlists', description: 'Lista playlists do usuário', inputSchema: { type: 'object', properties: { limit: { type: 'number', description: 'Número máximo de playlists (padrão: 20)', }, }, }, }, { name: 'spotify_play_playlist', description: 'Toca uma playlist específica', inputSchema: { type: 'object', properties: { playlist_id: { type: 'string', description: 'ID da playlist no Spotify', }, device_id: { type: 'string', description: 'ID do dispositivo (opcional)', }, }, required: ['playlist_id'], }, }, { name: 'spotify_create_playlist', description: 'Cria uma nova playlist no Spotify', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Nome da playlist', }, description: { type: 'string', description: 'Descrição da playlist (opcional)', }, public: { type: 'boolean', description: 'Se a playlist deve ser pública (padrão: false)', }, }, required: ['name'], }, }, { name: 'spotify_add_tracks_to_playlist', description: 'Adiciona músicas a uma playlist existente', inputSchema: { type: 'object', properties: { playlist_id: { type: 'string', description: 'ID da playlist no Spotify', }, track_ids: { type: 'array', items: { type: 'string', }, description: 'Array com os IDs das músicas para adicionar', }, }, required: ['playlist_id', 'track_ids'], }, }, ], }; }); // Processar chamadas de ferramentas server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name } = request.params; const args: any = (request.params.arguments ?? {}); try { switch (name) { case 'spotify_auth': return await spotifyTools.authenticate(); case 'spotify_set_tokens': return await spotifyTools.setTokens(args.code); case 'spotify_search': return await spotifyTools.search(args.query, args.type, args.limit); case 'spotify_play': return await spotifyTools.play(args.track_id, args.device_id); case 'spotify_pause': return await spotifyTools.pause(args.device_id); case 'spotify_resume': return await spotifyTools.resume(args.device_id); case 'spotify_next': return await spotifyTools.next(args.device_id); case 'spotify_previous': return await spotifyTools.previous(args.device_id); case 'spotify_current_playing': return await spotifyTools.getCurrentPlaying(); case 'spotify_devices': return await spotifyTools.getDevices(); case 'spotify_playlists': return await spotifyTools.getPlaylists(args.limit); case 'spotify_play_playlist': return await spotifyTools.playPlaylist(args.playlist_id, args.device_id); case 'spotify_create_playlist': return await spotifyTools.createPlaylist(args.name, args.description, args.public); case 'spotify_add_tracks_to_playlist': return await spotifyTools.addTracksToPlaylist(args.playlist_id, args.track_ids); default: throw new Error(`Ferramenta desconhecida: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `Erro ao executar ${name}: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }); // Iniciar servidor async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('🎵 Servidor MCP Spotify iniciado!'); } main().catch((error) => { console.error('Erro fatal:', error); process.exit(1); });

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