bc-code-intelligence-mcp
Version:
BC Code Intelligence MCP Server - Complete Specialist Bundle with AI-driven expert consultation, seamless handoffs, and context-preserving workflows
275 lines • 11.1 kB
JavaScript
/**
* MCP Tools for Specialist Discovery and Management
*
* Provides tools for discovering specialists, getting recommendations,
* and managing specialist interactions.
*/
import { z } from 'zod';
// Tool argument schemas
const DiscoverSpecialistsArgsSchema = z.object({
query: z.string().describe('Query or problem description to find relevant specialists'),
max_suggestions: z.number().optional().default(3).describe('Maximum number of specialist suggestions to return'),
include_examples: z.boolean().optional().default(true).describe('Include example queries for each specialist')
});
const BrowseSpecialistsArgsSchema = z.object({
category: z.string().optional().describe('Filter by domain/category (e.g., "performance", "api-design")'),
include_details: z.boolean().optional().default(false).describe('Include detailed specialist information')
});
const GetSpecialistArgsSchema = z.object({
specialist_id: z.string().describe('ID of the specialist to get information about'),
include_examples: z.boolean().optional().default(true).describe('Include example scenarios and usage')
});
export const SPECIALIST_DISCOVERY_TOOLS = [
{
name: 'discover_specialists',
description: 'Find specialists who can help with your specific query or problem',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Query or problem description to find relevant specialists'
},
max_suggestions: {
type: 'number',
description: 'Maximum number of specialist suggestions to return',
default: 3
},
include_examples: {
type: 'boolean',
description: 'Include example queries for each specialist',
default: true
}
},
required: ['query']
}
},
{
name: 'browse_specialists',
description: 'Browse all available specialists, optionally filtered by category/domain',
inputSchema: {
type: 'object',
properties: {
category: {
type: 'string',
description: 'Filter by domain/category (e.g., "performance", "api-design")'
},
include_details: {
type: 'boolean',
description: 'Include detailed specialist information',
default: false
}
},
required: []
}
},
{
name: 'get_specialist_info',
description: 'Get detailed information about a specific specialist',
inputSchema: {
type: 'object',
properties: {
specialist_id: {
type: 'string',
description: 'ID of the specialist to get information about'
},
include_examples: {
type: 'boolean',
description: 'Include example scenarios and usage',
default: true
}
},
required: ['specialist_id']
}
}
];
export class SpecialistDiscoveryTools {
discoveryService;
sessionManager;
layerService;
constructor(discoveryService, sessionManager, layerService) {
this.discoveryService = discoveryService;
this.sessionManager = sessionManager;
this.layerService = layerService;
}
/**
* Get tool definitions for MCP registration
*/
getToolDefinitions() {
return SPECIALIST_DISCOVERY_TOOLS;
}
async handleToolCall(request) {
try {
switch (request.params.name) {
case 'discover_specialists':
return await this.discoverSpecialists(request);
case 'browse_specialists':
return await this.browseSpecialists(request);
case 'get_specialist_info':
return await this.getSpecialistInfo(request);
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}
],
isError: true
};
}
}
async discoverSpecialists(request) {
const args = DiscoverSpecialistsArgsSchema.parse(request.params.arguments);
const suggestions = await this.discoveryService.suggestSpecialists({
query: args.query
}, args.max_suggestions);
// Get complete specialist roster
const allSpecialists = await this.discoveryService.getAllSpecialistsInfo();
const result = {
query: args.query,
matches: suggestions.map(suggestion => ({
specialist_id: suggestion.specialist.specialist_id,
title: suggestion.specialist.title || suggestion.specialist.specialist_id,
role: suggestion.specialist.role || 'Specialist',
confidence: Math.round(suggestion.confidence * 100),
match_type: suggestion.match_type || 'content_match',
reasons: suggestion.reasons,
keywords_matched: suggestion.keywords_matched,
emoji: suggestion.specialist.emoji || '�'
})),
all_specialists: allSpecialists,
total_available: allSpecialists.length
};
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2)
}
]
};
}
async browseSpecialists(request) {
const args = BrowseSpecialistsArgsSchema.parse(request.params.arguments);
let specialists;
if (args.category) {
specialists = await this.discoveryService.getSpecialistsByDomain(args.category);
}
else {
specialists = await this.layerService.getAllSpecialists();
}
if (specialists.length === 0) {
return {
content: [
{
type: 'text',
text: args.category
? `No specialists found for category "${args.category}"`
: 'No specialists available'
}
]
};
}
let result = args.category
? `🏷️ **Specialists in "${args.category}" category:**\n\n`
: '👥 **Available BC Code Intelligence Specialists:**\n\n';
for (const specialist of specialists) {
const emoji = specialist.emoji || '👤';
result += `${emoji} **${specialist.title}** (\`${specialist.specialist_id}\`)\n`;
result += ` 📋 ${specialist.role}\n`;
if (args.include_details) {
if (specialist.expertise?.primary) {
result += ` 🎯 **Primary:** ${specialist.expertise.primary.join(', ')}\n`;
}
if (specialist.when_to_use) {
result += ` 💡 **Use for:** ${specialist.when_to_use.slice(0, 2).join(', ')}\n`;
}
}
result += '\n';
}
result += '💬 **To interact:** Use `discover_specialists` with your specific question or `get_specialist_info` for details.\n';
return {
content: [
{
type: 'text',
text: result
}
]
};
}
async getSpecialistInfo(request) {
const args = GetSpecialistArgsSchema.parse(request.params.arguments);
// Try exact ID match first, then fuzzy matching
let specialist = await this.layerService.getSpecialist(args.specialist_id);
if (!specialist) {
specialist = await this.discoveryService.findSpecialistByName(args.specialist_id);
}
if (!specialist) {
return {
content: [
{
type: 'text',
text: `Specialist "${args.specialist_id}" not found. Tried exact ID match and fuzzy name matching. Use \`list_specialists\` to see available specialists.`
}
],
isError: true
};
}
const emoji = specialist.emoji || '👤';
let result = `${emoji} **${specialist.title}**\n\n`;
result += `**Specialist ID:** \`${specialist.specialist_id}\`\n`;
result += `**Role:** ${specialist.role}\n`;
result += `**Team:** ${specialist.team}\n\n`;
if (specialist.persona?.communication_style) {
result += `**Communication Style:** ${specialist.persona.communication_style}\n\n`;
}
if (specialist.expertise?.primary) {
result += `**Primary Expertise:**\n`;
specialist.expertise.primary.forEach(exp => result += `• ${exp}\n`);
result += '\n';
}
if (specialist.expertise?.secondary) {
result += `**Secondary Expertise:**\n`;
specialist.expertise.secondary.forEach(exp => result += `• ${exp}\n`);
result += '\n';
}
if (specialist.when_to_use) {
result += `**When to Use:**\n`;
specialist.when_to_use.forEach(use => result += `• ${use}\n`);
result += '\n';
}
if (specialist.collaboration?.natural_handoffs) {
result += `**Natural Handoffs:**\n`;
specialist.collaboration.natural_handoffs.forEach(handoff => result += `• ${handoff}\n`);
result += '\n';
}
if (args.include_examples) {
const example = this.generateExampleQuery(specialist);
result += `**Example Query:** "${example}"\n\n`;
}
result += `**💬 Start a session:** Use \`suggest_specialist\` with specialist_id: \`${specialist.specialist_id}\`\n`;
return {
content: [
{
type: 'text',
text: result
}
]
};
}
generateExampleQuery(specialist) {
if (specialist.when_to_use && specialist.when_to_use.length > 0) {
return `Help me with ${specialist.when_to_use[0].toLowerCase()}`;
}
if (specialist.expertise?.primary && specialist.expertise.primary.length > 0) {
return `I need guidance on ${specialist.expertise.primary[0].toLowerCase()}`;
}
return `I need help with ${specialist.role?.toLowerCase() || 'development'}`;
}
}
//# sourceMappingURL=specialist-discovery-tools.js.map