/**
* analyze_music Tool
*
* Extracts genre, mood, tempo, key, and instruments from audio files.
*/
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { MusicAnalysisResult } from '../types/mcp-tools.js';
import {
IRCAM_API_CONFIG,
IrcamMusicTaggerResponse,
transformMusicTaggerResponse,
} from '../types/ircam-api.js';
import { httpPost, buildApiUrl } from '../utils/http.js';
import { validateAudioUrl } from '../utils/validation.js';
import { formatError } from '../utils/errors.js';
/**
* Tool definition for MCP registration
*/
export const analyzeMusicTool: Tool = {
name: 'analyze_music',
description:
'Analyze an audio file to extract genre, mood, tempo, key, and detected instruments. ' +
'Accepts a public URL to an audio file (MP3, WAV, FLAC, OGG, M4A). ' +
'Returns structured tags useful for music classification and discovery.',
inputSchema: {
type: 'object',
properties: {
audio_url: {
type: 'string',
description: 'Public URL to the audio file to analyze',
},
},
required: ['audio_url'],
},
};
/**
* Handle analyze_music tool call
*/
export async function handleAnalyzeMusic(
args: Record<string, unknown>
): Promise<MusicAnalysisResult> {
const audioUrl = args.audio_url as string;
// Validate input
const validation = validateAudioUrl(audioUrl);
if (!validation.valid) {
throw validation.error;
}
// Call IRCAM Music Tagger API
const url = buildApiUrl(IRCAM_API_CONFIG.ENDPOINTS.MUSIC_TAGGER);
const response = await httpPost<IrcamMusicTaggerResponse>(url, {
url: audioUrl,
});
if (!response.ok || !response.data) {
throw response.error || formatError('UNKNOWN_ERROR', 'Failed to analyze music');
}
// Transform and return result
return transformMusicTaggerResponse(response.data);
}