bc-code-intelligence-mcp
Version:
BC Code Intelligence MCP Server - Complete Specialist Bundle with AI-driven expert consultation, seamless handoffs, and context-preserving workflows
265 lines (262 loc) • 12.3 kB
JavaScript
/**
* Specialist Handoff MCP Tools
*
* Tools for seamless transitions between specialists while preserving context,
* conversation history, and ensuring natural collaboration flow.
*/
import { z } from 'zod';
// Tool argument schemas
const HandoffToSpecialistArgsSchema = z.object({
target_specialist_id: z.string().describe('ID of the specialist to hand off to'),
handoff_type: z.enum(['transfer', 'consultation', 'collaboration', 'escalation']).describe('Type of handoff - transfer (complete), consultation (temporary), collaboration (joint), escalation (senior expert)'),
handoff_reason: z.string().describe('Clear reason why this handoff is needed'),
problem_summary: z.string().describe('Current problem/challenge being worked on'),
work_completed: z.array(z.string()).describe('List of work completed so far'),
current_challenges: z.array(z.string()).optional().default([]).describe('Current challenges or blockers'),
continuation_points: z.array(z.string()).optional().default([]).describe('Specific points for the next specialist to focus on'),
preserve_session: z.boolean().optional().default(true).describe('Whether to preserve current session context')
});
const BringInSpecialistArgsSchema = z.object({
specialist_id: z.string().describe('ID of the specialist to bring in for consultation'),
consultation_reason: z.string().describe('Why this specialist\'s expertise is needed'),
specific_question: z.string().describe('Specific question or challenge for the specialist'),
current_context: z.string().describe('Brief context of current work and situation'),
collaboration_type: z.enum(['advice', 'review', 'joint-work']).optional().default('advice').describe('Type of collaboration needed')
});
const GetHandoffSummaryArgsSchema = z.object({
session_id: z.string().optional().describe('Session ID to get handoff summary for (current session if omitted)'),
include_recommendations: z.boolean().optional().default(true).describe('Include previous recommendations in summary')
});
/**
* Handoff tool definitions for MCP registration
*/
export const HANDOFF_TOOLS = [
{
name: 'handoff_to_specialist',
description: `Transfer or collaborate with another BC specialist while preserving full context. Use when:
• Current problem requires different expertise domain
• User asks for specific specialist or different perspective
• Problem complexity requires architectural, security, testing, or other specialized input
• You've completed your analysis and next steps need different skills
Creates seamless transition with full context transfer so user doesn't repeat information.
🔧 **AL/BC Platform Constraints**: Specialists follow Business Central and AL Language limitations:
• Security: AL permissions, BC security framework only
• UX: AL page/report constraints, not custom rendering
• Performance: AL optimization patterns, BC server constraints
• API: BC web services, AL integration patterns only`,
inputSchema: {
type: 'object',
properties: {
target_specialist_id: {
type: 'string',
description: 'ID of the specialist to hand off to'
},
handoff_type: {
type: 'string',
enum: ['transfer', 'consultation', 'collaboration', 'escalation'],
description: 'Type of handoff - transfer (complete), consultation (temporary), collaboration (joint), escalation (senior expert)'
},
handoff_reason: {
type: 'string',
description: 'Clear reason why this handoff is needed'
},
problem_summary: {
type: 'string',
description: 'Current problem/challenge being worked on'
},
work_completed: {
type: 'array',
items: { type: 'string' },
description: 'List of work completed so far'
},
current_challenges: {
type: 'array',
items: { type: 'string' },
description: 'Current challenges or blockers'
},
continuation_points: {
type: 'array',
items: { type: 'string' },
description: 'Specific points for the next specialist to focus on'
},
preserve_session: {
type: 'boolean',
description: 'Whether to preserve current session context',
default: true
}
},
required: ['target_specialist_id', 'handoff_type', 'handoff_reason', 'problem_summary', 'work_completed']
}
},
{
name: 'bring_in_specialist',
description: `Bring in another specialist for consultation or collaboration while maintaining current session. Use for quick expert input, code reviews, or joint problem-solving without full handoff.
🔧 **AL/BC Platform Constraints**: Specialists follow Business Central limitations:
• Security: AL permissions, BC security framework only
• UX: AL page/report constraints, not custom rendering
• Performance: AL optimization patterns, BC server constraints
• API: BC web services, AL integration patterns only`,
inputSchema: {
type: 'object',
properties: {
specialist_id: {
type: 'string',
description: 'ID of the specialist to bring in for consultation'
},
consultation_reason: {
type: 'string',
description: 'Why this specialist\'s expertise is needed'
},
specific_question: {
type: 'string',
description: 'Specific question or challenge for the specialist'
},
current_context: {
type: 'string',
description: 'Brief context of current work and situation'
},
collaboration_type: {
type: 'string',
enum: ['advice', 'review', 'joint-work'],
description: 'Type of collaboration needed',
default: 'advice'
}
},
required: ['specialist_id', 'consultation_reason', 'specific_question', 'current_context']
}
},
{
name: 'get_handoff_summary',
description: `Get summary of previous specialist handoffs and context for current session. Useful when you need to understand what other specialists have already worked on.`,
inputSchema: {
type: 'object',
properties: {
session_id: {
type: 'string',
description: 'Session ID to get handoff summary for (current session if omitted)'
},
include_recommendations: {
type: 'boolean',
description: 'Include previous recommendations in summary',
default: true
}
},
required: []
}
}
];
/**
* Specialist Handoff Tools Class
* Handles handoff-related tool calls and maintains handoff context
*/
export class SpecialistHandoffTools {
sessionManager;
discoveryService;
layerService;
constructor(sessionManager, discoveryService, layerService) {
this.sessionManager = sessionManager;
this.discoveryService = discoveryService;
this.layerService = layerService;
}
/**
* Get tool definitions for MCP registration
*/
getToolDefinitions() {
return HANDOFF_TOOLS;
}
/**
* Handle tool calls
*/
async handleToolCall(request) {
try {
switch (request.params.name) {
case 'handoff_to_specialist':
return await this.handoffToSpecialist(request);
case 'bring_in_specialist':
return await this.bringInSpecialist(request);
case 'get_handoff_summary':
return await this.getHandoffSummary(request);
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`
}
],
isError: true
};
}
}
async handoffToSpecialist(request) {
const validated = HandoffToSpecialistArgsSchema.parse(request.params.arguments);
const specialist = await this.layerService.getSpecialist(validated.target_specialist_id);
if (!specialist) {
return {
content: [{ type: 'text', text: `Specialist not found: ${validated.target_specialist_id}` }],
isError: true
};
}
// Build handoff message
let response = `# 🔄 Specialist Handoff\n\n`;
response += `Transitioning to **${specialist.title}**\n\n`;
response += `## Handoff Summary\n`;
response += `**Type:** ${validated.handoff_type}\n`;
response += `**Reason:** ${validated.handoff_reason}\n\n`;
response += `**Problem:** ${validated.problem_summary}\n\n`;
if (validated.work_completed.length > 0) {
response += `**Work Completed:**\n`;
validated.work_completed.forEach(item => response += `- ${item}\n`);
response += `\n`;
}
if (validated.current_challenges && validated.current_challenges.length > 0) {
response += `**Current Challenges:**\n`;
validated.current_challenges.forEach(item => response += `- ${item}\n`);
response += `\n`;
}
if (validated.continuation_points && validated.continuation_points.length > 0) {
response += `**Continuation Points:**\n`;
validated.continuation_points.forEach(item => response += `- ${item}\n`);
response += `\n`;
}
response += `---\n\n`;
response += `${specialist.persona.greeting}\n\n`;
response += `I've reviewed the handoff context. Let me pick up from where we are...\n`;
return {
content: [{ type: 'text', text: response }]
};
}
async bringInSpecialist(request) {
const validated = BringInSpecialistArgsSchema.parse(request.params.arguments);
const specialist = await this.layerService.getSpecialist(validated.specialist_id);
if (!specialist) {
return {
content: [{ type: 'text', text: `Specialist not found: ${validated.specialist_id}` }],
isError: true
};
}
let response = `# 👋 Bringing in ${specialist.title}\n\n`;
response += `**Consultation Reason:** ${validated.consultation_reason}\n`;
response += `**Question:** ${validated.specific_question}\n`;
response += `**Context:** ${validated.current_context}\n\n`;
response += `---\n\n`;
response += `${specialist.persona.greeting}\n\n`;
response += `I'm here to help with this ${validated.collaboration_type}. Let me address your question...\n`;
return {
content: [{ type: 'text', text: response }]
};
}
async getHandoffSummary(request) {
const validated = GetHandoffSummaryArgsSchema.parse(request.params.arguments);
// For now, return a placeholder - full implementation would query session history
const response = `# 📋 Handoff Summary\n\nNo previous handoffs found for this session.\n`;
return {
content: [{ type: 'text', text: response }]
};
}
}
//# sourceMappingURL=handoff-tools.js.map