@answerai/answeragent-mcp 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,254 @@
1
+ # @answerai/answeragent-mcp
2
+
3
+ [![npm version](https://badge.fury.io/js/@answerai%2Fansweragent-mcp.svg)](https://badge.fury.io/js/@answerai%2Fansweragent-mcp)
4
+
5
+ A lightweight Model Context Protocol (MCP) server for Answer AI chatflow and document store management. This server exposes Answer AI's powerful features through standardized MCP tools and prompts, allowing you to manage chatflows, document stores, assistants, and more directly from your MCP-compatible AI clients.
6
+
7
+ ## Installation
8
+
9
+ Install globally via npm:
10
+
11
+ ```bash
12
+ npm install -g @answerai/answeragent-mcp
13
+ ```
14
+
15
+ Or use with npx (no installation required):
16
+
17
+ ```bash
18
+ npx @answerai/answeragent-mcp
19
+ ```
20
+
21
+ ## Quick Start
22
+
23
+ 1. **Get Your Answer AI Credentials**:
24
+ - API Base URL (e.g., `https://your-instance.studio.theanswer.ai`)
25
+ - API Token (JWT token from your Answer AI instance)
26
+
27
+ 2. **Test the Server**:
28
+ ```bash
29
+ npx @modelcontextprotocol/inspector @answerai/answeragent-mcp
30
+ ```
31
+
32
+ ## Client Configuration
33
+
34
+ ### Cursor IDE
35
+
36
+ Add this configuration to your `~/.cursor/mcp.json` file:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "answerai-mcp": {
42
+ "command": "node",
43
+ "args": [
44
+ "/path/to/your/project/dist/index.js"
45
+ ],
46
+ "env": {
47
+ "ANSWERAGENT_AI_API_BASE_URL": "https://your-instance.studio.theanswer.ai",
48
+ "ANSWERAGENT_AI_API_TOKEN": "your-jwt-token-here"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ **For NPM installed version:**
56
+ ```json
57
+ {
58
+ "mcpServers": {
59
+ "answerai-mcp": {
60
+ "command": "npx",
61
+ "args": ["@answerai/answeragent-mcp"],
62
+ "env": {
63
+ "ANSWERAGENT_AI_API_BASE_URL": "https://your-instance.studio.theanswer.ai",
64
+ "ANSWERAGENT_AI_API_TOKEN": "your-jwt-token-here"
65
+ }
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ ### Claude Desktop
72
+
73
+ Add this to your Claude Desktop MCP settings file:
74
+
75
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
76
+ **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
77
+
78
+ ```json
79
+ {
80
+ "mcpServers": {
81
+ "answerai": {
82
+ "command": "npx",
83
+ "args": ["@answerai/answeragent-mcp"],
84
+ "env": {
85
+ "ANSWERAGENT_AI_API_BASE_URL": "https://your-instance.studio.theanswer.ai",
86
+ "ANSWERAGENT_AI_API_TOKEN": "your-jwt-token-here"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### Other MCP Clients (Cline, etc.)
94
+
95
+ Most MCP clients follow the same pattern:
96
+
97
+ ```json
98
+ {
99
+ "command": "npx",
100
+ "args": ["@answerai/answeragent-mcp"],
101
+ "env": {
102
+ "ANSWERAGENT_AI_API_BASE_URL": "https://your-instance.studio.theanswer.ai",
103
+ "ANSWERAGENT_AI_API_TOKEN": "your-jwt-token-here"
104
+ }
105
+ }
106
+ ```
107
+
108
+ ## Configuration
109
+
110
+ The server requires two environment variables:
111
+
112
+ - `ANSWERAGENT_AI_API_BASE_URL`: Your Answer AI instance base URL (without `/api/v1`)
113
+ - `ANSWERAGENT_AI_API_TOKEN`: Your Answer AI JWT authentication token
114
+
115
+ **Important**:
116
+ - Don't include `/api/v1` in the base URL - the server adds this automatically
117
+ - Make sure you're using a JWT token, not an API key
118
+ - The token must have appropriate permissions for the operations you want to perform
119
+
120
+ ## Available Tools
121
+
122
+ ### Chatflow Management
123
+ - `create_chatflow` - Create new chatflows
124
+ - `get_chatflow` - Retrieve chatflow details
125
+ - `update_chatflow` - Update existing chatflows
126
+ - `delete_chatflow` - Remove chatflows
127
+ - `list_chatflows` - List all chatflows
128
+
129
+ ### Document Store Management
130
+ - `create_document_store` - Create document stores
131
+ - `get_document_store` - Get store details
132
+ - `delete_document_store` - Remove document stores
133
+ - `list_document_stores` - List all stores
134
+ - `query_vector_store` - Query document stores
135
+ - `upsert_document` - Add/update documents
136
+ - `refresh_document_store` - Refresh store contents
137
+
138
+ ### Assistant Management
139
+ - `create_assistant` - Create AI assistants
140
+ - `get_assistant` - Get assistant details
141
+ - `update_assistant` - Update assistants
142
+ - `delete_assistant` - Remove assistants
143
+ - `list_assistants` - List all assistants
144
+
145
+ ### Tool Management
146
+ - `create_tool` - Create custom tools
147
+ - `get_tool` - Get tool details
148
+ - `update_tool` - Update tools
149
+ - `delete_tool` - Remove tools
150
+ - `list_tools` - List all tools
151
+
152
+ ### Document Loader Management
153
+ - `get_loader_chunks` - Get document chunks
154
+ - `update_loader_chunk` - Update chunks
155
+ - `delete_loader_chunk` - Remove chunks
156
+ - `delete_loader` - Remove loaders
157
+
158
+ ## Intelligent Prompts
159
+
160
+ The server provides AI-powered prompts for advanced analysis and management:
161
+
162
+ ### `analyze_chatflow`
163
+ Analyzes chatflow configuration and provides optimization recommendations.
164
+
165
+ **Arguments:**
166
+ - `chatflowId` (required): The chatflow ID to analyze
167
+ - `focusAreas` (optional): Array of specific areas to focus on
168
+
169
+ ### `analyze_document_store`
170
+ Analyzes document store configuration, loaders, and usage patterns.
171
+
172
+ **Arguments:**
173
+ - `documentStoreId` (required): The document store ID to analyze
174
+ - `focusAreas` (optional): Array of specific areas to focus on
175
+
176
+ ### `manage_document_store`
177
+ Provides step-by-step guidance for document store operations.
178
+
179
+ **Arguments:**
180
+ - `action` (required): One of "setup", "optimize", "troubleshoot", "migrate"
181
+ - `documentStoreId` (optional): Target document store ID
182
+ - `context` (optional): Additional context for the operation
183
+
184
+ ## Usage Examples
185
+
186
+ ### With Cursor IDE
187
+
188
+ After configuring in Cursor, you can use natural language commands:
189
+
190
+ 1. **List your chatflows**:
191
+ > "Show me all my Answer AI chatflows"
192
+
193
+ 2. **Analyze a specific chatflow**:
194
+ > "Analyze the 'RDS Call Analysis' chatflow and suggest optimizations"
195
+
196
+ 3. **Create a document store**:
197
+ > "Create a new document store called 'Customer Support KB' for storing help articles"
198
+
199
+ 4. **Query documents**:
200
+ > "Search my 'Contracts' document store for information about payment terms"
201
+
202
+ ### With Claude Desktop
203
+
204
+ After adding to your Claude Desktop configuration:
205
+
206
+ 1. **Analyze a chatflow**:
207
+ > "Please analyze my chatflow with ID 'df23d39c-a25b-4842-8997-dce3afed88f4' and focus on performance optimization"
208
+
209
+ 2. **Document store management**:
210
+ > "Help me troubleshoot my document store that's not syncing properly"
211
+
212
+ 3. **Assistant management**:
213
+ > "Show me details about my 'Document Reader' assistant and suggest improvements"
214
+
215
+ ### With MCP Inspector
216
+
217
+ Test and explore the server capabilities:
218
+
219
+ ```bash
220
+ npx @modelcontextprotocol/inspector @answerai/answeragent-mcp
221
+ ```
222
+
223
+ ## Troubleshooting
224
+
225
+ ### Common Issues
226
+
227
+ 1. **401 Unauthorized Error**:
228
+ - Check that your JWT token is valid and not expired
229
+ - Ensure you're using a JWT token, not an API key
230
+ - Verify the token has the necessary permissions
231
+
232
+ 2. **Connection Issues**:
233
+ - Confirm your base URL is correct (without `/api/v1`)
234
+ - Check that your Answer AI instance is accessible
235
+ - Verify environment variables are set correctly
236
+
237
+ 3. **Tool Not Found**:
238
+ - Restart your MCP client after configuration changes
239
+ - Check the server logs for any startup errors
240
+ - Verify the package is properly installed
241
+
242
+ ## Requirements
243
+
244
+ - Node.js 18+
245
+ - Valid Answer AI JWT token with appropriate permissions
246
+ - MCP-compatible client (Claude Desktop, Cursor, Cline, etc.)
247
+
248
+ ## Support
249
+
250
+ For issues and feature requests, visit our [GitHub repository](https://github.com/bradtaylor/answerai-mcp).
251
+
252
+ ## License
253
+
254
+ ISC
package/dist/index.js ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import * as prompts from "./prompts/index.js";
6
+ import { getAllTools, handleToolCall } from "./tools/registry.js";
7
+ // Create MCP server
8
+ const server = new Server({
9
+ name: "answerai-mcp",
10
+ version: "1.0.0",
11
+ }, {
12
+ capabilities: {
13
+ tools: {},
14
+ prompts: {},
15
+ },
16
+ });
17
+ // Register tools
18
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
19
+ return { tools: getAllTools() };
20
+ });
21
+ // Register prompts
22
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
23
+ return {
24
+ prompts: [
25
+ {
26
+ name: prompts.analyzeChatflowPrompt.name,
27
+ description: prompts.analyzeChatflowPrompt.description,
28
+ schema: prompts.analyzeChatflowPrompt.schema,
29
+ },
30
+ {
31
+ name: prompts.analyzeDocumentStorePrompt.name,
32
+ description: prompts.analyzeDocumentStorePrompt.description,
33
+ schema: prompts.analyzeDocumentStorePrompt.schema,
34
+ },
35
+ {
36
+ name: prompts.manageDocumentStorePrompt.name,
37
+ description: prompts.manageDocumentStorePrompt.description,
38
+ schema: prompts.manageDocumentStorePrompt.schema,
39
+ },
40
+ ],
41
+ };
42
+ });
43
+ // Handle prompt requests
44
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
45
+ const { name, arguments: args = {} } = request.params;
46
+ try {
47
+ switch (name) {
48
+ case prompts.analyzeChatflowPrompt.name:
49
+ return await prompts.analyzeChatflowPrompt.handler({
50
+ chatflowId: args.chatflowId,
51
+ focusAreas: Array.isArray(args.focusAreas)
52
+ ? args.focusAreas
53
+ : undefined,
54
+ });
55
+ case prompts.analyzeDocumentStorePrompt.name:
56
+ return await prompts.analyzeDocumentStorePrompt.handler({
57
+ documentStoreId: args.documentStoreId,
58
+ focusAreas: Array.isArray(args.focusAreas)
59
+ ? args.focusAreas
60
+ : undefined,
61
+ });
62
+ case prompts.manageDocumentStorePrompt.name:
63
+ return await prompts.manageDocumentStorePrompt.handler({
64
+ action: args.action,
65
+ documentStoreId: args.documentStoreId,
66
+ context: args.context,
67
+ });
68
+ default:
69
+ throw new Error(`Unknown prompt: ${name}`);
70
+ }
71
+ }
72
+ catch (error) {
73
+ const err = error;
74
+ throw new Error(`Prompt error: ${err.message || "An unexpected error occurred"} ${err.statusCode ? `(Status: ${err.statusCode})` : ""}`);
75
+ }
76
+ });
77
+ // Handle tool calls
78
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
79
+ const { name, arguments: args = {} } = request.params;
80
+ try {
81
+ const result = (await handleToolCall(name, args));
82
+ return {
83
+ _meta: {},
84
+ content: result.content,
85
+ };
86
+ }
87
+ catch (error) {
88
+ console.error(`Error executing tool ${name}:`, error);
89
+ throw error;
90
+ }
91
+ });
92
+ // Start the server
93
+ async function main() {
94
+ const transport = new StdioServerTransport();
95
+ await server.connect(transport);
96
+ }
97
+ main().catch((error) => {
98
+ console.error("Server error:", error);
99
+ process.exit(1);
100
+ });
@@ -0,0 +1,205 @@
1
+ import { z } from "zod";
2
+ import { ChatflowsService } from "../services/chatflows.js";
3
+ const chatflowsService = ChatflowsService.getInstance();
4
+ /**
5
+ * Chatflow Analysis Prompt
6
+ *
7
+ * This prompt analyzes a chatflow and provides structured insights
8
+ * about its configuration, nodes, and potential improvements.
9
+ */
10
+ export const analyzeChatflowPrompt = {
11
+ name: "analyze_chatflow",
12
+ description: "Analyzes a chatflow and provides structured insights about its configuration and nodes",
13
+ schema: {
14
+ chatflowId: z.string().describe("The ID of the chatflow to analyze"),
15
+ focusAreas: z
16
+ .array(z.string())
17
+ .optional()
18
+ .default([])
19
+ .describe("Specific areas to focus on in the analysis (e.g., 'prompts', 'nodes', 'credentials')"),
20
+ },
21
+ handler: async ({ chatflowId, focusAreas = [], }) => {
22
+ // Fetch the chatflow data
23
+ const chatflow = await chatflowsService.getChatflow(chatflowId, true);
24
+ if (!chatflow) {
25
+ throw new Error(`Chatflow with ID ${chatflowId} not found`);
26
+ }
27
+ // Extract key information from the chatflow
28
+ const { name, description, deployed, isPublic, category, type, parsedFlowData, createdDate, updatedDate, } = chatflow;
29
+ // Analyze the flow data
30
+ const nodeAnalysis = [];
31
+ const credentialAnalysis = [];
32
+ const promptAnalysis = [];
33
+ if (parsedFlowData) {
34
+ // Analyze nodes
35
+ for (const node of parsedFlowData.nodes) {
36
+ nodeAnalysis.push({
37
+ id: node.id,
38
+ type: node.type,
39
+ label: node.label,
40
+ description: node.description,
41
+ category: node.category,
42
+ hasPrompts: !!node.prompts,
43
+ hasCredentials: !!node.credential,
44
+ });
45
+ // Analyze prompts within nodes
46
+ if (node.prompts && (focusAreas.length === 0 || focusAreas.includes("prompts"))) {
47
+ const { systemMessagePrompt, humanMessagePrompt, agentInstructions } = node.prompts;
48
+ if (systemMessagePrompt) {
49
+ promptAnalysis.push({
50
+ nodeId: node.id,
51
+ nodeLabel: node.label,
52
+ type: "system",
53
+ content: systemMessagePrompt,
54
+ length: systemMessagePrompt.length,
55
+ hasVariables: systemMessagePrompt.includes("{") || systemMessagePrompt.includes("{{"),
56
+ });
57
+ }
58
+ if (humanMessagePrompt) {
59
+ promptAnalysis.push({
60
+ nodeId: node.id,
61
+ nodeLabel: node.label,
62
+ type: "human",
63
+ content: humanMessagePrompt,
64
+ length: humanMessagePrompt.length,
65
+ hasVariables: humanMessagePrompt.includes("{") || humanMessagePrompt.includes("{{"),
66
+ });
67
+ }
68
+ if (agentInstructions) {
69
+ promptAnalysis.push({
70
+ nodeId: node.id,
71
+ nodeLabel: node.label,
72
+ type: "agent",
73
+ content: agentInstructions,
74
+ length: agentInstructions.length,
75
+ hasVariables: agentInstructions.includes("{") || agentInstructions.includes("{{"),
76
+ });
77
+ }
78
+ }
79
+ }
80
+ // Analyze credentials
81
+ for (const credentialId of parsedFlowData.credentialIds) {
82
+ credentialAnalysis.push({
83
+ id: credentialId,
84
+ usedByNodes: parsedFlowData.nodes.filter(n => n.credential === credentialId).length,
85
+ });
86
+ }
87
+ }
88
+ // Generate insights
89
+ const insights = [];
90
+ // Node insights
91
+ if (nodeAnalysis.length > 0) {
92
+ insights.push(`Flow contains ${nodeAnalysis.length} nodes`);
93
+ const nodeTypes = [...new Set(nodeAnalysis.map(n => n.type))];
94
+ insights.push(`Node types: ${nodeTypes.join(", ")}`);
95
+ const nodesWithPrompts = nodeAnalysis.filter(n => n.hasPrompts).length;
96
+ if (nodesWithPrompts > 0) {
97
+ insights.push(`${nodesWithPrompts} nodes have custom prompts`);
98
+ }
99
+ const nodesWithCredentials = nodeAnalysis.filter(n => n.hasCredentials).length;
100
+ if (nodesWithCredentials > 0) {
101
+ insights.push(`${nodesWithCredentials} nodes use credentials`);
102
+ }
103
+ }
104
+ // Prompt insights
105
+ if (promptAnalysis.length > 0) {
106
+ const avgPromptLength = promptAnalysis.reduce((sum, p) => sum + p.length, 0) / promptAnalysis.length;
107
+ insights.push(`Average prompt length: ${Math.round(avgPromptLength)} characters`);
108
+ const promptsWithVariables = promptAnalysis.filter(p => p.hasVariables).length;
109
+ if (promptsWithVariables > 0) {
110
+ insights.push(`${promptsWithVariables} prompts use variables`);
111
+ }
112
+ }
113
+ // Credential insights
114
+ if (credentialAnalysis.length > 0) {
115
+ insights.push(`Uses ${credentialAnalysis.length} different credentials`);
116
+ }
117
+ // Generate recommendations
118
+ const recommendations = [];
119
+ if (nodeAnalysis.length > 10) {
120
+ recommendations.push("Consider breaking down complex flows into smaller, more manageable components");
121
+ }
122
+ if (promptAnalysis.length > 0) {
123
+ const longPrompts = promptAnalysis.filter(p => p.length > 1000);
124
+ if (longPrompts.length > 0) {
125
+ recommendations.push(`${longPrompts.length} prompts are quite long (>1000 chars) - consider breaking them down`);
126
+ }
127
+ }
128
+ if (!deployed && isPublic) {
129
+ recommendations.push("Chatflow is public but not deployed - consider deploying or making it private");
130
+ }
131
+ if (!description) {
132
+ recommendations.push("Add a description to help users understand the chatflow's purpose");
133
+ }
134
+ // Filter analysis based on focus areas
135
+ let filteredNodeAnalysis = nodeAnalysis;
136
+ let filteredPromptAnalysis = promptAnalysis;
137
+ let filteredCredentialAnalysis = credentialAnalysis;
138
+ if (focusAreas.length > 0) {
139
+ if (!focusAreas.includes("nodes")) {
140
+ filteredNodeAnalysis = [];
141
+ }
142
+ if (!focusAreas.includes("prompts")) {
143
+ filteredPromptAnalysis = [];
144
+ }
145
+ if (!focusAreas.includes("credentials")) {
146
+ filteredCredentialAnalysis = [];
147
+ }
148
+ }
149
+ // Construct the analysis response
150
+ return {
151
+ messages: [
152
+ {
153
+ role: "assistant",
154
+ content: {
155
+ type: "text",
156
+ text: `# Chatflow Analysis: ${name}
157
+
158
+ ## Overview
159
+ - **Name**: ${name}
160
+ - **Description**: ${description || "No description provided"}
161
+ - **Status**: ${deployed ? "Deployed" : "Not deployed"}
162
+ - **Visibility**: ${isPublic ? "Public" : "Private"}
163
+ - **Category**: ${category || "Uncategorized"}
164
+ - **Type**: ${type || "Unknown"}
165
+ - **Created**: ${createdDate ? new Date(createdDate).toLocaleDateString() : "Unknown"}
166
+ - **Updated**: ${updatedDate ? new Date(updatedDate).toLocaleDateString() : "Unknown"}
167
+
168
+ ## Key Insights
169
+ ${insights.map(i => `- ${i}`).join("\n")}
170
+
171
+ ${filteredNodeAnalysis.length > 0 ? `## Node Analysis
172
+ ${filteredNodeAnalysis.map(node => `
173
+ ### ${node.label} (${node.type})
174
+ - **ID**: ${node.id}
175
+ - **Description**: ${node.description || "No description"}
176
+ - **Category**: ${node.category || "Uncategorized"}
177
+ - **Has Prompts**: ${node.hasPrompts ? "Yes" : "No"}
178
+ - **Uses Credentials**: ${node.hasCredentials ? "Yes" : "No"}
179
+ `).join("\n")}` : ""}
180
+
181
+ ${filteredPromptAnalysis.length > 0 ? `## Prompt Analysis
182
+ ${filteredPromptAnalysis.map(prompt => `
183
+ ### ${prompt.nodeLabel} - ${prompt.type.toUpperCase()} Prompt
184
+ - **Length**: ${prompt.length} characters
185
+ - **Uses Variables**: ${prompt.hasVariables ? "Yes" : "No"}
186
+ - **Content Preview**: ${prompt.content.substring(0, 100)}${prompt.content.length > 100 ? "..." : ""}
187
+ `).join("\n")}` : ""}
188
+
189
+ ${filteredCredentialAnalysis.length > 0 ? `## Credential Analysis
190
+ ${filteredCredentialAnalysis.map(cred => `
191
+ ### Credential: ${cred.id}
192
+ - **Used by**: ${cred.usedByNodes} node(s)
193
+ `).join("\n")}` : ""}
194
+
195
+ ## Recommendations
196
+ ${recommendations.map(r => `- ${r}`).join("\n")}
197
+
198
+ ## Summary
199
+ 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."}`,
200
+ },
201
+ },
202
+ ],
203
+ };
204
+ },
205
+ };