Skip to main content
Glama
igorgarbuz
by igorgarbuz
player.ts3.57 kB
import { handleSpotifyRequest } from './utils.js'; import { z } from 'zod'; import type { SpotifyHandlerExtra, tool } from './types.js'; const playMusic: tool<{ uri: z.ZodOptional<z.ZodString>; type: z.ZodOptional<z.ZodEnum<['track', 'album', 'artist', 'playlist']>>; id: z.ZodOptional<z.ZodString>; deviceId: z.ZodOptional<z.ZodString>; }> = { name: 'playMusic', description: 'Start playing a Spotify track, album, artist, or playlist', schema: { uri: z .string() .optional() .describe('The Spotify URI to play (overrides type and id)'), type: z .enum(['track', 'album', 'artist', 'playlist']) .optional() .describe('The type of item to play'), id: z.string().optional().describe('The Spotify ID of the item to play'), deviceId: z .string() .optional() .describe('The Spotify device ID to play on'), }, handler: async (args, extra: SpotifyHandlerExtra) => { const { uri, type, id, deviceId } = args; if (!uri && (!type || !id)) { return { content: [ { type: 'text', text: 'Error: Must provide either a URI or both a type and ID', isError: true, }, ], }; } let spotifyUri = uri; if (!spotifyUri && type && id) { spotifyUri = `spotify:${type}:${id}`; } await handleSpotifyRequest(async (spotifyApi) => { const device = deviceId || ''; if (!spotifyUri) { await spotifyApi.player.startResumePlayback(device); return; } if (type === 'track') { await spotifyApi.player.startResumePlayback(device, undefined, [ spotifyUri, ]); } else { await spotifyApi.player.startResumePlayback(device, spotifyUri); } }); return { content: [ { type: 'text', text: `Started playing ${type || 'music'} ${id ? `(ID: ${id})` : ''}`, }, ], }; }, }; const playbackAction: tool<{ action: z.ZodEnum<['pause', 'skipToNext', 'skipToPrevious', 'resume']>; deviceId: z.ZodOptional<z.ZodString>; }> = { name: 'playbackAction', description: 'Perform a playback action (pause, resume, skip to next, skip to previous)', schema: { action: z .enum(['pause', 'skipToNext', 'skipToPrevious', 'resume']) .describe('The playback action to perform'), deviceId: z .string() .optional() .describe('The Spotify device ID to perform the action on'), }, handler: async (args, extra: SpotifyHandlerExtra) => { const { action, deviceId } = args; let successMessage = ''; await handleSpotifyRequest(async (spotifyApi) => { const device = deviceId || ''; switch (action) { case 'pause': await spotifyApi.player.pausePlayback(device); successMessage = 'Playback paused'; break; case 'resume': await spotifyApi.player.startResumePlayback(device); successMessage = 'Playback resumed'; break; case 'skipToNext': await spotifyApi.player.skipToNext(device); successMessage = 'Skipped to next track'; break; case 'skipToPrevious': await spotifyApi.player.skipToPrevious(device); successMessage = 'Skipped to previous track'; break; } }); return { content: [ { type: 'text', text: successMessage, }, ], }; }, }; export const playTools = [playMusic, playbackAction];

Implementation Reference

Latest Blog Posts

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/igorgarbuz/spotify-mcp'

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