UNPKG

@answerai/answeragent-mcp

Version:

A lightweight Model Context Protocol (MCP) server for Answer AI chatflow and document store management

206 lines (198 loc) 9.16 kB
import { z } from "zod"; import { ChatflowsService } from "../services/chatflows.js"; const chatflowsService = ChatflowsService.getInstance(); /** * Chatflow Analysis Prompt * * This prompt analyzes a chatflow and provides structured insights * about its configuration, nodes, and potential improvements. */ export const analyzeChatflowPrompt = { name: "analyze_chatflow", description: "Analyzes a chatflow and provides structured insights about its configuration and nodes", schema: { chatflowId: z.string().describe("The ID of the chatflow to analyze"), focusAreas: z .array(z.string()) .optional() .default([]) .describe("Specific areas to focus on in the analysis (e.g., 'prompts', 'nodes', 'credentials')"), }, handler: async ({ chatflowId, focusAreas = [], }) => { // Fetch the chatflow data const chatflow = await chatflowsService.getChatflow(chatflowId, true); if (!chatflow) { throw new Error(`Chatflow with ID ${chatflowId} not found`); } // Extract key information from the chatflow const { name, description, deployed, isPublic, category, type, parsedFlowData, createdDate, updatedDate, } = chatflow; // Analyze the flow data const nodeAnalysis = []; const credentialAnalysis = []; const promptAnalysis = []; if (parsedFlowData) { // Analyze nodes for (const node of parsedFlowData.nodes) { nodeAnalysis.push({ id: node.id, type: node.type, label: node.label, description: node.description, category: node.category, hasPrompts: !!node.prompts, hasCredentials: !!node.credential, }); // Analyze prompts within nodes if (node.prompts && (focusAreas.length === 0 || focusAreas.includes("prompts"))) { const { systemMessagePrompt, humanMessagePrompt, agentInstructions } = node.prompts; if (systemMessagePrompt) { promptAnalysis.push({ nodeId: node.id, nodeLabel: node.label, type: "system", content: systemMessagePrompt, length: systemMessagePrompt.length, hasVariables: systemMessagePrompt.includes("{") || systemMessagePrompt.includes("{{"), }); } if (humanMessagePrompt) { promptAnalysis.push({ nodeId: node.id, nodeLabel: node.label, type: "human", content: humanMessagePrompt, length: humanMessagePrompt.length, hasVariables: humanMessagePrompt.includes("{") || humanMessagePrompt.includes("{{"), }); } if (agentInstructions) { promptAnalysis.push({ nodeId: node.id, nodeLabel: node.label, type: "agent", content: agentInstructions, length: agentInstructions.length, hasVariables: agentInstructions.includes("{") || agentInstructions.includes("{{"), }); } } } // Analyze credentials for (const credentialId of parsedFlowData.credentialIds) { credentialAnalysis.push({ id: credentialId, usedByNodes: parsedFlowData.nodes.filter(n => n.credential === credentialId).length, }); } } // Generate insights const insights = []; // Node insights if (nodeAnalysis.length > 0) { insights.push(`Flow contains ${nodeAnalysis.length} nodes`); const nodeTypes = [...new Set(nodeAnalysis.map(n => n.type))]; insights.push(`Node types: ${nodeTypes.join(", ")}`); const nodesWithPrompts = nodeAnalysis.filter(n => n.hasPrompts).length; if (nodesWithPrompts > 0) { insights.push(`${nodesWithPrompts} nodes have custom prompts`); } const nodesWithCredentials = nodeAnalysis.filter(n => n.hasCredentials).length; if (nodesWithCredentials > 0) { insights.push(`${nodesWithCredentials} nodes use credentials`); } } // Prompt insights if (promptAnalysis.length > 0) { const avgPromptLength = promptAnalysis.reduce((sum, p) => sum + p.length, 0) / promptAnalysis.length; insights.push(`Average prompt length: ${Math.round(avgPromptLength)} characters`); const promptsWithVariables = promptAnalysis.filter(p => p.hasVariables).length; if (promptsWithVariables > 0) { insights.push(`${promptsWithVariables} prompts use variables`); } } // Credential insights if (credentialAnalysis.length > 0) { insights.push(`Uses ${credentialAnalysis.length} different credentials`); } // Generate recommendations const recommendations = []; if (nodeAnalysis.length > 10) { recommendations.push("Consider breaking down complex flows into smaller, more manageable components"); } if (promptAnalysis.length > 0) { const longPrompts = promptAnalysis.filter(p => p.length > 1000); if (longPrompts.length > 0) { recommendations.push(`${longPrompts.length} prompts are quite long (>1000 chars) - consider breaking them down`); } } if (!deployed && isPublic) { recommendations.push("Chatflow is public but not deployed - consider deploying or making it private"); } if (!description) { recommendations.push("Add a description to help users understand the chatflow's purpose"); } // Filter analysis based on focus areas let filteredNodeAnalysis = nodeAnalysis; let filteredPromptAnalysis = promptAnalysis; let filteredCredentialAnalysis = credentialAnalysis; if (focusAreas.length > 0) { if (!focusAreas.includes("nodes")) { filteredNodeAnalysis = []; } if (!focusAreas.includes("prompts")) { filteredPromptAnalysis = []; } if (!focusAreas.includes("credentials")) { filteredCredentialAnalysis = []; } } // Construct the analysis response return { messages: [ { role: "assistant", content: { type: "text", text: `# Chatflow Analysis: ${name} ## Overview - **Name**: ${name} - **Description**: ${description || "No description provided"} - **Status**: ${deployed ? "Deployed" : "Not deployed"} - **Visibility**: ${isPublic ? "Public" : "Private"} - **Category**: ${category || "Uncategorized"} - **Type**: ${type || "Unknown"} - **Created**: ${createdDate ? new Date(createdDate).toLocaleDateString() : "Unknown"} - **Updated**: ${updatedDate ? new Date(updatedDate).toLocaleDateString() : "Unknown"} ## Key Insights ${insights.map(i => `- ${i}`).join("\n")} ${filteredNodeAnalysis.length > 0 ? `## Node Analysis ${filteredNodeAnalysis.map(node => ` ### ${node.label} (${node.type}) - **ID**: ${node.id} - **Description**: ${node.description || "No description"} - **Category**: ${node.category || "Uncategorized"} - **Has Prompts**: ${node.hasPrompts ? "Yes" : "No"} - **Uses Credentials**: ${node.hasCredentials ? "Yes" : "No"} `).join("\n")}` : ""} ${filteredPromptAnalysis.length > 0 ? `## Prompt Analysis ${filteredPromptAnalysis.map(prompt => ` ### ${prompt.nodeLabel} - ${prompt.type.toUpperCase()} Prompt - **Length**: ${prompt.length} characters - **Uses Variables**: ${prompt.hasVariables ? "Yes" : "No"} - **Content Preview**: ${prompt.content.substring(0, 100)}${prompt.content.length > 100 ? "..." : ""} `).join("\n")}` : ""} ${filteredCredentialAnalysis.length > 0 ? `## Credential Analysis ${filteredCredentialAnalysis.map(cred => ` ### Credential: ${cred.id} - **Used by**: ${cred.usedByNodes} node(s) `).join("\n")}` : ""} ## Recommendations ${recommendations.map(r => `- ${r}`).join("\n")} ## Summary This chatflow ${deployed ? "is deployed and ready for use" : "is not yet deployed"}. ${recommendations.length > 0 ? `Consider implementing the ${recommendations.length} recommendations above to improve the flow.` : "The flow appears to be well-configured."}`, }, }, ], }; }, };