@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
JavaScript
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."}`,
},
},
],
};
},
};