/**
* check_job_status Tool
*
* Checks the status of an async job and retrieves results when completed.
*/
import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { JobStatusOutput, StemSeparationResult } from '../types/mcp-tools.js';
import { IRCAM_API_CONFIG, IrcamJobStatusResponse } from '../types/ircam-api.js';
import { httpGet, buildApiUrl } from '../utils/http.js';
import { validateJobId } from '../utils/validation.js';
import { formatError } from '../utils/errors.js';
/**
* Tool definition for MCP registration
*/
export const checkJobStatusTool: Tool = {
name: 'check_job_status',
description:
'Check the status of an async processing job. ' +
'Use this to monitor jobs returned by separate_stems and other async operations. ' +
'Returns job status (pending, processing, completed, failed), progress percentage, and results when completed.',
inputSchema: {
type: 'object',
properties: {
job_id: {
type: 'string',
description: 'The job ID returned by an async operation',
},
},
required: ['job_id'],
},
};
/**
* Handle check_job_status tool call
*/
export async function handleCheckJobStatus(
args: Record<string, unknown>
): Promise<JobStatusOutput> {
const jobId = args.job_id as string;
// Validate input
const validation = validateJobId(jobId);
if (!validation.valid) {
throw validation.error;
}
// Call IRCAM Job Status API
const url = buildApiUrl(`${IRCAM_API_CONFIG.ENDPOINTS.JOB_STATUS}/${jobId}`);
const response = await httpGet<IrcamJobStatusResponse>(url);
if (!response.ok || !response.data) {
throw response.error || formatError('JOB_NOT_FOUND', 'Job not found');
}
const job = response.data;
// Build job state response
const result: JobStatusOutput = {
status: job.status,
progress: job.progress,
};
// Add result if completed (assuming stem separation result)
if (job.status === 'completed' && job.result) {
const stemResult = job.result as {
stems?: {
vocals?: { url: string };
drums?: { url: string };
bass?: { url: string };
other?: { url: string };
};
};
if (stemResult.stems) {
result.result = {
vocals_url: stemResult.stems.vocals?.url || '',
drums_url: stemResult.stems.drums?.url || '',
bass_url: stemResult.stems.bass?.url || '',
other_url: stemResult.stems.other?.url || '',
} as StemSeparationResult;
}
}
// Add error if failed
if (job.status === 'failed' && job.error) {
result.error = job.error;
}
return result;
}