Skip to main content
Glama
cyqlelabs

MCP Dual-Cycle Reasoner

by cyqlelabs

retrieve_similar_cases

Use this tool to find and retrieve similar cases from the case base based on a provided problem description. Input a description and specify the maximum number of results for precise matching.

Instructions

Retrieve similar cases from the case base

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMaximum number of cases to return
problem_descriptionYesSimple description of the problem

Implementation Reference

  • The execute handler for the 'retrieve_similar_cases' tool. It validates input using the schema, retrieves the session's DualCycleEngine, calls getSimilarCases on it with filters, simplifies the result by removing internal fields, and returns JSON.
    execute: async (args, { log, reportProgress, session }) => {
      try {
        const sessionEngine = this.getSessionEngine(session);
        const sessionId = this.sessionIds.get(session);
        const validatedArgs = RetrieveSimilarCasesInputSchema.parse(args);
    
        log.info('Retrieving similar cases', {
          problemDescription: validatedArgs.problem_description,
          maxResults: validatedArgs.max_results,
          sessionId,
        });
    
        await reportProgress({ progress: 0, total: 2 });
    
        const filters = {
          context_filter: validatedArgs.context_filter,
          difficulty_filter: validatedArgs.difficulty_filter,
          outcome_filter: validatedArgs.outcome_filter,
          min_similarity: validatedArgs.min_similarity,
        };
    
        const result = await sessionEngine.getSimilarCases(
          validatedArgs.problem_description,
          validatedArgs.max_results,
          filters
        );
    
        await reportProgress({ progress: 2, total: 2 });
    
        log.info('Similar cases retrieved', {
          casesFound: result.length,
          maxResults: validatedArgs.max_results,
        });
    
        const simplifiedResult = result.map((caseItem: any) => {
          const { semantic_features, similarity_metrics, ...rest } = caseItem;
          return rest;
        });
    
        return JSON.stringify(simplifiedResult, null, 2);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        log.error('Failed to retrieve similar cases', { error: errorMessage });
        throw new UserError(`Failed to retrieve similar cases: {errorMessage}`);
      }
    },
  • src/server.ts:527-588 (registration)
    The registration of the 'retrieve_similar_cases' tool using FastMCP's addTool method within addRetrieveSimilarCasesTool().
      this.server.addTool({
        name: 'retrieve_similar_cases',
        description: 'Retrieve similar cases from the case base',
        parameters: z.object({
          problem_description: z.string().describe(DESCRIPTIONS.PROBLEM_DESCRIPTION),
          max_results: z.number().optional().default(5).describe(DESCRIPTIONS.MAX_RESULTS),
        }),
        annotations: {
          title: 'Retrieve Similar Cases',
          readOnlyHint: true,
          destructiveHint: false,
          idempotentHint: true,
          openWorldHint: false,
        },
        execute: async (args, { log, reportProgress, session }) => {
          try {
            const sessionEngine = this.getSessionEngine(session);
            const sessionId = this.sessionIds.get(session);
            const validatedArgs = RetrieveSimilarCasesInputSchema.parse(args);
    
            log.info('Retrieving similar cases', {
              problemDescription: validatedArgs.problem_description,
              maxResults: validatedArgs.max_results,
              sessionId,
            });
    
            await reportProgress({ progress: 0, total: 2 });
    
            const filters = {
              context_filter: validatedArgs.context_filter,
              difficulty_filter: validatedArgs.difficulty_filter,
              outcome_filter: validatedArgs.outcome_filter,
              min_similarity: validatedArgs.min_similarity,
            };
    
            const result = await sessionEngine.getSimilarCases(
              validatedArgs.problem_description,
              validatedArgs.max_results,
              filters
            );
    
            await reportProgress({ progress: 2, total: 2 });
    
            log.info('Similar cases retrieved', {
              casesFound: result.length,
              maxResults: validatedArgs.max_results,
            });
    
            const simplifiedResult = result.map((caseItem: any) => {
              const { semantic_features, similarity_metrics, ...rest } = caseItem;
              return rest;
            });
    
            return JSON.stringify(simplifiedResult, null, 2);
          } catch (error) {
            const errorMessage = error instanceof Error ? error.message : String(error);
            log.error('Failed to retrieve similar cases', { error: errorMessage });
            throw new UserError(`Failed to retrieve similar cases: {errorMessage}`);
          }
        },
      });
    }
  • Zod schema for validating input parameters to the retrieve_similar_cases tool.
    export const RetrieveSimilarCasesInputSchema = z.object({
      problem_description: z.string().describe(DESCRIPTIONS.PROBLEM_DESCRIPTION),
      max_results: z.number().default(5).describe(DESCRIPTIONS.MAX_RESULTS),
      context_filter: z.string().optional().describe('Filter cases by context'),
      difficulty_filter: z
        .enum(['low', 'medium', 'high'])
        .optional()
        .describe('Filter cases by difficulty level'),
      outcome_filter: z.boolean().optional().describe('Filter cases by outcome (success/failure)'),
      min_similarity: z.number().min(0).max(1).optional().describe('Minimum similarity threshold'),
    });
  • Wrapper method in DualCycleEngine that delegates to Adjudicator's retrieveSimilarCases.
    async getSimilarCases(
      problemDescription: string,
      maxResults: number = 5,
      filters: {
        context_filter?: string;
        difficulty_filter?: 'low' | 'medium' | 'high';
        outcome_filter?: boolean;
        min_similarity?: number;
      } = {}
    ): Promise<Case[]> {
      return await this.adjudicator.retrieveSimilarCases(
        problemDescription,
        maxResults,
        filters,
        this.sessionId
      );
    }
  • Core implementation in Adjudicator class performing semantic feature extraction, filtering, enhanced similarity calculation (semantic + traditional NLP), sorting, and fallback retrieval.
    async retrieveSimilarCases(
      problemDescription: string,
      maxResults: number = 5,
      filters: {
        context_filter?: string;
        difficulty_filter?: 'low' | 'medium' | 'high';
        outcome_filter?: boolean;
        min_similarity?: number;
      } = {},
      sessionId?: string
    ): Promise<Case[]> {
      if (!this.isInitialized) {
        await this.initialize();
      }
      try {
        // Check if semantic analyzer is available
        if (!semanticAnalyzer.isReady()) {
          throw new Error('SemanticAnalyzer is not ready');
        }
    
        // Extract semantic features from the query
        const queryFeatures = await semanticAnalyzer.extractSemanticFeatures(
          problemDescription,
          this.semanticIntents
        );
    
        // Filter cases based on provided filters
        let filteredCases = this.caseBase;
    
        if (filters.context_filter) {
          filteredCases = filteredCases.filter(
            (case_) =>
              case_.context?.includes(filters.context_filter!) ||
              case_.problem_description.includes(filters.context_filter!)
          );
        }
    
        if (filters.difficulty_filter) {
          filteredCases = filteredCases.filter(
            (case_) => case_.difficulty_level === filters.difficulty_filter
          );
        }
    
        if (filters.outcome_filter !== undefined) {
          filteredCases = filteredCases.filter((case_) => case_.outcome === filters.outcome_filter);
        }
    
        // Calculate enhanced similarity scores
        const scoredCases = await Promise.all(
          filteredCases.map(async (case_) => {
            const rawSimilarity = await this.calculateEnhancedSimilarity(
              problemDescription,
              case_.problem_description,
              queryFeatures,
              case_.semantic_features,
              sessionId
            );
    
            return {
              case: case_,
              similarity: rawSimilarity,
              rawSimilarity: rawSimilarity,
            };
          })
        );
    
        // Filter by minimum similarity threshold (more restrictive due to inflated semantic scores)
        const minSimilarity = filters.min_similarity || 0.6;
        const validCases = scoredCases.filter((item) => item.similarity >= minSimilarity);
    
        // Sort by similarity and success rate
        const sortedCases = validCases.sort((a, b) => {
          // Primary sort by similarity
          if (Math.abs(a.similarity - b.similarity) > 0.05) {
            return b.similarity - a.similarity;
          }
          // Secondary sort by success rate for similar cases
          const aSuccessRate = a.case.success_rate || (a.case.outcome ? 1 : 0);
          const bSuccessRate = b.case.success_rate || (b.case.outcome ? 1 : 0);
          return bSuccessRate - aSuccessRate;
        });
    
        // Update usage statistics and calculate dynamic confidence/validation scores
        const results = sortedCases.slice(0, maxResults);
        results.forEach((item) => {
          item.case.usage_count = (item.case.usage_count || 0) + 1;
    
          // Calculate dynamic confidence score based on similarity to query
          // Higher similarity = higher confidence in the match
          const similarityConfidence = Math.min(1.0, item.rawSimilarity * 1.2); // Boost good similarities
          const usageBonus = Math.min(0.1, (item.case.usage_count || 0) * 0.02);
          const outcomeBonus = item.case.outcome ? 0.1 : 0;
    
          // Dynamic confidence score reflecting match quality
          item.case.confidence_score = Math.max(
            0,
            Math.min(1, similarityConfidence + usageBonus + outcomeBonus)
          );
    
          // Add similarity metrics to the case for reference
          item.case.similarity_metrics = {
            ...item.case.similarity_metrics,
            raw_similarity: item.rawSimilarity,
            combined_similarity: item.rawSimilarity,
          };
        });
    
        return results.map((item) => item.case);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        console.error(
          'Error retrieving similar cases, falling back to simple matching:',
          errorMessage
        );
        // Fallback to simple similarity matching
        return this.fallbackRetrieveSimilarCases(problemDescription, maxResults);
      }
    }
Install Server

Other Tools

Related Tools

Latest Blog Posts

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/cyqlelabs/mcp-dual-cycle-reasoner'

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