Skip to main content
Glama

π“‚€π“’π“‹Ήπ”Έβ„•π•Œπ”Ήπ•€π•Šπ“‹Ήπ“’π“‚€ - Intelligent Guidance for

by Hive-Academy
review-operations.service.tsβ€’9.13 kB
import { Injectable, Inject } from '@nestjs/common'; import { CodeReview, CompletionReport, Prisma } from 'generated/prisma'; import { ZodSchema } from 'zod'; import { BaseMcpService, McpResponse, } from '../workflow-rules/utils/mcp-response.utils'; import { ReviewOperationsInput, ReviewOperationsInputSchema, } from './schemas/review-operations.schema'; import { Tool } from '@rekog/mcp-nest'; import { CodeReviewRepository } from './repositories/implementations/code-review.repository'; import { CompletionReportRepository } from './repositories/implementations/completion-report.repository'; // Type-safe interfaces for review operations export interface ReviewOperationResult { success: boolean; data?: CodeReview | CompletionReport | ReviewSummary | CompletionSummary; error?: { message: string; code: string; operation: string; }; metadata?: { operation: string; taskId: number; responseTime: number; }; } export interface ReviewSummary { taskId: number; status: string; summary: string; } export interface CompletionSummary { taskId: number; summary: string; createdAt: Date; } /** * Review Operations Service - MCP Tool * Handles code review and completion report management for workflow tasks * * SOLID Principles Applied: * - Single Responsibility: Focused on review and completion operations only * - Open/Closed: Extensible through input schema without modifying core logic * - Liskov Substitution: Consistent interface for all review operations * - Interface Segregation: Clean separation of review concerns * - Dependency Inversion: Depends on PrismaService abstraction */ @Injectable() export class ReviewOperationsService extends BaseMcpService { constructor( @Inject('ICodeReviewRepository') private readonly codeReviewRepository: CodeReviewRepository, @Inject('ICompletionReportRepository') private readonly completionReportRepository: CompletionReportRepository, ) { super(); } @Tool({ name: 'execute_review_operation', description: 'Execute review operations including create, update, get for code reviews and completion reports', parameters: ReviewOperationsInputSchema as ZodSchema, }) async executeReviewOperation( input: ReviewOperationsInput, ): Promise<McpResponse> { const startTime = performance.now(); try { let result: | CodeReview | CompletionReport | ReviewSummary | CompletionSummary; switch (input.operation) { case 'create_review': result = await this.createReview(input); break; case 'update_review': result = await this.updateReview(input); break; case 'get_review': result = await this.getReview(input); break; case 'create_completion': result = await this.createCompletion(input); break; case 'get_completion': result = await this.getCompletion(input); break; default: throw new Error(`Unknown operation: ${String(input.operation)}`); } const responseTime = performance.now() - startTime; return this.buildResponse({ success: true, data: result, metadata: { operation: input.operation, taskId: input.taskId, responseTime: Math.round(responseTime), }, }); } catch (error: any) { return this.buildResponse({ success: false, error: { message: error.message, code: 'REVIEW_OPERATION_FAILED', operation: input.operation, }, }); } } private async createReview( input: ReviewOperationsInput, ): Promise<CodeReview> { const { taskId, reviewData } = input; if (!reviewData) { throw new Error('Review data is required for creation'); } const review = await this.codeReviewRepository.create({ task: { connect: { id: taskId } }, status: reviewData.status, summary: reviewData.summary, strengths: reviewData.strengths || '', issues: reviewData.issues || '', acceptanceCriteriaVerification: reviewData.acceptanceCriteriaVerification || {}, manualTestingResults: reviewData.manualTestingResults || '', requiredChanges: reviewData.requiredChanges || null, } satisfies Prisma.CodeReviewCreateInput); return review; } private async updateReview( input: ReviewOperationsInput, ): Promise<CodeReview> { const { taskId, reviewData } = input; if (!reviewData) { throw new Error('Review data is required for update'); } // Find the code review by taskId first const existingReview = await this.codeReviewRepository.findByTaskId(taskId); if (!existingReview) { throw new Error(`Code review not found for task ${taskId}`); } const updateData: any = {}; if (reviewData.status) updateData.status = reviewData.status; if (reviewData.summary) updateData.summary = reviewData.summary; if (reviewData.strengths) updateData.strengths = reviewData.strengths; if (reviewData.issues) updateData.issues = reviewData.issues; if (reviewData.acceptanceCriteriaVerification) { updateData.acceptanceCriteriaVerification = reviewData.acceptanceCriteriaVerification; } if (reviewData.manualTestingResults) { updateData.manualTestingResults = reviewData.manualTestingResults; } if (reviewData.requiredChanges) { updateData.requiredChanges = reviewData.requiredChanges; } const review = await this.codeReviewRepository.update( existingReview.id, updateData, ); return review; } private async getReview( input: ReviewOperationsInput, ): Promise<CodeReview | ReviewSummary> { const { taskId, includeDetails } = input; const review = await this.codeReviewRepository.findByTaskId(taskId); if (!review) { throw new Error(`Code review not found for task ${taskId}`); } if (!includeDetails) { // Return summary only return { taskId: review.taskId, status: review.status, summary: review.summary, } as ReviewSummary; } return review; } private async createCompletion( input: ReviewOperationsInput, ): Promise<CompletionReport> { const { taskId, completionData } = input; if (!completionData) { throw new Error('Completion data is required for creation'); } const completion = await this.completionReportRepository.create({ task: { connect: { id: taskId } }, summary: completionData.summary, filesModified: completionData.filesModified || [], acceptanceCriteriaVerification: completionData.acceptanceCriteriaVerification || {}, delegationSummary: completionData.delegationSummary || '', } satisfies Prisma.CompletionReportCreateInput); return completion; } private async getCompletion( input: ReviewOperationsInput, ): Promise<CompletionReport | CompletionSummary> { const { taskId, includeDetails } = input; const completion = await this.completionReportRepository.findByTaskId(taskId); if (!completion) { throw new Error(`Completion report not found for task ${taskId}`); } if (!includeDetails) { // Return summary only return { taskId: completion.taskId, summary: completion.summary, createdAt: completion.createdAt, } as CompletionSummary; } return completion; } /** * Internal method for backward compatibility * Allows other services to call review operations without MCP wrapping */ async executeReviewOperationInternal( input: ReviewOperationsInput, ): Promise<ReviewOperationResult> { const startTime = performance.now(); try { let result: | CodeReview | CompletionReport | ReviewSummary | CompletionSummary; switch (input.operation) { case 'create_review': result = await this.createReview(input); break; case 'update_review': result = await this.updateReview(input); break; case 'get_review': result = await this.getReview(input); break; case 'create_completion': result = await this.createCompletion(input); break; case 'get_completion': result = await this.getCompletion(input); break; default: throw new Error(`Unknown operation: ${String(input.operation)}`); } const responseTime = performance.now() - startTime; return { success: true, data: result, metadata: { operation: input.operation, taskId: input.taskId, responseTime: Math.round(responseTime), }, }; } catch (error: any) { return { success: false, error: { message: error.message, code: 'REVIEW_OPERATION_FAILED', operation: input.operation, }, }; } } }

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/Hive-Academy/Anubis-MCP'

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