Skip to main content
Glama

Claude Music MCP

by leehave
index.ts9.76 kB
import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from '@modelcontextprotocol/sdk/types.js'; import { z } from 'zod'; import { MusicDatabase } from './music-database.js'; import { PlaylistManager } from './playlist-manager.js'; class MusicMCPServer { private server: Server; private musicDb: MusicDatabase; private playlistManager: PlaylistManager; constructor() { this.server = new Server( { name: 'music-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.musicDb = new MusicDatabase(); this.playlistManager = new PlaylistManager(); this.setupToolHandlers(); } private setupToolHandlers() { // 列出所有可用工具 this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'search_music', description: '搜索音乐,支持按歌曲名、艺术家、专辑搜索', inputSchema: { type: 'object', properties: { query: { type: 'string', description: '搜索关键词', }, type: { type: 'string', enum: ['song', 'artist', 'album', 'all'], description: '搜索类型', default: 'all', }, limit: { type: 'number', description: '返回结果数量限制', default: 10, }, }, required: ['query'], }, }, { name: 'get_song_info', description: '获取歌曲详细信息', inputSchema: { type: 'object', properties: { songId: { type: 'string', description: '歌曲ID', }, }, required: ['songId'], }, }, { name: 'create_playlist', description: '创建新的播放列表', inputSchema: { type: 'object', properties: { name: { type: 'string', description: '播放列表名称', }, description: { type: 'string', description: '播放列表描述', }, }, required: ['name'], }, }, { name: 'add_to_playlist', description: '将歌曲添加到播放列表', inputSchema: { type: 'object', properties: { playlistId: { type: 'string', description: '播放列表ID', }, songId: { type: 'string', description: '歌曲ID', }, }, required: ['playlistId', 'songId'], }, }, { name: 'get_playlist', description: '获取播放列表信息', inputSchema: { type: 'object', properties: { playlistId: { type: 'string', description: '播放列表ID', }, }, required: ['playlistId'], }, }, { name: 'list_playlists', description: '列出所有播放列表', inputSchema: { type: 'object', properties: {}, }, }, { name: 'get_recommendations', description: '根据用户喜好获取音乐推荐', inputSchema: { type: 'object', properties: { genre: { type: 'string', description: '音乐风格', }, mood: { type: 'string', description: '心情/氛围', }, limit: { type: 'number', description: '推荐数量', default: 10, }, }, }, }, ], }; }); // 处理工具调用 this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'search_music': return await this.handleSearchMusic(args); case 'get_song_info': return await this.handleGetSongInfo(args); case 'create_playlist': return await this.handleCreatePlaylist(args); case 'add_to_playlist': return await this.handleAddToPlaylist(args); case 'get_playlist': return await this.handleGetPlaylist(args); case 'list_playlists': return await this.handleListPlaylists(args); case 'get_recommendations': return await this.handleGetRecommendations(args); default: throw new Error(`未知的工具: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `错误: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }); } private async handleSearchMusic(args: any) { const { query, type = 'all', limit = 10 } = args; const results = await this.musicDb.search(query, type, limit); return { content: [ { type: 'text', text: `搜索结果 "${query}":\n\n${results.map(song => `🎵 ${song.title}\n👤 艺术家: ${song.artist}\n💿 专辑: ${song.album}\n⏱️ 时长: ${song.duration}\n🆔 ID: ${song.id}\n` ).join('\n')}`, }, ], }; } private async handleGetSongInfo(args: any) { const { songId } = args; const song = await this.musicDb.getSongById(songId); if (!song) { throw new Error(`未找到ID为 ${songId} 的歌曲`); } return { content: [ { type: 'text', text: `🎵 歌曲信息:\n\n标题: ${song.title}\n艺术家: ${song.artist}\n专辑: ${song.album}\n发行年份: ${song.year}\n时长: ${song.duration}\n风格: ${song.genre}\n播放次数: ${song.playCount}\n评分: ${song.rating}/5`, }, ], }; } private async handleCreatePlaylist(args: any) { const { name, description } = args; const playlist = await this.playlistManager.createPlaylist(name, description); return { content: [ { type: 'text', text: `✅ 播放列表创建成功!\n\n名称: ${playlist.name}\n描述: ${playlist.description || '无'}\nID: ${playlist.id}\n创建时间: ${playlist.createdAt}`, }, ], }; } private async handleAddToPlaylist(args: any) { const { playlistId, songId } = args; await this.playlistManager.addSongToPlaylist(playlistId, songId); const song = await this.musicDb.getSongById(songId); return { content: [ { type: 'text', text: `✅ 歌曲已添加到播放列表!\n\n歌曲: ${song?.title} - ${song?.artist}`, }, ], }; } private async handleGetPlaylist(args: any) { const { playlistId } = args; const playlist = await this.playlistManager.getPlaylist(playlistId); if (!playlist) { throw new Error(`未找到ID为 ${playlistId} 的播放列表`); } const songs = await Promise.all( playlist.songIds.map(id => this.musicDb.getSongById(id)) ); return { content: [ { type: 'text', text: `🎵 播放列表: ${playlist.name}\n\n描述: ${playlist.description || '无'}\n歌曲数量: ${playlist.songIds.length}\n创建时间: ${playlist.createdAt}\n\n歌曲列表:\n${songs.map((song, index) => `${index + 1}. ${song?.title} - ${song?.artist}` ).join('\n')}`, }, ], }; } private async handleListPlaylists(args: any) { const playlists = await this.playlistManager.getAllPlaylists(); return { content: [ { type: 'text', text: `📋 所有播放列表:\n\n${playlists.map(playlist => `🎵 ${playlist.name}\n📝 ${playlist.description || '无描述'}\n🎶 ${playlist.songIds.length} 首歌曲\n🆔 ID: ${playlist.id}\n` ).join('\n')}`, }, ], }; } private async handleGetRecommendations(args: any) { const { genre, mood, limit = 10 } = args; const recommendations = await this.musicDb.getRecommendations(genre, mood, limit); return { content: [ { type: 'text', text: `🎯 音乐推荐${genre ? ` (${genre})` : ''}${mood ? ` - ${mood}心情` : ''}:\n\n${recommendations.map(song => `🎵 ${song.title}\n👤 ${song.artist}\n💿 ${song.album}\n⭐ ${song.rating}/5\n🆔 ${song.id}\n` ).join('\n')}`, }, ], }; } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('音乐 MCP 服务器已启动'); } } const server = new MusicMCPServer(); server.run().catch(console.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/leehave/Claude-Music-Mcp'

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