ai-expert-workflow-mcp
Version:
Enhanced AI Expert Workflow MCP Server with structured conversation flow, topic tracking, and optional Task Master integration
115 lines (114 loc) • 4.79 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.callAI = callAI;
exports.consultWithExpert = consultWithExpert;
exports.generateExpertDocument = generateExpertDocument;
exports.saveForTaskMaster = saveForTaskMaster;
const dotenv_1 = __importDefault(require("dotenv"));
const experts_1 = require("../experts");
const promises_1 = __importDefault(require("fs/promises"));
const path_1 = __importDefault(require("path"));
const node_fetch_1 = __importDefault(require("node-fetch"));
dotenv_1.default.config();
// Get OpenRouter API key
function getApiKey() {
// Force reload of .env file
dotenv_1.default.config({ path: '.env' });
const apiKey = process.env.OPENROUTER_API_KEY || '';
console.log('API Key:', apiKey);
if (!apiKey) {
console.error('Error: OPENROUTER_API_KEY is required but not set in environment variables');
process.exit(1);
}
return apiKey;
}
// Generic function to call AI with any prompt and context
async function callAI(systemPrompt, context, userInput) {
try {
const apiKey = getApiKey();
const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'HTTP-Referer': 'https://github.com/bacoco/ai-expert-workflow-mcp',
'X-Title': 'AI Expert Workflow MCP'
};
const response = await (0, node_fetch_1.default)('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers,
body: JSON.stringify({
model: process.env.OPENROUTER_MODEL || 'openai/gpt-3.5-turbo',
max_tokens: parseInt(process.env.MAX_TOKENS || '4000', 10),
temperature: parseFloat(process.env.TEMPERATURE || '0.7'),
messages: [
{ role: 'system', content: systemPrompt },
...(context ? [{ role: 'user', content: context }] : []),
{ role: 'user', content: userInput }
]
})
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`OpenRouter API error: ${response.status} ${JSON.stringify(errorData)}`);
}
const data = await response.json();
// Get the response text
const responseText = data.choices[0].message.content || '';
return responseText;
}
catch (error) {
console.error('Error calling OpenRouter API:', error);
throw error;
}
}
async function consultWithExpert(role, userInput) {
const expert = experts_1.experts[role];
if (!expert) {
throw new Error(`Unknown expert role: ${role}`);
}
return callAI(expert.systemPrompt, '', userInput);
}
async function generateExpertDocument(role, template, userInput) {
const expert = experts_1.experts[role];
if (!expert) {
throw new Error(`Unknown expert role: ${role}`);
}
const enhancedPrompt = `${expert.systemPrompt}\n\nPlease use the following template structure for your response:\n\n${template}\n\nBased on the user's input, create a complete, well-structured document. Format your response using Markdown with clear sections and subsections.`;
// Use higher max tokens and lower temperature for document generation
const originalMaxTokens = process.env.MAX_TOKENS;
const originalTemperature = process.env.TEMPERATURE;
try {
process.env.MAX_TOKENS = '8000';
process.env.TEMPERATURE = '0.5';
return await callAI(enhancedPrompt, '', userInput);
}
finally {
// Restore original values
process.env.MAX_TOKENS = originalMaxTokens;
process.env.TEMPERATURE = originalTemperature;
}
}
// Special function to save PRD in the format Task Master expects
async function saveForTaskMaster(content, isInitial = false) {
try {
// Create scripts directory if it doesn't exist
const scriptsDir = path_1.default.join(process.cwd(), 'scripts');
try {
await promises_1.default.mkdir(scriptsDir, { recursive: true });
}
catch (err) {
// Directory might already exist
}
// Determine the filename based on whether this is the initial PRD or the final one
const filename = isInitial ? 'initial_prd.txt' : 'prd.txt';
const filePath = path_1.default.join(scriptsDir, filename);
await promises_1.default.writeFile(filePath, content, 'utf8');
return filePath;
}
catch (error) {
console.error('Error saving for Task Master:', error);
throw error;
}
}