vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
179 lines (178 loc) ⢠10.6 kB
JavaScript
import { z } from 'zod';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import logger from '../../logger.js';
import { registerTool } from '../../services/routing/toolRegistry.js';
import { jobManager, JobStatus } from '../../services/job-manager/index.js';
import { createJobStatusMessage } from '../../services/job-manager/jobStatusMessage.js';
const getJobResultInputSchemaShape = {
jobId: z.string().uuid({ message: "Invalid Job ID format. Must be a UUID." }).describe("The unique identifier of the job to retrieve."),
includeDetails: z.boolean().default(true).optional().describe("Whether to include detailed diagnostic information in the response. Defaults to true.")
};
export const getJobResult = async (params, _config, context) => {
const { jobId, includeDetails = true } = params;
const sessionId = context?.sessionId || 'unknown-session';
const transportType = context?.transportType || 'unknown';
try {
logger.info({ jobId, sessionId, transportType }, `Attempting to retrieve result for job.`);
const { job, waitTime, shouldWait } = jobManager.getJobWithRateLimit(jobId);
if (!job) {
logger.warn({ jobId }, `Job not found.`);
const notFoundError = new McpError(ErrorCode.InvalidParams, `Job with ID '${jobId}' not found.`);
return {
content: [{ type: 'text', text: notFoundError.message }],
isError: true,
errorDetails: notFoundError
};
}
if (shouldWait) {
logger.info({ jobId, waitTime }, `Rate limited job status request.`);
const statusMessage = createJobStatusMessage(jobId, job.toolName, job.status, `Rate limited: Please wait ${Math.ceil(waitTime / 1000)} seconds before checking again.`, undefined, job.createdAt, job.updatedAt, includeDetails ? job.details : undefined);
return {
content: [{
type: 'text',
text: `Job '${jobId}' (${job.toolName}) status is being checked too frequently. Please wait ${Math.ceil(waitTime / 1000)} seconds before checking again. Current status: ${job.status}, last updated at: ${new Date(job.updatedAt).toISOString()}.`
}],
isError: false,
pollInterval: waitTime,
jobStatus: statusMessage
};
}
let responseText = '';
let finalResult = undefined;
switch (job.status) {
case JobStatus.PENDING:
responseText = `Job '${jobId}' (${job.toolName}) is pending. Created at: ${new Date(job.createdAt).toISOString()}.`;
break;
case JobStatus.RUNNING:
responseText = `Job '${jobId}' (${job.toolName}) is running. Status updated at: ${new Date(job.updatedAt).toISOString()}.`;
if (job.progressMessage) {
responseText += `\n\nš **Progress**: ${job.progressMessage}`;
}
if (job.progressPercentage !== undefined) {
responseText += `\nā±ļø **Completion**: ${job.progressPercentage}%`;
}
if (job.details?.metadata?.estimatedCompletion &&
(typeof job.details.metadata.estimatedCompletion === 'string' ||
typeof job.details.metadata.estimatedCompletion === 'number' ||
job.details.metadata.estimatedCompletion instanceof Date)) {
responseText += `\nš **Estimated Completion**: ${new Date(job.details.metadata.estimatedCompletion).toISOString()}`;
}
responseText += `\n\nš” **Tip**: Continue polling for updates. This job will provide detailed results when complete.`;
break;
case JobStatus.COMPLETED:
responseText = `Job '${jobId}' (${job.toolName}) completed successfully at: ${new Date(job.updatedAt).toISOString()}.`;
if (job.result) {
finalResult = JSON.parse(JSON.stringify(job.result));
if (finalResult) {
if (finalResult.taskData && Array.isArray(finalResult.taskData) && finalResult.taskData.length > 0) {
const taskSummary = `\n\nš **Task Summary:**\n` +
`⢠Total Tasks: ${finalResult.taskData.length}\n` +
`⢠Total Hours: ${finalResult.taskData.reduce((sum, task) => sum + (typeof task.estimatedHours === 'number' ? task.estimatedHours : 0), 0)}h\n` +
`⢠Files Created: ${Array.isArray(finalResult.fileReferences) ? finalResult.fileReferences.length : 0}\n`;
const completionNote = {
type: 'text',
text: taskSummary + `\n---\nJob Status: COMPLETED (${new Date(job.updatedAt).toISOString()})`
};
finalResult.content = [...(finalResult.content || []), completionNote];
}
else {
const completionNote = {
type: 'text',
text: `\n---\nJob Status: COMPLETED (${new Date(job.updatedAt).toISOString()})`
};
finalResult.content = [...(finalResult.content || []), completionNote];
}
}
else {
logger.error({ jobId }, "Deep copy of job result failed unexpectedly for COMPLETED job.");
responseText += ' Failed to process final result.';
}
}
else {
responseText += ' However, the final result is missing.';
logger.error({ jobId }, "Job status is COMPLETED but result is missing.");
}
break;
case JobStatus.FAILED:
responseText = `Job '${jobId}' (${job.toolName}) failed at: ${new Date(job.updatedAt).toISOString()}. Reason: ${job.progressMessage || 'No failure message available.'}`;
if (job.result && job.result.isError) {
finalResult = JSON.parse(JSON.stringify(job.result));
if (finalResult) {
const failureNote = { type: 'text', text: `\n---\nJob Status: FAILED (${new Date(job.updatedAt).toISOString()})` };
finalResult.content = [...(finalResult.content || []), failureNote];
}
else {
logger.error({ jobId }, "Deep copy of job result failed unexpectedly for FAILED job.");
responseText += ' Failed to process error result.';
}
}
else {
responseText += ' Error details are missing.';
logger.error({ jobId }, "Job status is FAILED but error result is missing or not marked as error.");
finalResult = {
content: [{ type: 'text', text: responseText }],
isError: true,
errorDetails: new McpError(ErrorCode.InternalError, "Job failed but error details are missing.", { jobId })
};
}
break;
default:
logger.error({ jobId, status: job.status }, `Job has unknown status.`);
responseText = `Job '${jobId}' has an unknown status: ${job.status}.`;
break;
}
if (finalResult) {
logger.info({ jobId, status: job.status }, `Returning final stored result for job.`);
return finalResult;
}
const statusMessage = createJobStatusMessage(jobId, job.toolName, job.status, job.progressMessage, job.progressPercentage, job.createdAt, job.updatedAt, includeDetails ? job.details : undefined);
if (statusMessage.pollingRecommendation) {
responseText += `\n\nRecommended polling interval: ${statusMessage.pollingRecommendation.interval / 1000} seconds.`;
}
if (includeDetails && statusMessage.details) {
responseText += '\n\n--- Detailed Information ---';
if (statusMessage.details.currentStage) {
responseText += `\nCurrent Stage: ${statusMessage.details.currentStage}`;
}
if (statusMessage.details.subProgress !== undefined) {
responseText += `\nSub-progress: ${statusMessage.details.subProgress}%`;
}
if (statusMessage.details.diagnostics && statusMessage.details.diagnostics.length > 0) {
responseText += '\nDiagnostics:';
statusMessage.details.diagnostics.forEach((diagnostic, index) => {
responseText += `\n ${index + 1}. ${diagnostic}`;
});
}
if (statusMessage.details.metadata && Object.keys(statusMessage.details.metadata).length > 0) {
responseText += '\nMetadata:';
Object.entries(statusMessage.details.metadata).forEach(([key, value]) => {
responseText += `\n ${key}: ${JSON.stringify(value)}`;
});
}
}
logger.info({ jobId, status: job.status }, `Returning current status for job.`);
return {
content: [{ type: "text", text: responseText }],
isError: false,
jobStatus: statusMessage,
pollingRecommendation: statusMessage.pollingRecommendation
};
}
catch (error) {
logger.error({ err: error, jobId }, 'Error retrieving job result.');
const execError = new McpError(ErrorCode.InternalError, `An unexpected error occurred while retrieving job '${jobId}'.`, { originalError: String(error) });
return {
content: [{ type: 'text', text: execError.message }],
isError: true,
errorDetails: execError
};
}
};
const getJobResultToolDefinition = {
name: "get-job-result",
description: "Retrieves the current status and, if available, the final result of a background job. Supports enhanced diagnostic information for debugging and troubleshooting.",
inputSchema: getJobResultInputSchemaShape,
executor: getJobResult
};
registerTool(getJobResultToolDefinition);
logger.info("Registered tool: get-job-result");