Skip to main content
Glama
agentic.ts21.8 kB
import { z } from "zod"; /** * Agentic & Synaptic Tools - Higher-order cognitive functions * Simulates advanced reasoning, association, and autonomous behavior. */ // ============================================ // Decision Matrix Tool // ============================================ export const decisionMatrixSchema = { name: "decision_matrix", description: "Evaluates options using weighted criteria to make data-driven decisions", inputSchema: z.object({ problem: z.string().describe("The decision to be made"), options: z.array(z.string()).describe("List of available options"), criteria: z .array( z.object({ name: z.string(), weight: z .number() .min(0) .max(10) .describe("Importance weight (1-10)"), }), ) .describe("Evaluation criteria"), evaluations: z .array( z.object({ optionIndex: z.number(), scores: z .array(z.number().min(0).max(10)) .describe("Score for each criteria (in order)"), }), ) .optional() .describe("Optional pre-filled scores"), }), }; export function decisionMatrixHandler(args: { problem: string; options: string[]; criteria: Array<{ name: string; weight: number }>; evaluations?: Array<{ optionIndex: number; scores: number[] }>; }) { const { problem, options, criteria, evaluations } = args; // If no evaluations provided, return the template structure to fill if (!evaluations) { return { content: [ { type: "text", text: `# Decision Matrix Setup for: ${problem}\n\nPlease analyze the options and provide scores (0-10) for each criteria.\n\nCritera:\n${criteria.map((c, i) => `${i + 1}. ${c.name} (Weight: ${c.weight})`).join("\n")}\n\nOptions:\n${options.map((o, i) => `${i + 1}. ${o}`).join("\n")}`, }, ], }; } // Calculate weighted scores const results = evaluations.map((evalItem) => { const option = options[evalItem.optionIndex]; let totalScore = 0; let weightedScore = 0; let maxPossibleWeighted = 0; evalItem.scores.forEach((score, i) => { const weight = criteria[i].weight; totalScore += score; weightedScore += score * weight; maxPossibleWeighted += 10 * weight; }); const percent = Math.round((weightedScore / maxPossibleWeighted) * 100); return { option, rawResults: evalItem.scores .map((s, i) => `${criteria[i].name}: ${s}`) .join(", "), totalScore, weightedScore, percent, }; }); results.sort((a, b) => b.weightedScore - a.weightedScore); const winner = results[0]; const runnerUp = results.length > 1 ? results[1] : null; // Sensitivity Analysis let sensitivityNote = ""; if (runnerUp) { const diff = winner.weightedScore - runnerUp.weightedScore; const percentDiff = (diff / winner.weightedScore) * 100; if (percentDiff < 5) { sensitivityNote = `**Close Call**: The winner is only ${percentDiff.toFixed(1)}% ahead of ${runnerUp.option}. a slight change in weights could flip the result.`; } else { sensitivityNote = `**Clear Winner**: The winner is ${percentDiff.toFixed(1)}% ahead, indicating a robust decision.`; } } return { content: [ { type: "text", text: `# Decision Analysis: ${problem} ## 🏆 Winner: **${winner.option}** (${winner.percent}%) ## Sensitivity Analysis ${sensitivityNote} ## Details ${results .map( (r, i) => `### ${i + 1}. ${r.option} - **Score**: ${r.weightedScore} / ${r.percent}% - Breakdown: ${r.rawResults}`, ) .join("\n\n")}`, }, ], }; } // ============================================ // Consequence Analysis Tool // ============================================ export const consequenceAnalysisSchema = { name: "consequence_analysis", description: "Analyzes 2nd and 3rd order consequences of a decision or action (Ripple Effect)", inputSchema: z.object({ action: z.string().describe("The action or change being proposed"), stakeholders: z .array(z.string()) .describe("Who/what is affected (Users, DB, specific modules)"), timeframes: z .array(z.enum(["immediate", "short_term", "medium_term", "long_term"])) .describe("Time horizons to analyze"), }), }; export function consequenceAnalysisHandler(args: { action: string; stakeholders: string[]; timeframes: string[]; }) { const { action, stakeholders, timeframes } = args; // In a real agent, this would query a knowledge base. // Here we provide a structured template for the LLM to fill or for the user to reflect on. return { content: [ { type: "text", text: `# Consequence Analysis (Ripple Effect)\n**Action**: ${action}\n\n## Impact Matrix\n\n${timeframes .map((time) => { return `### ⏱️ ${time.replace("_", " ").toUpperCase()}\n${stakeholders.map((s) => `- **${s}**: [Analyze impact on ${s}]`).join("\n")}`; }) .join( "\n\n", )}\n\n## ⚠️ Risks & Mitigations\n- [Identify major risks]\n- [Propose mitigations]`, }, ], }; } // ============================================ // Concept Association (Synaptic) Tool // ============================================ export const conceptAssociationSchema = { name: "concept_association", description: "Links concepts to build a knowledge graph and identify hidden connections", inputSchema: z.object({ concept: z.string().describe("The central concept to analyze"), domains: z .array(z.string()) .optional() .describe( "Domains to look for associations in (e.g. 'security', 'performance', 'business')", ), depth: z .enum(["shallow", "deep", "abstract"]) .optional() .default("shallow"), }), }; export function conceptAssociationHandler(args: { concept: string; domains?: string[]; depth?: string; }) { const { concept, domains = ["general"], depth = "shallow" } = args; const prompts = { shallow: "Direct dependencies, immediate parents/children, explicit references.", deep: "Indirect dependencies, shared resources, race conditions, architectural patterns.", abstract: "Metaphorical similarities, design philosophy, structural parallels, anti-patterns.", }; return { content: [ { type: "text", text: `# Synaptic Association: ${concept}\n\n**Mode**: ${depth} (${prompts[depth as keyof typeof prompts]})\n**Domains**: ${domains.join(", ")}\n\n## Associations Map\n\n1. **Direct Links**\n - [Link 1]\n - [Link 2]\n\n2. **Conceptual Parallels**\n - [Concept A] is like [Concept B] because...\n\n3. **Hidden Implications**\n - If ${concept} changes, then...\n\n4. **Pattern Recognition**\n - This resembles the [Pattern Name] pattern.`, }, ], }; } // ============================================ // Derive Patterns Tool // ============================================ export const derivePatternsSchema = { name: "derive_patterns", description: "Identifies repeating code or architectural patterns to suggest refactoring or standardization", inputSchema: z.object({ sourcePaths: z .array(z.string()) .describe("File paths or components to analyze"), focus: z .enum([ "code_duplication", "architectural_style", "naming_conventions", "error_handling", ]) .describe("Aspect to analyze"), }), }; export const derivePatternsHandler = async (args: { sourcePaths: string[]; focus: string; }) => { const { sourcePaths, focus } = args; const fs = require("fs"); const path = require("path"); let findings: string[] = []; let analyzedCount = 0; for (const filePath of sourcePaths) { try { if (fs.existsSync(filePath)) { const content = fs.readFileSync(filePath, "utf-8"); analyzedCount++; const lines = content.split("\n"); if (focus === "code_duplication") { // Simple heuristic: check for identical blocks of 5+ lines (very naive) // Better: check for "TODO" or specific anti-patterns if (content.includes("TODO")) { findings.push( `- ${path.basename(filePath)}: Contains TODOs, potential technical debt.`, ); } if (lines.length > 300) { findings.push( `- ${path.basename(filePath)}: Large file (${lines.length} lines), potential monolith.`, ); } } else if (focus === "error_handling") { const tryCatchCount = (content.match(/try\s*{/g) || []).length; findings.push( `- ${path.basename(filePath)}: Found ${tryCatchCount} try-catch blocks.`, ); } else if (focus === "architectural_style") { if (content.includes("class ")) { findings.push( `- ${path.basename(filePath)}: Uses OOP (Class definitions found).`, ); } else if (content.includes("function ")) { findings.push( `- ${path.basename(filePath)}: Uses Functional patterns.`, ); } } else if (focus === "naming_conventions") { // Basic checks for camelCase vs snake_case const hasSnake = /const [a-z]+_[a-z]+/.test(content); const hasCamel = /const [a-z]+[A-Z][a-z]+/.test(content); if (hasSnake && hasCamel) { findings.push( `- ${path.basename(filePath)}: Mixed naming conventions detected (snake_case and camelCase).`, ); } else if (hasSnake) { findings.push( `- ${path.basename(filePath)}: Predominantly snake_case.`, ); } else { findings.push( `- ${path.basename(filePath)}: Predominantly camelCase (or consistent).`, ); } } } else { findings.push(`- ${path.basename(filePath)}: File not found.`); } } catch (error) { findings.push(`- ${path.basename(filePath)}: Error reading file.`); } } return { content: [ { type: "text", text: `# Pattern Recognition: ${focus}\n\nAnalyzing: ${analyzedCount} sources\n\n## Observed Patterns\n\n${findings.length > 0 ? findings.join("\n") : "No specific patterns detected with current heuristics."}\n\n## Recommendations\n\n- Review larger files for decomposition.\n- Standardize error handling where inconsistent.`, }, ], }; }; // ============================================ // Research Synthesis Tool // ============================================ export const researchSynthesisSchema = { name: "research_synthesis", description: "Aggregates and synthesizes information from multiple sources to answer a complex question", inputSchema: z.object({ topic: z.string().describe("The topic to research"), sources: z .array(z.string()) .describe("List of provided information/code snippets"), goal: z.string().describe("The specific question or output needed"), }), }; export function researchSynthesisHandler(args: { topic: string; sources: string[]; goal: string; }) { const { topic, sources, goal } = args; // Simple frequency analysis const allText = sources.join(" ").toLowerCase(); const words = allText.match(/\b\w+\b/g) || []; const wordCounts: Record<string, number> = {}; const stopWords = new Set([ "the", "and", "a", "to", "of", "in", "is", "for", "on", "with", "as", "this", "that", "it", ]); words.forEach((w) => { if (!stopWords.has(w) && w.length > 3) { wordCounts[w] = (wordCounts[w] || 0) + 1; } }); const topKeywords = Object.entries(wordCounts) .sort((a, b) => b[1] - a[1]) .slice(0, 5) .map(([w, c]) => `${w} (${c})`); const summaryPoints = sources.map((s, i) => { const firstSentence = s.split(".")[0]; return `${i + 1}. ${firstSentence}.`; }); return { content: [ { type: "text", text: `# Research Synthesis: ${topic}\n\n## Goal\n${goal}\n\n## Synthesized Highlights\n\n**Common Keywords**: ${topKeywords.join(", ")}\n\n## Key Findings (Extracted)\n\n${summaryPoints.map((p) => `- ${p}`).join("\n")}\n\n## Conclusion\nBased on the analysis of ${sources.length} sources, the content revolves around ${topKeywords .slice(0, 3) .map((k) => k.split(" ")[0]) .join(", ")}.`, }, ], }; } // ============================================ // Six Thinking Hats Tool // ============================================ export const sixThinkingHatsSchema = { name: "six_thinking_hats", description: "Runs a meaningful parallel thinking session using the Six Thinking Hats method to explore a problem from all angles.", inputSchema: z.object({ problem: z.string().describe("The problem or decision to analyze"), participants: z .array(z.string()) .optional() .describe("Optional stakeholders to assign per hat"), }), }; export const sixThinkingHatsHandler = (args: { problem: string }) => { const { problem } = args; const context = problem.toLowerCase(); const hats = [ { color: "⚪ White Hat", focus: "Facts & Information", questions: [ "What do we know?", "What information is missing?", "What data do we need?", context.includes("performance") ? "What are the current metrics?" : "What are the verified facts?", ], }, { color: "🔴 Red Hat", focus: "Feelings & Intuition", questions: [ "What is my gut reaction?", "What are the emotional risks?", "How will users feel?", context.includes("ui") ? "Is the design frustrating?" : "Are we excited about this?", ], }, { color: "⚫ Black Hat", focus: "Caution & Risks", questions: [ "What could go wrong?", "What are the weaknesses?", "Why might this fail?", context.includes("security") ? "Where are the vulnerabilities?" : "What is the worst case scenario?", ], }, { color: "🟡 Yellow Hat", focus: "Benefits & Value", questions: [ "What are the positives?", "What is the value add?", "Who benefits?", context.includes("refactor") ? "How does this improve maintainability?" : "What is the ROI?", ], }, { color: "🟢 Green Hat", focus: "Creativity & Alternatives", questions: [ "Are there other ways?", "What if we break the rules?", "Can we combine ideas?", context.includes("deadline") ? "Is there a faster shortcut?" : "What is the radical alternative?", ], }, { color: "🔵 Blue Hat", focus: "Process & Control", questions: [ "What is the next step?", "How do we summarize?", "What hat do we need next?", ], }, ]; const analysis = hats .map( (h) => `### ${h.color} (${h.focus}) *Guiding Questions:* ${h.questions.map((q) => `- ${q}`).join("\n")} **Analysis**: [Insert thoughts here based on ${h.focus.toLowerCase()}] `, ) .join("\n\n---\n\n"); return { content: [ { type: "text", text: `# Six Thinking Hats Session: ${problem}\n\n${analysis}\n\n## Synthesis\n[Summarize the holistic view here]`, }, ], }; }; // ============================================ // Logical Fallacy Check Tool // ============================================ export const logicalFallacyCheckSchema = { name: "logical_fallacy_check", description: "Analyzes an argument or text for common logical fallacies.", inputSchema: z.object({ text: z.string().describe("The argument or text to analyze"), }), }; export const logicalFallacyCheckHandler = (args: { text: string }) => { const { text } = args; const lowerText = text.toLowerCase(); const fallacies = [ { name: "Ad Hominem", description: "Attacking the person instead of the argument", keywords: ["idiot", "stupid", "ignorant", "you are", "personally"], }, { name: "Straw Man", description: "Misrepresenting the argument to make it easier to attack", keywords: ["so you're saying", "twist", "never said", "misinterpret"], }, { name: "Appeal to Authority", description: "Assuming something is true because an authority said so", keywords: ["expert says", "doctor says", "because he is", "authority"], }, { name: "False Dichotomy", description: "Presenting only two options when more exist", keywords: ["either", "or", "only two", "black and white"], }, { name: "Confirmation Bias", description: "Favoring information that confirms existing beliefs", keywords: ["always", "knew it", "proves my point"], }, { name: "Sunk Cost Fallacy", description: "Continuing because of past investment", keywords: ["invested", "spent so much", "too late"], }, { name: "Circular Reasoning", description: "The conclusion is included in the premise", keywords: ["because", "therefore", "is true because"], }, ]; const detected = fallacies.filter((f) => f.keywords.some((k) => lowerText.includes(k)), ); return { content: [ { type: "text", text: `# Logical Fallacy Check\n\n**Input Text**: "${text}"\n\n## Potential Fallacies Detected\n\n${ detected.length > 0 ? detected .map( (f) => `- **${f.name}**: ${f.description} (Trigger: keywords found)`, ) .join("\n") : "No specific fallacies detected based on simple heuristics." }\n\n## Automated Checklist\n\n${fallacies .map( (f) => `- [${detected.includes(f) ? "x" : " "}] **${f.name}**: ${f.description}`, ) .join( "\n", )}\n\n## Findings\n[Identify potential fallacies found in the text]\n\n## Recommendation\n[How to strengthen the argument]`, }, ], }; }; // ============================================ // Causal Loop Diagram Tool // ============================================ export const causalLoopDiagramSchema = { name: "causal_loop_diagram", description: "Visualizes a system using a Causal Loop Diagram (CLD) description to identify feedback loops.", inputSchema: z.object({ params: z .array(z.string()) .describe("List of variables/parameters in the system"), relationships: z .array( z.object({ from: z.string(), to: z.string(), type: z .enum(["positive", "negative"]) .describe( "Positive (+) means same direction, Negative (-) means opposite direction", ), description: z.string().optional(), }), ) .describe("Causal links between parameters"), }), }; export const causalLoopDiagramHandler = (args: { params: string[]; relationships: Array<{ from: string; to: string; type: "positive" | "negative"; description?: string; }>; }) => { const { params, relationships } = args; // Validation const errors: string[] = []; const nodes = new Set(params); // Check for unknown nodes in relationships relationships.forEach((r) => { if (!nodes.has(r.from)) errors.push(`Unknown source node: ${r.from}`); if (!nodes.has(r.to)) errors.push(`Unknown target node: ${r.to}`); if (r.from === r.to) errors.push( `Self-loop detected: ${r.from} -> ${r.to} (CLDs typically involve loops of 2+ variables)`, ); }); if (errors.length > 0) { return { content: [ { type: "text", text: `# Causal Loop Diagram Error\n\n## Issues Found\n${errors.map((e) => `- ${e}`).join("\n")}\n\nPlease correct the parameters or relationships.`, }, ], isError: true, }; } const mermaidParams = params .map((p) => { // Sanitize for mermaid id (remove spaces, special chars) const id = p.replace(/[^a-zA-Z0-9]/g, ""); return `${id}["${p}"]`; }) .join("\n "); const mermaidEdges = relationships .map((r) => { const fromId = r.from.replace(/[^a-zA-Z0-9]/g, ""); const toId = r.to.replace(/[^a-zA-Z0-9]/g, ""); const label = r.type === "positive" ? "+" : "-"; return `${fromId} -->|"${label}"| ${toId}`; }) .join("\n "); const diagram = `graph TD\n ${mermaidParams}\n ${mermaidEdges}`; return { content: [ { type: "text", text: `# Causal Loop Diagram\n\n## Visual\n\`\`\`mermaid\n${diagram}\n\`\`\`\n\n## Loop Analysis\n- **Reinforcing Loops (R)**: Creating exponential growth/collapse?\n- **Balancing Loops (B)**: Creating stability or resistance?\n\n## Insights\n[Analyze the system behavior based on loops]`, }, ], }; }; // Export all export const agenticTools = { decisionMatrixSchema, decisionMatrixHandler, consequenceAnalysisSchema, consequenceAnalysisHandler, conceptAssociationSchema, conceptAssociationHandler, derivePatternsSchema, derivePatternsHandler, researchSynthesisSchema, researchSynthesisHandler, sixThinkingHatsSchema, sixThinkingHatsHandler, logicalFallacyCheckSchema, logicalFallacyCheckHandler, causalLoopDiagramSchema, causalLoopDiagramHandler, };

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/millsydotdev/Code-MCP'

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