recommendations-tool.ts•3.55 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { SpotifyClient } from "../../spotify-client.js";
import {
getRecommendations,
getAvailableGenreSeeds,
formatRecommendations,
} from "../recommendations.js";
export function registerRecommendationsTools(server: McpServer, spotifyClient: SpotifyClient) {
// Get Recommendations Tool
server.tool(
"get_recommendations",
"Get track recommendations based on seed tracks, artists, or genres. Can automatically use recent listening history if no seeds provided.",
{
seed_tracks: z
.array(z.string())
.optional()
.describe("Array of Spotify track IDs as seeds"),
seed_artists: z
.array(z.string())
.optional()
.describe("Array of Spotify artist IDs as seeds"),
seed_genres: z
.array(z.string())
.optional()
.describe("Array of genre names as seeds (use get_genre_seeds to see available genres)"),
limit: z
.number()
.optional()
.default(10)
.describe("Maximum number of recommendations (default: 10)"),
target_energy: z
.number()
.min(0)
.max(1)
.optional()
.describe("Target energy level (0.0 to 1.0, where 1.0 is most energetic)"),
target_danceability: z
.number()
.min(0)
.max(1)
.optional()
.describe("Target danceability (0.0 to 1.0, where 1.0 is most danceable)"),
target_valence: z
.number()
.min(0)
.max(1)
.optional()
.describe("Target valence/positivity (0.0 to 1.0, where 1.0 is most positive/happy)"),
use_recent_listening: z
.boolean()
.optional()
.default(false)
.describe("If true and no seeds provided, automatically use recently played tracks as seeds"),
},
async ({
seed_tracks,
seed_artists,
seed_genres,
limit,
target_energy,
target_danceability,
target_valence,
use_recent_listening,
}) => {
try {
const recommendations = await getRecommendations(spotifyClient, {
seed_tracks,
seed_artists,
seed_genres,
limit,
target_energy,
target_danceability,
target_valence,
use_recent_listening,
});
const formatted = formatRecommendations(recommendations);
return {
content: [{ type: "text", text: formatted }],
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
return {
content: [{ type: "text", text: `Error getting recommendations: ${errorMessage}` }],
isError: true,
};
}
}
);
// Get Available Genre Seeds Tool
server.tool(
"get_genre_seeds",
"Get list of available genre seeds for recommendations",
{},
async () => {
try {
const genres = await getAvailableGenreSeeds(spotifyClient);
return {
content: [
{
type: "text",
text: `**Available Genre Seeds:**\n\n${genres.join(", ")}`,
},
],
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
return {
content: [{ type: "text", text: `Error getting genres: ${errorMessage}` }],
isError: true,
};
}
}
);
}