searchSpotify
Search Spotify music by keywords and filters to find tracks, albums, or playlists matching specific criteria like artist, genre, or release year.
Instructions
Search Spotify by keyword and field filters (e.g. artist, track, playlist, tag:new, tag:hipster) and return items of the given type
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Full Spotify search string combining: - free-text keywords (e.g. “remaster”), - field filters: artist:<name>, track:<name>, album:<name>, year:<YYYY> or <YYYY-YYYY>, genre:<name>. The album, artist and year filters can be used for album and track types. The genre filter can only be used for track type. Special filter tag:hipster (bottom 10% popularity) can be used with track and album types. All separated by spaces. Example: "tag:hipster artist:Queen remaster". | |
| type | Yes | Which item type to return: track, album or playlist | |
| limit | No | Max number of results to return (1-50) | |
| offset | No | The index of the first item to return. Defaults to 0 |
Implementation Reference
- src/read.ts:56-124 (handler)The main handler function that executes the Spotify search. It calls the Spotify API's search method with the provided query, type, limit, and offset. Formats the results into a numbered list depending on the type (track, album, or playlist), including relevant details like artists, duration, and ID. Returns formatted text content or error message.handler: async (args, extra: SpotifyHandlerExtra) => { const { query, type, limit = 20, offset = 0 } = args; try { const results = await handleSpotifyRequest(async (spotifyApi) => { return await spotifyApi.search( query, [type], undefined, limit as MaxInt<50>, offset, ); }); let formattedResults = ''; if (type === 'track' && results.tracks) { formattedResults = results.tracks.items .map((track, i) => { const artists = track.artists.map((a) => a.name).join(', '); const duration = formatDuration(track.duration_ms); return `${i + 1}. "${ track.name }" by ${artists} (${duration}) - ID: ${track.id}`; }) .join('\n'); } else if (type === 'album' && results.albums) { formattedResults = results.albums.items .map((album, i) => { const artists = album.artists.map((a) => a.name).join(', '); return `${i + 1}. "${album.name}" by ${artists} - ID: ${album.id}`; }) .join('\n'); } else if (type === 'playlist' && results.playlists) { formattedResults = results.playlists.items .map((playlist, i) => { return `${i + 1}. "${playlist?.name ?? 'Unknown Playlist'} (${ playlist?.description ?? 'No description' } tracks)" by ${playlist?.owner?.display_name} - ID: ${ playlist?.id }`; }) .join('\n'); } return { content: [ { type: 'text', text: formattedResults.length > 0 ? `# Search results for "${query}" (type: ${type})\n\n${formattedResults}` : `No ${type} results found for "${query}"`, }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error searching for ${type}s: ${ error instanceof Error ? error.message : String(error) }`, }, ], }; } },
- src/read.ts:25-55 (schema)Zod-based input schema defining the parameters for the searchSpotify tool: query (required string with detailed description of search syntax), type (enum: 'track', 'album', 'playlist'), optional limit (1-50), optional offset (0-1000).schema: { query: z .string() .describe( [ 'Full Spotify search string combining:', '- free-text keywords (e.g. “remaster”),', '- field filters: artist:<name>, track:<name>, album:<name>,', ' year:<YYYY> or <YYYY-YYYY>, genre:<name>.', 'The album, artist and year filters can be used for album and track types.', 'The genre filter can only be used for track type.', 'Special filter tag:hipster (bottom 10% popularity) can be used with track and album types.', 'All separated by spaces. Example: "tag:hipster artist:Queen remaster".', ].join(' '), ), type: z .enum(['track', 'album', 'playlist']) .describe('Which item type to return: track, album or playlist'), limit: z .number() .min(1) .max(50) .optional() .describe('Max number of results to return (1-50)'), offset: z .number() .min(0) .max(1000) .optional() .describe('The index of the first item to return. Defaults to 0'), },
- src/read.ts:521-529 (registration)The searchSpotify tool is included in the readTools array, which collects all read-related tools for export.export const readTools = [ searchSpotify, getNowPlaying, getUserPlaylists, getPlaylistTracks, getRecentlyPlayed, getFollowedArtists, getUserTopItems, ];
- src/index.ts:12-14 (registration)All tools from readTools, playTools, and writeTools (including searchSpotify) are registered with the MCP server by calling server.tool() for each tool, passing name, description, schema, and handler.[...playTools, ...readTools, ...writeTools].forEach((tool) => { server.tool(tool.name, tool.description, tool.schema, tool.handler); });