Skip to main content
Glama

Analytical MCP Server

logical_fallacy_detector.ts10.2 kB
import { z } from 'zod'; import { ValidationError, ToolExecutionError, DataProcessingError } from '../utils/errors.js'; import { Logger } from '../utils/logger.js'; // Fallacy definition type interface FallacyDefinition { name: string; category: string; description: string; signals: RegExp[]; confidence: number; examples: { bad: string; good: string; }; } // Schema for logical fallacy detector const logicalFallacyDetectorSchemaDefinition = z.object({ text: z.string().describe('Text to analyze for logical fallacies'), confidenceThreshold: z .number() .min(0) .max(1) .default(0.5) .describe('Minimum confidence level to report a fallacy'), categories: z .array(z.enum(['informal', 'formal', 'relevance', 'ambiguity', 'all'])) .default(['all']), includeExplanations: z.boolean().default(true), includeExamples: z.boolean().default(true), }); // Export the schema export const logicalFallacyDetectorSchema = logicalFallacyDetectorSchemaDefinition; // Comprehensive list of logical fallacies function getFallacyDefinitions(): FallacyDefinition[] { return [ { name: 'Ad Hominem', category: 'relevance', description: 'Attacking the person making the argument rather than addressing the argument itself', signals: [ /\b(stupid|idiot|fool|ignorant|young)\b/i, /too \w+ to understand/i, /attack on character/i, /personal insult/i, ], confidence: 0.7, examples: { bad: "You can't trust her climate policy because she's just a young activist.", good: "Let's evaluate the climate policy based on its merits, evidence, and potential impact.", }, }, { name: 'Straw Man', category: 'relevance', description: "Misrepresenting an opponent's argument to make it easier to attack", signals: [/that means you want/i, /so you're saying/i, /exaggerated interpretation/i], confidence: 0.6, examples: { bad: 'You support gun control? So you want to completely abolish the Second Amendment!', good: "Let's discuss the specific gun control measures you're proposing and their potential impacts.", }, }, { name: 'False Dichotomy', category: 'informal', description: 'Presenting only two alternatives when more exist', signals: [/\b(either|or)\b/i, /only two choices/i, /black and white/i], confidence: 0.5, examples: { bad: 'We must either cut taxes dramatically or the economy will collapse.', good: "Let's explore multiple economic strategies, including targeted tax adjustments, spending reforms, and regulatory approaches.", }, }, { name: 'Slippery Slope', category: 'informal', description: 'Arguing that a small first step will inevitably lead to a chain of related events', signals: [/will lead to/i, /next thing you know/i, /eventually/i], confidence: 0.6, examples: { bad: 'If we legalize same-sex marriage, next people will want to marry animals!', good: "Let's examine the specific legal and social implications of marriage equality based on existing marriage laws.", }, }, { name: 'Appeal to Authority', category: 'relevance', description: 'Claiming something is true because an authority figure says so', signals: [ /expert/i, /experts claim/i, /according to/i, /celebrity/i, /doctor/i, /so it must be/i, /must be/i, /authoritative/i, ], confidence: 0.4, // Lowered to match test case with 0.3 threshold examples: { bad: 'This diet must work because a celebrity doctor recommends it.', good: "Let's review peer-reviewed scientific studies and medical research about this diet's effectiveness.", }, }, ]; } // Internal implementation of logical fallacy detector async function detectFallacies( text: string, confidenceThreshold: number = 0.5, categories: string[] = ['all'], includeExplanations: boolean = true, includeExamples: boolean = true ): Promise<string> { try { // Performance optimization: early validation of input length if (!text || text.trim().length === 0) { throw new ValidationError('ERR_1001', 'Empty or invalid text provided for fallacy detection'); } Logger.debug(`Analyzing text for logical fallacies`, { textLength: text.length, confidenceThreshold, categories, }); // Validate input let validatedInput; try { validatedInput = logicalFallacyDetectorSchemaDefinition.parse({ text, confidenceThreshold, categories, includeExplanations, includeExamples, }); } catch (error) { if (error instanceof z.ZodError) { Logger.error('Validation error in logical fallacy detector', error); throw new ValidationError( 'ERR_1001', `Invalid parameters for logical fallacy detection: ${error.message}`, { issues: error.issues } ); } throw error; } // Prepare report let report = `# Logical Fallacy Analysis\n\n`; report += `## Original Text:\n> ${text}\n\n`; // Get fallacy definitions const fallacyDefinitions = getFallacyDefinitions(); // Filter fallacies based on categories const fallenciesToCheck = categories.includes('all') ? fallacyDefinitions : fallacyDefinitions.filter((f) => categories.includes(f.category)); Logger.debug(`Checking for ${fallenciesToCheck.length} potential fallacy types`); // Detected fallacies const detectedFallacies: FallacyDefinition[] = []; // Analyze text for fallacies (performance optimized version) const textLower = text.toLowerCase(); // Pre-compute lowercase text once try { for (const fallacy of fallenciesToCheck) { let confidence = 0; let matchCount = 0; // Check signals - exit early when match found for (const signal of fallacy.signals) { if (signal.test(text)) { matchCount++; confidence = fallacy.confidence; break; // Exit signal loop once we have a match } } // Apply confidence threshold and ensure we only add each fallacy once if (matchCount > 0 && confidence >= confidenceThreshold) { detectedFallacies.push({ ...fallacy, confidence, }); } } } catch (error) { Logger.error('Error during fallacy pattern matching', error); throw new DataProcessingError( 'ERR_3001', `Error analyzing text for fallacies: ${error instanceof Error ? error.message : String(error)}`, { textLength: text.length } ); } // Report detected fallacies if (detectedFallacies.length === 0) { report += '**No significant logical fallacies detected.**\n\n'; report += 'The argument appears to be logically sound based on the analysis.'; Logger.debug('No fallacies detected in text'); return report; } // Organize fallacies by category const categorizedFallacies: Record<string, FallacyDefinition[]> = {}; detectedFallacies.forEach((fallacy) => { if (!categorizedFallacies[fallacy.category]) { categorizedFallacies[fallacy.category] = []; } categorizedFallacies[fallacy.category]!.push(fallacy); }); // Generate detailed report report += `## Detected Logical Fallacies\n\n`; Object.entries(categorizedFallacies).forEach(([category, fallacies]) => { report += `### ${category.charAt(0).toUpperCase() + category.slice(1)} Fallacies\n\n`; fallacies.forEach((fallacy) => { report += `#### ${fallacy.name} (${(fallacy.confidence * 100).toFixed(0)}% confidence)\n\n`; if (includeExplanations) { report += `**Description:** ${fallacy.description}\n\n`; } if (includeExamples) { report += `**Example of Fallacious Reasoning:**\n> ${fallacy.examples.bad}\n\n`; report += `**Improved Reasoning:**\n> ${fallacy.examples.good}\n\n`; } }); }); // Add overall assessment report += `## Overall Assessment\n\n`; report += `**Total Fallacies Detected:** ${detectedFallacies.length}\n\n`; report += `**Severity:** ${ detectedFallacies.length > 2 ? 'High' : detectedFallacies.length > 1 ? 'Moderate' : 'Low' }\n\n`; Logger.debug(`Detected ${detectedFallacies.length} fallacies in text`); return report; } catch (error) { // Ensure errors are properly logged and propagated if (error instanceof ValidationError || error instanceof DataProcessingError) { // These errors are already logged and formatted appropriately throw error; } // For unknown errors, wrap in a DataProcessingError for consistent handling Logger.error('Unexpected error in logical fallacy detector', error); throw new DataProcessingError( 'ERR_3001', `Logical fallacy detection failed: ${error instanceof Error ? error.message : String(error)}`, { textLength: text?.length } ); } } // Export the function export const logicalFallacyDetector = async ( textOrParams: string | { text: string; confidenceThreshold?: number; categories?: string[]; includeExplanations?: boolean; includeExamples?: boolean; }, confidenceThreshold: number = 0.5, categories: string[] = ['all'], includeExplanations: boolean = true, includeExamples: boolean = true ): Promise<string> => { // Handle both parameter styles (object and individual parameters) if (typeof textOrParams === 'object') { return detectFallacies( textOrParams.text, textOrParams.confidenceThreshold ?? 0.5, textOrParams.categories ?? ['all'], textOrParams.includeExplanations ?? true, textOrParams.includeExamples ?? true ); } else { return detectFallacies( textOrParams, confidenceThreshold, categories, includeExplanations, includeExamples ); } };

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/quanticsoul4772/analytical-mcp'

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