Anti-Bullshit MCP Server

by bmorphism
Verified
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from "@modelcontextprotocol/sdk/types.js"; import { VALIDATION_FRAMEWORKS, validateWithFramework, getValidationSuggestions } from "./validation.js"; const server = new Server( { name: "anti-bullshit-mcp-server", version: "0.1.0", }, { capabilities: { tools: { analyze_claim: true, validate_sources: true, check_manipulation: true }, }, } ); // Load validation framework configuration from environment const VALIDATION_FRAMEWORK = (process.env.VALIDATION_FRAMEWORK || "pluralistic") as keyof typeof VALIDATION_FRAMEWORKS; // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "analyze_claim", description: "Analyze a claim using multiple epistemological frameworks and suggest validation steps", inputSchema: { type: "object", properties: { text: { type: "string", description: "Claim to analyze", }, framework: { type: "string", description: "Validation framework to use (empirical, responsible, harmonic, or pluralistic)", enum: ["empirical", "responsible", "harmonic", "pluralistic"], } }, required: ["text"], }, }, { name: "validate_sources", description: "Validate sources and evidence using configured framework", inputSchema: { type: "object", properties: { text: { type: "string", description: "Text containing claims and sources to validate", }, framework: { type: "string", description: "Validation framework to use", enum: ["empirical", "responsible", "harmonic", "pluralistic"], } }, required: ["text"], }, }, { name: "check_manipulation", description: "Check for manipulation tactics across different cultural contexts", inputSchema: { type: "object", properties: { text: { type: "string", description: "Text to analyze for manipulation", } }, required: ["text"], }, } ], }; }); // Handle tool execution interface ToolArguments { text: string; framework?: string; } server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: rawArgs } = request.params; const args = rawArgs as unknown as ToolArguments; if (!args || typeof args.text !== 'string') { throw new McpError(ErrorCode.InvalidParams, "Text parameter is required and must be a string"); } try { if (name === "analyze_claim") { const framework: keyof typeof VALIDATION_FRAMEWORKS = (typeof args.framework === 'string' && args.framework in VALIDATION_FRAMEWORKS) ? args.framework as keyof typeof VALIDATION_FRAMEWORKS : VALIDATION_FRAMEWORK; const validation = validateWithFramework(args.text, framework, { hasEmpirical: /evidence|study|research|data/i.test(args.text), servesWellbeing: /benefit|improve|help|support/i.test(args.text), maintainsHarmony: /balance|harmony|integrate/i.test(args.text) }); const suggestions = getValidationSuggestions(args.text, framework); // Generate cross-referencing prompts const crossRefPrompts = [ `- Use Exa MCP server to search for general information: "${args.text}"`, `- Use Brave Search for independent web sources: "${args.text}"`, `- Search ArXiv for preprints and technical papers: "${args.text}"`, `- Use Google Scholar MCP server to find peer-reviewed research: "${args.text}"`, `- Cross-reference findings between academic and general sources to identify consensus or conflicts` ]; // Framework-specific cross-references if (framework === "empirical" || framework === "pluralistic") { crossRefPrompts.push( `- Compare methodologies between ArXiv papers and peer-reviewed research`, `- Analyze replication status across different studies`, `- Cross-validate findings between academic databases` ); } if (framework === "responsible" || framework === "pluralistic") { crossRefPrompts.push( `- Use Exa MCP server to search for community impact studies: "${args.text}"`, `- Cross-reference academic findings with community experiences`, `- Compare traditional knowledge with modern research findings` ); } if (framework === "harmonic" || framework === "pluralistic") { crossRefPrompts.push( `- Use Exa MCP server to search for alternative perspectives: "${args.text}"`, `- Compare Eastern and Western research approaches`, `- Synthesize findings across different knowledge systems` ); } return { content: [ { type: "text", text: `Analysis using ${framework} framework:\n\n` + `Requirements:\n${suggestions.join("\n")}\n\n` + `Confidence level: ${validation.confidence}\n\n` + `Suggested cross-references:\n${crossRefPrompts.join("\n")}` }, { type: "text", text: JSON.stringify({ framework, validation, suggestions, crossRefPrompts }) } ], }; } if (name === "validate_sources") { const framework: keyof typeof VALIDATION_FRAMEWORKS = (typeof args.framework === 'string' && args.framework in VALIDATION_FRAMEWORKS) ? args.framework as keyof typeof VALIDATION_FRAMEWORKS : VALIDATION_FRAMEWORK; // Extract sources const sourcePattern = /according to|cited by|reported by|study by|research by|experts|scientists/gi; const sources = []; let match: RegExpExecArray | null; while ((match = sourcePattern.exec(args.text)) !== null) { const context = args.text.substring( Math.max(0, match.index - 30), Math.min(args.text.length, match.index + 70) ); sources.push({ type: "citation", context: context.trim() }); } // Generate validation prompts for each source const validationPrompts = sources.flatMap((source: { type: string; context: string }) => { const basePrompts = [ `- Use Exa MCP server to verify credibility of: "${source.context}"`, `- Use Brave Search to find independent verification: "${source.context}"`, `- Search ArXiv for related technical papers: "${source.context}"`, `- Use Google Scholar MCP server to check academic citations: "${source.context}"`, `- Cross-reference findings between different platforms to establish credibility` ]; if (framework === "empirical" || framework === "pluralistic") { basePrompts.push( `- Compare methodologies and results across different studies`, `- Verify replication status and reproducibility`, `- Cross-validate findings between different research groups` ); } if (framework === "responsible" || framework === "pluralistic") { basePrompts.push( `- Use Exa MCP server to search for community perspectives: "${source.context}"`, `- Compare academic findings with real-world impacts`, `- Cross-reference with local knowledge and experiences` ); } if (framework === "harmonic" || framework === "pluralistic") { basePrompts.push( `- Compare perspectives across different cultural contexts`, `- Synthesize findings from multiple knowledge systems`, `- Identify areas of consensus and divergence` ); } return basePrompts; }); return { content: [ { type: "text", text: `Source validation using ${framework} framework:\n\n` + `Found ${sources.length} sources to validate.\n\n` + `Validation steps:\n${validationPrompts.join("\n")}` }, { type: "text", text: JSON.stringify({ framework, sources, validationPrompts }, null, 2) } ], }; } if (name === "check_manipulation") { const patterns = { emotional: /fear|urgent|must act|limited time|don't wait|before it's too late/i, social: /everyone knows|nobody wants|you don't want to be|don't miss out/i, authority: /experts say|scientists claim|studies show|research proves/i, scarcity: /limited time|exclusive|rare opportunity|don't miss out/i }; const detectedPatterns = Object.entries(patterns) .filter(([_, pattern]) => pattern.test(args.text)) .map(([type]) => type); // Generate validation prompts const validationPrompts = [ `- Use Exa MCP server to search for factual information: "${args.text}"`, `- Use Brave Search for independent fact-checking: "${args.text}"`, `- Search ArXiv for technical analysis: "${args.text}"`, `- Use Google Scholar MCP server to find peer-reviewed research: "${args.text}"`, `- Cross-reference findings across different platforms to establish truth` ]; if (detectedPatterns.includes("authority")) { validationPrompts.push( `- Use Google Scholar MCP server to verify credibility of cited authorities`, `- Cross-reference authority claims with independent research`, `- Compare expert opinions across different fields` ); } if (detectedPatterns.includes("emotional")) { validationPrompts.push( `- Use Exa MCP server to find balanced, non-emotional discussions`, `- Compare emotional appeals with empirical evidence`, `- Cross-validate claims across multiple neutral sources` ); } if (detectedPatterns.includes("social") || detectedPatterns.includes("scarcity")) { validationPrompts.push( `- Verify claims using multiple independent sources`, `- Cross-reference marketing claims with factual data`, `- Compare urgency claims with historical patterns` ); } return { content: [ { type: "text", text: `Manipulation check results:\n\n` + `Detected patterns: ${detectedPatterns.join(", ") || "None"}\n\n` + `Suggested validation:\n${validationPrompts.join("\n")}` }, { type: "text", text: JSON.stringify({ detectedPatterns, validationPrompts }, null, 2) } ], }; } throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } catch (error: unknown) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Error analyzing text: ${(error instanceof Error ? error.message : String(error)) as string}` ); } }); // Start the server const transport = new StdioServerTransport(); await server.connect(transport); console.error("Anti-bullshit MCP server running on stdio");