jay-code
Version:
Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability
841 lines (752 loc) âĸ 23.6 kB
text/typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
CallToolResult,
TextContent,
ImageContent,
EmbeddedResource,
} from '@modelcontextprotocol/sdk/types.js';
import * as fs from 'fs/promises';
import * as path from 'path';
import { fileURLToPath } from 'url';
import { SparcMode, loadSparcModes } from './sparc-modes.js';
// Simple ID generation
function generateId(): string {
return `${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
interface SparcContext {
memoryKey?: string;
parallel?: boolean;
timeout?: number;
workingDirectory?: string;
}
interface SwarmAgent {
id: string;
mode: string;
task: string;
status: 'pending' | 'active' | 'completed' | 'failed';
result?: any;
}
interface SwarmExecution {
id: string;
objective: string;
strategy: string;
mode: string;
agents: SwarmAgent[];
startTime: Date;
endTime?: Date;
status: 'active' | 'completed' | 'failed';
}
export class ClaudeCodeMCPWrapper {
private server: Server;
private sparcModes: Map<string, SparcMode> = new Map();
private swarmExecutions: Map<string, SwarmExecution> = new Map();
private claudeCodeMCP: any; // Reference to Claude Code MCP client
constructor() {
this.server = new Server(
{
name: 'jay-code-wrapper',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
},
);
this.setupHandlers();
this.loadSparcModes();
}
private async loadSparcModes() {
try {
const modes = await loadSparcModes();
modes.forEach((mode) => {
this.sparcModes.set(mode.name, mode);
});
} catch (error) {
console.error('Failed to load SPARC modes:', error);
}
}
private setupHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: await this.getTools(),
}));
this.server.setRequestHandler(CallToolRequestSchema, async (request) =>
this.handleToolCall(request.params.name, request.params.arguments || {}),
);
}
private async getTools(): Promise<Tool[]> {
const tools: Tool[] = [];
// Add SPARC mode tools
for (const [name, mode] of this.sparcModes) {
tools.push({
name: `sparc_${name}`,
description: `Execute SPARC ${name} mode: ${mode.description}`,
inputSchema: {
type: 'object',
properties: {
task: {
type: 'string',
description: 'The task description for the SPARC mode to execute',
},
context: {
type: 'object',
description: 'Optional context or parameters for the task',
properties: {
memoryKey: {
type: 'string',
description: 'Memory key to store results',
},
parallel: {
type: 'boolean',
description: 'Enable parallel execution',
},
},
},
},
required: ['task'],
},
});
}
// Add meta tools
tools.push(
{
name: 'sparc_list',
description: 'List all available SPARC modes',
inputSchema: {
type: 'object',
properties: {
verbose: {
type: 'boolean',
description: 'Include detailed information',
},
},
},
},
{
name: 'sparc_swarm',
description: 'Coordinate multiple SPARC agents in a swarm',
inputSchema: {
type: 'object',
properties: {
objective: {
type: 'string',
description: 'The swarm objective',
},
strategy: {
type: 'string',
enum: [
'research',
'development',
'analysis',
'testing',
'optimization',
'maintenance',
],
description: 'Swarm execution strategy',
},
mode: {
type: 'string',
enum: ['centralized', 'distributed', 'hierarchical', 'mesh', 'hybrid'],
description: 'Coordination mode',
},
maxAgents: {
type: 'number',
description: 'Maximum number of agents',
default: 5,
},
},
required: ['objective', 'strategy'],
},
},
{
name: 'sparc_swarm_status',
description: 'Check status of running swarms and list created files',
inputSchema: {
type: 'object',
properties: {
swarmId: {
type: 'string',
description: 'Optional swarm ID to check specific swarm',
},
},
},
},
);
return tools;
}
private async handleToolCall(toolName: string, args: any): Promise<CallToolResult> {
try {
if (toolName.startsWith('sparc_')) {
return await this.handleSparcTool(toolName, args);
}
// Pass through to Claude Code MCP
return this.forwardToClaudeCode(toolName, args);
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
private async handleSparcTool(toolName: string, args: any): Promise<CallToolResult> {
const mode = toolName.replace('sparc_', '');
// Handle special tools
if (mode === 'list') {
return this.listModes(args.verbose);
}
if (mode === 'swarm') {
return this.handleSwarm(args);
}
if (mode === 'swarm_status') {
return this.getSwarmStatus(args.swarmId);
}
// Standard SPARC mode execution
const sparcMode = this.sparcModes.get(mode);
if (!sparcMode) {
throw new Error(`Unknown SPARC mode: ${mode}`);
}
// Execute the SPARC mode directly
try {
// Import the execution function dynamically to avoid circular dependencies
// const { executeSparcMode } = await import('../cli/mcp-stdio-server.js');
// TODO: Implement proper SPARC mode execution or fix import path
const executeSparcMode = (mode: string, task: string, tools: any[], context: any) => {
throw new Error('SPARC mode execution not yet implemented in wrapper');
};
const result = await executeSparcMode(
mode,
args.task,
sparcMode.tools || [],
args.context || {},
);
return {
content: [
{
type: 'text',
text: result.output,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error executing SPARC ${mode}: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
private buildEnhancedPrompt(mode: SparcMode, task: string, context?: SparcContext): string {
const parts: string[] = [];
// Add SPARC mode header
parts.push(`SPARC: ${mode.name}\n`);
parts.push(`## Mode Description\n${mode.description}\n`);
// Add available tools
if (mode.tools && mode.tools.length > 0) {
parts.push(`## Available Tools`);
mode.tools.forEach((tool) => {
parts.push(`- **${tool}**: ${this.getToolDescription(tool)}`);
});
parts.push('');
}
// Add usage pattern
if (mode.usagePattern) {
parts.push(`## Usage Pattern\n\`\`\`javascript\n${mode.usagePattern}\n\`\`\`\n`);
}
// Add best practices
if (mode.bestPractices) {
parts.push(`## Best Practices`);
mode.bestPractices.forEach((practice) => {
parts.push(`- ${practice}`);
});
parts.push('');
}
// Add integration capabilities
if (mode.integrationCapabilities) {
parts.push(`## Integration Capabilities\nThis mode integrates with:`);
mode.integrationCapabilities.forEach((capability) => {
parts.push(`- ${capability}`);
});
parts.push('');
}
// Add instructions
if (mode.instructions) {
parts.push(`## Instructions\n${mode.instructions}\n`);
}
// Add the actual task
parts.push(`## TASK: ${task}\n`);
// Add SPARC methodology
parts.push(this.getSparcMethodology(mode.name, task, context));
// Add context if provided
if (context) {
if (context.memoryKey) {
parts.push(`**Memory Key:** \`${context.memoryKey}\``);
}
if (context.parallel) {
parts.push(`**Parallel Execution:** Enabled`);
}
if (context.workingDirectory) {
parts.push(`**Working Directory:** ${context.workingDirectory}`);
}
}
return parts.join('\n');
}
private getToolDescription(tool: string): string {
const descriptions: Record<string, string> = {
TodoWrite: 'Create and manage task coordination',
TodoRead: 'Monitor task progress and status',
Task: 'Spawn and manage specialized agents',
Memory: 'Store and retrieve coordination data',
Bash: 'Execute system commands',
Read: 'Read file contents',
Write: 'Write files',
Edit: 'Edit existing files',
MultiEdit: 'Make multiple edits to a file',
Glob: 'Search for files by pattern',
Grep: 'Search file contents',
WebSearch: 'Search the web',
WebFetch: 'Fetch web content',
};
return descriptions[tool] || `${tool} tool`;
}
private getSparcMethodology(mode: string, task: string, context?: SparcContext): string {
return `
# đ¯ SPARC METHODOLOGY EXECUTION FRAMEWORK
You are operating in **SPARC ${mode} mode**. Follow the SPARC Workflow precisely:
## SPARC Workflow Steps
### 1ī¸âŖ SPECIFICATION - Clarify goals, scope, constraints
**Your Task:** ${task}
**Analysis Required:**
- Break down into clear, measurable objectives
- Identify all requirements and constraints
- Define acceptance criteria
- Never hard-code environment variables
**Use TodoWrite to capture specifications:**
\`\`\`javascript
TodoWrite([
{
id: "specification",
content: "Clarify goals, scope, and constraints for: ${task}",
status: "pending",
priority: "high"
},
{
id: "acceptance_criteria",
content: "Define clear acceptance criteria and success metrics",
status: "pending",
priority: "high"
}
]);
\`\`\`
### 2ī¸âŖ PSEUDOCODE - High-level logic with TDD anchors
**Design Approach:**
- Identify core functions and data structures
- Create TDD test anchors before implementation
- Map out component interactions
### 3ī¸âŖ ARCHITECTURE - Design extensible systems
**Architecture Requirements:**
- Clear service boundaries
- Define interfaces between components
- Design for extensibility and maintainability
- Mode-specific architecture: ${this.getModeSpecificArchitecture(mode)}
### 4ī¸âŖ REFINEMENT - Iterate with TDD and security
**Refinement Process:**
- TDD implementation cycles
- Security vulnerability checks (injection, XSS, CSRF)
- Performance optimization
- Code review and refactoring
- All files must be ⤠500 lines
### 5ī¸âŖ COMPLETION - Integrate and verify
**Completion Checklist:**
- [ ] All acceptance criteria met
- [ ] Tests passing (comprehensive test suite)
- [ ] Security review completed
- [ ] Documentation updated
- [ ] Results stored in Memory: \`sparc_${mode}_${Date.now()}\`
- [ ] No hard-coded secrets or env vars
- [ ] Proper error handling in all code paths
## đ Execution Configuration
**Mode:** ${mode}
**Strategy:** ${this.getModeStrategy(mode)}
**Memory Key:** \`sparc_${mode}_${Date.now()}\`
**Batch Operations:** ${context?.parallel ? 'Enabled' : 'Standard operations'}
**Primary Tools:** ${this.sparcModes.get(mode)?.tools?.join(', ') || 'Standard tools'}
## đ Must Block (Non-negotiable)
- Every file ⤠500 lines
- No hard-coded secrets or env vars
- All user inputs validated
- No security vulnerabilities
- Proper error handling in all paths
- Each subtask ends with completion check
## đ¯ IMMEDIATE ACTION REQUIRED
**START NOW with SPARC Step 1 - SPECIFICATION:**
1. Create comprehensive TodoWrite task breakdown following SPARC workflow
2. Set "specification" task to "in_progress"
3. Analyze requirements and define acceptance criteria
4. Store initial analysis in Memory: \`sparc_${mode}_${Date.now()}\`
**Remember:** You're in **${mode}** mode. Follow the SPARC workflow systematically:
Specification â Pseudocode â Architecture â Refinement â Completion
Use the appropriate tools for each phase and maintain progress in TodoWrite.`;
}
private getModeSpecificArchitecture(mode: string): string {
const architectures: Record<string, string> = {
orchestrator: 'Design for parallel agent coordination with clear task boundaries',
coder: 'Focus on clean code architecture with proper abstractions',
researcher: 'Structure for data collection and analysis pipelines',
tdd: 'Test-first design with comprehensive test coverage',
architect: 'System-wide design patterns and component interactions',
reviewer: 'Code quality gates and review checkpoints',
debugger: 'Diagnostic and monitoring integration points',
tester: 'Test framework integration and coverage analysis',
};
return architectures[mode] || 'Design for the specific mode requirements';
}
private getModeStrategy(mode: string): string {
const strategies: Record<string, string> = {
orchestrator: 'Parallel coordination',
coder: 'Iterative development',
researcher: 'Deep analysis',
tdd: 'Test-driven cycles',
architect: 'System design',
reviewer: 'Quality assurance',
debugger: 'Systematic debugging',
tester: 'Comprehensive validation',
};
return strategies[mode] || 'Mode-specific execution';
}
private listModes(verbose: boolean): CallToolResult {
const modes = Array.from(this.sparcModes.values());
if (verbose) {
const content = modes.map((mode) => ({
name: mode.name,
description: mode.description,
tools: mode.tools,
bestPractices: mode.bestPractices,
}));
return {
content: [
{
type: 'text',
text: JSON.stringify(content, null, 2),
},
],
};
}
const list = modes.map((m) => `- **${m.name}**: ${m.description}`).join('\n');
return {
content: [
{
type: 'text',
text: `Available SPARC modes:\n\n${list}`,
},
],
};
}
private async handleSwarm(args: any): Promise<CallToolResult> {
const { objective, strategy, mode = 'distributed', maxAgents = 5 } = args;
const swarmId = generateId();
// Plan swarm agents
const agents = this.planSwarmAgents(objective, strategy, maxAgents);
// Create swarm execution record
const execution: SwarmExecution = {
id: swarmId,
objective,
strategy,
mode,
agents,
startTime: new Date(),
status: 'active',
};
this.swarmExecutions.set(swarmId, execution);
// Launch agents based on coordination mode
if (mode === 'distributed' || mode === 'mesh') {
// Parallel execution
await Promise.all(agents.map((agent) => this.launchSwarmAgent(agent, execution)));
} else {
// Sequential execution
for (const agent of agents) {
await this.launchSwarmAgent(agent, execution);
}
}
execution.status = 'completed';
execution.endTime = new Date();
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
swarmId,
objective,
strategy,
mode,
agentCount: agents.length,
status: 'launched',
message: 'Swarm coordination initiated',
},
null,
2,
),
},
],
};
}
private planSwarmAgents(objective: string, strategy: string, maxAgents: number): SwarmAgent[] {
const agents: SwarmAgent[] = [];
// Strategy-based agent planning
switch (strategy) {
case 'research':
agents.push(
{
id: generateId(),
mode: 'researcher',
task: `Research: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'analyst',
task: `Analyze findings for: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'documenter',
task: `Document research results: ${objective}`,
status: 'pending',
},
);
break;
case 'development':
agents.push(
{
id: generateId(),
mode: 'architect',
task: `Design architecture: ${objective}`,
status: 'pending',
},
{ id: generateId(), mode: 'coder', task: `Implement: ${objective}`, status: 'pending' },
{
id: generateId(),
mode: 'tester',
task: `Test implementation: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'reviewer',
task: `Review code: ${objective}`,
status: 'pending',
},
);
break;
case 'analysis':
agents.push(
{ id: generateId(), mode: 'analyst', task: `Analyze: ${objective}`, status: 'pending' },
{
id: generateId(),
mode: 'optimizer',
task: `Optimize based on analysis: ${objective}`,
status: 'pending',
},
);
break;
case 'testing':
agents.push(
{
id: generateId(),
mode: 'tester',
task: `Create test suite: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'debugger',
task: `Debug issues: ${objective}`,
status: 'pending',
},
);
break;
case 'optimization':
agents.push(
{
id: generateId(),
mode: 'analyst',
task: `Performance analysis: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'optimizer',
task: `Optimize: ${objective}`,
status: 'pending',
},
);
break;
case 'maintenance':
agents.push(
{
id: generateId(),
mode: 'reviewer',
task: `Code review: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'debugger',
task: `Fix issues: ${objective}`,
status: 'pending',
},
{
id: generateId(),
mode: 'documenter',
task: `Update documentation: ${objective}`,
status: 'pending',
},
);
break;
}
// Limit to maxAgents
return agents.slice(0, maxAgents);
}
private async launchSwarmAgent(agent: SwarmAgent, execution: SwarmExecution): Promise<void> {
agent.status = 'active';
try {
// Use the SPARC mode handler
const result = await this.handleSparcTool(`sparc_${agent.mode}`, {
task: agent.task,
context: {
memoryKey: `swarm_${execution.id}_${agent.id}`,
parallel: execution.mode === 'distributed',
},
});
agent.status = 'completed';
agent.result = result;
} catch (error) {
agent.status = 'failed';
agent.result = { error: error instanceof Error ? error.message : String(error) };
}
}
private getSwarmStatus(swarmId?: string): CallToolResult {
if (swarmId) {
const execution = this.swarmExecutions.get(swarmId);
if (!execution) {
return {
content: [
{
type: 'text',
text: `No swarm found with ID: ${swarmId}`,
},
],
};
}
return {
content: [
{
type: 'text',
text: JSON.stringify(execution, null, 2),
},
],
};
}
// Return all swarms
const swarms = Array.from(this.swarmExecutions.values()).map((e) => ({
id: e.id,
objective: e.objective,
status: e.status,
agentCount: e.agents.length,
startTime: e.startTime,
endTime: e.endTime,
}));
return {
content: [
{
type: 'text',
text: JSON.stringify(swarms, null, 2),
},
],
};
}
private async forwardToClaudeCode(toolName: string, args: any): Promise<CallToolResult> {
// For SPARC tools that were already handled, this shouldn't be called
// For other tools, we execute them using the existing logic
if (toolName === 'Task') {
// This is a SPARC task that's been enhanced with prompts
// Extract the mode from the description if possible
const modeMatch = args.description?.match(/SPARC (\w+)/);
if (modeMatch) {
const modeName = modeMatch[1];
const mode = this.sparcModes.get(modeName);
if (mode) {
// Execute using the existing SPARC execution logic
try {
const result = await executeSparcMode(
modeName,
args.prompt || '',
mode.tools || [],
{},
);
return {
content: [
{
type: 'text',
text: result.output,
},
],
};
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error executing SPARC ${modeName}: ${error instanceof Error ? error.message : String(error)}`,
},
],
isError: true,
};
}
}
}
}
// For non-SPARC tools, return a message
return {
content: [
{
type: 'text',
text: `Tool ${toolName} is not available in this MCP server.`,
},
],
isError: true,
};
}
async run() {
const transport = new StdioServerTransport();
// Log startup message
console.error('đ Jay-Code MCP Server (Wrapper Mode)');
console.error('đĻ Using Claude Code MCP pass-through with SPARC prompt injection');
console.error('đ§ All SPARC tools available with enhanced AI capabilities');
console.error('âšī¸ To use legacy mode, set JAY_CODE_LEGACY_MCP=true');
console.error('');
await this.server.connect(transport);
}
}
// Run the server if this is the main module
if (import.meta.url === `file://${process.argv[1]}`) {
const wrapper = new ClaudeCodeMCPWrapper();
wrapper.run().catch(console.error);
}