Skip to main content
Glama

Worksona MCP Server

Official
by worksona
executor.ts•18.6 kB
import { WorksonaAgent, AgentExecutionContext, AgentExecutionResult } from './types'; import { ContextManager } from '../utils/context'; export class AgentExecutor { private executionCount = 0; private executionTimes: number[] = []; constructor(private contextManager: ContextManager) {} async executeAgent( agent: WorksonaAgent, request: string, context: AgentExecutionContext ): Promise<AgentExecutionResult> { const startTime = Date.now(); this.executionCount++; console.error(`šŸŽÆ Executing agent: ${agent.name}`); console.error(`šŸ“ Request: ${request.substring(0, 100)}...`); try { // Build comprehensive execution prompt const prompt = this.buildExecutionPrompt(agent, request, context); // Simulate agent execution (in a real implementation, this would call Claude API) const response = await this.callAgent(prompt, agent, context); // Calculate execution time const executionTime = Date.now() - startTime; this.executionTimes.push(executionTime); // Update memory with execution results await this.updateAgentMemory(agent, request, response, context); const result: AgentExecutionResult = { agentName: agent.name, request, response, metadata: { executionTime, toolsUsed: this.extractToolsUsed(response), suggestedNextAgents: this.suggestFollowupAgents(agent, response), confidence: this.calculateConfidence(agent, request, response), tokens: this.estimateTokens(prompt + response) } }; console.error(`āœ… Agent ${agent.name} completed in ${executionTime}ms`); return result; } catch (error) { console.error(`āŒ Agent ${agent.name} failed:`, error); const executionTime = Date.now() - startTime; return { agentName: agent.name, request, response: `Error executing agent: ${error instanceof Error ? error.message : String(error)}`, metadata: { executionTime, toolsUsed: [], suggestedNextAgents: [], confidence: 0 } }; } } private buildExecutionPrompt( agent: WorksonaAgent, request: string, context: AgentExecutionContext ): string { let prompt = agent.prompt; // Add project context if available if (context.projectContext) { prompt += `\\n\\n## Current Project Context\\n`; prompt += `**Project**: ${context.projectContext.name}\\n`; prompt += `**Type**: ${context.projectContext.type}\\n`; prompt += `**Tech Stack**: ${JSON.stringify(context.projectContext.techStack, null, 2)}\\n`; prompt += `**Current Phase**: ${context.projectContext.currentPhase}\\n`; const goals = context.projectContext.goals || []; prompt += `**Goals**: ${goals.join(', ')}\\n`; if (Object.keys(context.projectContext.standards).length > 0) { prompt += `**Standards**: ${JSON.stringify(context.projectContext.standards, null, 2)}\\n`; } } // Add conversation history context if (context.conversationHistory?.length) { prompt += `\\n\\n## Recent Conversation Context\\n`; context.conversationHistory.slice(-3).forEach((turn, i) => { prompt += `**Turn ${i + 1}**: ${turn.user}\\n`; prompt += `**Response**: ${turn.assistant.substring(0, 200)}...\\n\\n`; }); } // Add relevant memory context const relevantMemory = context.memory.getRelevantMemory(agent.name, request); if (relevantMemory.length) { prompt += `\\n\\n## Relevant Memory Context\\n`; relevantMemory.forEach(memory => { const summary = memory.summary || memory.response.substring(0, 150) + '...'; prompt += `- **${memory.agentName}** (${memory.timestamp.toLocaleDateString()}): ${summary}\\n`; }); } // Add agent capabilities reminder prompt += `\\n\\n## Your Capabilities\\n`; // Safe capability access with fallbacks const primaryCaps = agent.capabilities?.primary || []; const secondaryCaps = agent.capabilities?.secondary || []; const frameworkCaps = agent.capabilities?.frameworks || []; prompt += `**Primary**: ${primaryCaps.join(', ')}\\n`; if (secondaryCaps.length) { prompt += `**Secondary**: ${secondaryCaps.join(', ')}\\n`; } if (frameworkCaps.length) { prompt += `**Frameworks**: ${frameworkCaps.join(', ')}\\n`; } // Add current request prompt += `\\n\\n## Current Request\\n${request}`; // Add available tools const availableTools = context.availableTools || []; prompt += `\\n\\n## Available Tools\\n${availableTools.join(', ')}`; // Add quality expectations if (agent.quality?.enterpriseGrade) { prompt += `\\n\\n## Quality Standards\\n`; prompt += `- Provide enterprise-grade, production-ready solutions\\n`; prompt += `- Follow industry best practices and standards\\n`; prompt += `- Include comprehensive documentation and examples\\n`; if (agent.quality.professionalLevel) { prompt += `- Apply ${agent.quality.professionalLevel}-level expertise\\n`; } } // Add coordination context if (agent.coordination?.worksWellWith?.length) { prompt += `\\n\\n## Coordination Notes\\n`; prompt += `Consider how your work might integrate with: ${agent.coordination.worksWellWith.join(', ')}\\n`; } return prompt; } private async callAgent( prompt: string, agent: WorksonaAgent, context: AgentExecutionContext ): Promise<string> { // When running inside Claude Desktop (MCP environment), we should return the agent prompt // and let Claude Desktop handle the AI processing instead of making separate API calls const isClaudeDesktop = this.isRunningInClaudeDesktop(); if (isClaudeDesktop) { console.error('šŸ¤– Running inside Claude Desktop - using integrated AI processing'); // Extract the actual request from the full prompt const requestMatch = prompt.match(/## Current Request\n(.*?)(?:\n\n##|$)/s); const actualRequest = requestMatch ? requestMatch[1].trim() : prompt; // Add explicit code generation instructions const codeInstructions = ` ## CRITICAL INSTRUCTIONS - CODE GENERATION REQUIRED You MUST provide working, complete, production-ready code as SEPARATE FILES. Do NOT just provide documentation, architecture, or explanations. **REQUIREMENTS:** 1. **Generate actual code files** - Provide complete, runnable code 2. **Create separate, distinct files** - Each file should be clearly separated 3. **Include all necessary imports and dependencies** 4. **Provide working examples** - Code that can be immediately used 5. **Be specific and concrete** - No placeholders like [Your code here] or [Implementation details] 6. **Add proper error handling** - Include try/catch blocks and validation 7. **Use modern best practices** - Latest syntax, patterns, and approaches 8. **Make it production-ready** - Code should be enterprise-grade and deployable **MANDATORY FILE FORMAT:** Use this EXACT format for each file: \`\`\` ## FILE: path/to/filename.ext \`\`\`language [Complete file contents here] \`\`\` **EXAMPLE:** \`\`\` ## FILE: src/components/Button.tsx \`\`\`typescript import React from 'react'; interface ButtonProps { children: React.ReactNode; onClick?: () => void; } export const Button: React.FC<ButtonProps> = ({ children, onClick }) => { return ( <button onClick={onClick} className="btn"> {children} </button> ); }; \`\`\` ## FILE: src/styles/Button.css \`\`\`css .btn { padding: 10px 20px; border: none; border-radius: 4px; background: #007bff; color: white; cursor: pointer; } \`\`\` \`\`\` **OUTPUT STRUCTURE:** 1. Brief summary (1-2 sentences) 2. Multiple separate files using the FILE format above 3. Setup/installation instructions 4. Usage examples **AVOID:** - Single large code blocks without file separation - Generic explanations without code - Architecture discussions without implementation - Placeholder code or pseudo-code - Collaborative document format Remember: Create SEPARATE FILES that can be copied individually, not a single collaborative document.`; // Return the agent prompt with enhanced instructions and the request return `${agent.prompt}${codeInstructions}\n\n## Current Request\n${actualRequest}`; } // For standalone usage, check for API key const apiKey = process.env.ANTHROPIC_API_KEY; if (!apiKey) { console.error('āš ļø ANTHROPIC_API_KEY not found - using fallback response'); return this.generateFallbackResponse(agent, prompt, context, 'ANTHROPIC_API_KEY not found'); } console.error('šŸš€ Making external API call to Claude...'); try { // Check if fetch is available if (typeof fetch === 'undefined') { console.error('āŒ fetch is not available in this Node.js environment'); return this.generateFallbackResponse(agent, prompt, context, 'fetch not available'); } // Make actual API call to Claude console.error('šŸ“” Sending request to Anthropic API...'); const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 second timeout const response = await fetch('https://api.anthropic.com/v1/messages', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiKey}`, 'anthropic-version': '2023-06-01' }, body: JSON.stringify({ model: 'claude-3-sonnet-20240229', max_tokens: 4000, messages: [{ role: 'user', content: prompt }], temperature: 0.7 }), signal: controller.signal }); clearTimeout(timeoutId); console.error(`šŸ“” API Response status: ${response.status}`); if (!response.ok) { const errorText = await response.text(); console.error(`āŒ Claude API error (${response.status}): ${errorText}`); return this.generateFallbackResponse(agent, prompt, context, `API Error: ${response.status}`); } const data = await response.json() as any; if (!data.content || !Array.isArray(data.content) || !data.content[0] || !data.content[0].text) { console.error('āŒ Invalid Claude API response structure'); return this.generateFallbackResponse(agent, prompt, context, 'Invalid API response'); } // Return the actual AI-generated response return data.content[0].text; } catch (error) { console.error('āŒ Claude API call failed:', error); if (error instanceof Error) { if (error.name === 'AbortError') { console.error('ā° API call timed out after 30 seconds'); return this.generateFallbackResponse(agent, prompt, context, 'API timeout after 30 seconds'); } return this.generateFallbackResponse(agent, prompt, context, error.message); } return this.generateFallbackResponse(agent, prompt, context, 'Unknown error'); } } private isRunningInClaudeDesktop(): boolean { // Detect if we're running inside Claude Desktop MCP environment return ( // Check if stdin/stdout are pipes (typical for MCP servers) (!process.stdin.isTTY && !process.stdout.isTTY) || // Check for Claude Desktop specific process arguments or environment process.argv.some(arg => arg.includes('claude') || arg.includes('mcp')) || // Check if we're being called as a subprocess without a terminal process.env.NODE_ENV !== 'development' && !process.env.ANTHROPIC_API_KEY ); } private generateFallbackResponse( agent: WorksonaAgent, prompt: string, context: AgentExecutionContext, errorReason?: string ): string { const requestSummary = prompt.split('## Current Request\\n')[1]?.split('\\n')[0] || 'Unknown request'; let response = `# šŸŽÆ ${agent.name} Agent Response\\n\\n`; if (errorReason) { response += `āš ļø *Note: Using fallback response due to: ${errorReason}*\\n\\n`; } response += `I understand you need: "${requestSummary}"\\n\\n`; // Safe capability access with fallback const primaryCapabilities = agent.capabilities?.primary || []; const capabilitiesText = primaryCapabilities.length > 0 ? primaryCapabilities.join(', ') : 'general problem-solving'; response += `Based on my expertise in **${capabilitiesText}**, I would provide working code for: "${requestSummary}"\\n\\n`; response += `āš ļø **Note**: This is a fallback response. With a valid API key, I would generate:\\n\\n`; // Add agent-specific response structure focused on code output if (agent.category === 'software-engineering') { response += `## Complete Code Implementation\\n`; response += `- Full source code files with proper structure\\n`; response += `- All necessary imports and dependencies\\n`; response += `- Production-ready error handling\\n`; response += `- Setup and installation instructions\\n`; response += `- Working examples and usage demonstrations\\n\\n`; response += `## File Structure\\n`; response += `- Organized project layout\\n`; response += `- Configuration files\\n`; response += `- Test files and documentation\\n\\n`; response += `## Testing Strategy\\n`; response += `[Comprehensive testing approach and examples]\\n\\n`; } else if (agent.category === 'business-strategy') { response += `## Strategic Analysis\\n`; response += `[Business analysis and strategic recommendations]\\n\\n`; response += `## Implementation Plan\\n`; response += `[Step-by-step implementation roadmap]\\n\\n`; response += `## Success Metrics\\n`; response += `[KPIs and measurement criteria]\\n\\n`; } else if (agent.category === 'elite-research') { response += `## Research Methodology\\n`; response += `[Comprehensive research approach and source strategy]\\n\\n`; response += `## Key Findings\\n`; response += `[Research results and insights]\\n\\n`; response += `## Recommendations\\n`; response += `[Actionable recommendations based on research]\\n\\n`; } // Note: Tool references removed for Claude Desktop compatibility // Add next steps and coordination if (agent.coordination?.worksWellWith?.length) { const suggestedAgents = agent.coordination.worksWellWith.slice(0, 2); response += `## Next Steps & Coordination\\n`; response += `Consider consulting with the following specialists for additional expertise:\\n`; suggestedAgents.forEach(agentName => { response += `- **${agentName}**: For complementary capabilities\\n`; }); response += `\\n`; } // Add quality assurance note for enterprise-grade agents if (agent.quality?.enterpriseGrade) { response += `## Quality Assurance\\n`; response += `This solution follows enterprise standards and best practices:\\n`; response += `- Production-ready implementation\\n`; response += `- Comprehensive error handling\\n`; response += `- Scalable and maintainable architecture\\n`; response += `- Industry compliance considerations\\n`; } return response; } // Tool usage description method removed for Claude Desktop compatibility private extractToolsUsed(response: string): string[] { // Tool extraction disabled for Claude Desktop compatibility return []; } private suggestFollowupAgents(agent: WorksonaAgent, response: string): string[] { const suggestions: string[] = []; // Add agents from coordination metadata if (agent.coordination?.worksWellWith) { suggestions.push(...agent.coordination.worksWellWith.slice(0, 2)); } // Extract agent names mentioned in the response const mentionedAgents = this.extractMentionedAgents(response); suggestions.push(...mentionedAgents); // Remove duplicates and limit to 3 return Array.from(new Set(suggestions)).slice(0, 3); } private extractMentionedAgents(response: string): string[] { // Look for agent name patterns in the response const agentPattern = /\\b([a-z-]+(?:-[a-z]+)*(?:-(?:engineer|developer|architect|specialist|manager|analyst|auditor)))\\b/g; const matches = response.match(agentPattern) || []; return matches.slice(0, 2); } private calculateConfidence(agent: WorksonaAgent, request: string, response: string): number { let confidence = 0.7; // Base confidence // Higher confidence for agents with matching capabilities const requestLower = request.toLowerCase(); const matchingCapabilities = agent.capabilities.primary.filter(cap => requestLower.includes(cap.toLowerCase().replace(/_/g, ' ')) ); confidence += matchingCapabilities.length * 0.1; // Higher confidence for enterprise-grade agents if (agent.quality?.enterpriseGrade) { confidence += 0.1; } // Higher confidence for longer, detailed responses if (response.length > 1000) { confidence += 0.1; } return Math.min(confidence, 1.0); } private estimateTokens(text: string): number { // Rough estimation: ~4 characters per token return Math.ceil(text.length / 4); } private async updateAgentMemory( agent: WorksonaAgent, request: string, response: string, context: AgentExecutionContext ): Promise<void> { const summary = response.length > 300 ? response.substring(0, 300) + '...' : response; context.memory.addMemory({ agentName: agent.name, request, response, timestamp: new Date(), context: context.projectContext?.name || 'general', summary }); } // Utility methods for execution statistics getExecutionStats(): { totalExecutions: number; averageExecutionTime: number; successRate: number; } { const totalExecutions = this.executionCount; const averageExecutionTime = this.executionTimes.length > 0 ? this.executionTimes.reduce((a, b) => a + b, 0) / this.executionTimes.length : 0; return { totalExecutions, averageExecutionTime, successRate: 1.0 // In this simulation, we assume all executions succeed }; } }

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/worksona/-worksona-mcp-server'

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