mushcode-mcp-server
Version:
A specialized Model Context Protocol server for MUSHCODE development assistance. Provides AI-powered code generation, validation, optimization, and examples for MUD development.
216 lines • 9.06 kB
JavaScript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
import { MushcodeToolRegistry } from './registry.js';
import { ProtocolError, ToolExecutionError, ToolNotFoundError, handleError, validateToolParameters } from '../utils/errors.js';
export class MushcodeProtocolHandler {
server;
registry;
configManager;
isRunning = false;
constructor(configManager) {
this.configManager = configManager;
this.registry = new MushcodeToolRegistry();
const config = configManager.getConfig();
this.server = new Server({
name: config.server.name,
version: config.server.version,
}, {
capabilities: {
tools: {
listChanged: false, // We don't support dynamic tool changes yet
},
},
});
this.setupHandlers();
// Note: registerDefaultTools is async, so we'll call it in start()
}
setupHandlers() {
// Handle tool listing
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
try {
const tools = this.registry.getTools();
return {
tools,
};
}
catch (error) {
throw handleError(error);
}
});
// Handle tool calls with comprehensive error handling
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
const { name, arguments: args } = request.params;
// Get tool from registry
const tool = this.registry.getTool(name);
if (!tool) {
throw new ToolNotFoundError(name);
}
// Validate parameters against tool schema
if (tool.inputSchema) {
validateToolParameters(name, args, tool.inputSchema);
}
// Get tool handler
const handler = this.registry.getToolHandler(name);
if (!handler) {
throw new ToolExecutionError(name, 'No handler registered for tool');
}
// Execute tool with error handling
const result = await this.executeToolSafely(name, handler, args || {});
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
catch (error) {
throw handleError(error);
}
});
// Handle server errors
this.server.onerror = (error) => {
console.error('MCP Server error:', error);
};
}
/**
* Execute a tool handler with comprehensive error handling
*/
async executeToolSafely(toolName, handler, args) {
try {
return await handler(args);
}
catch (error) {
if (error instanceof Error) {
throw new ToolExecutionError(toolName, error.message, { originalError: error.message });
}
throw new ToolExecutionError(toolName, 'Unknown error during tool execution');
}
}
/**
* Register default MUSHCODE tools
*/
async registerDefaultTools() {
const config = this.configManager.getConfig();
// Initialize knowledge base with configuration
const { MushcodeKnowledgeBase } = await import('../knowledge/base.js');
const { MushcodePopulator } = await import('../knowledge/populator.js');
const { generateMushcodeTool, generateMushcodeHandler } = await import('../tools/generate.js');
const { validateMushcodeTool, validateMushcodeHandler } = await import('../tools/validate.js');
const { optimizeMushcodeTool, optimizeMushcodeHandler } = await import('../tools/optimize.js');
const { explainMushcodeTool, explainMushcodeHandler } = await import('../tools/explain.js');
const { getExamplesTool, getExamplesHandler } = await import('../tools/examples.js');
const { formatMushcodeTool, formatMushcodeHandler } = await import('../tools/format.js');
const { compressMushcodeTool, compressMushcodeHandler } = await import('../tools/compress.js');
// Load the enhanced knowledge base from persisted data
const { KnowledgeBasePersistence } = await import('../knowledge/persistence.js');
const persistence = new KnowledgeBasePersistence();
let knowledgeBase;
try {
// Try to load the enhanced knowledge base first
knowledgeBase = await persistence.load();
console.log('✅ Loaded enhanced knowledge base with help files and GitHub content');
}
catch (error) {
// Fallback to basic population if enhanced KB not available
console.log('⚠️ Enhanced knowledge base not found, falling back to basic population');
knowledgeBase = new MushcodeKnowledgeBase();
const populator = new MushcodePopulator(knowledgeBase);
await populator.populateFromMushcodeCom();
}
// Register tools based on configuration
const toolsConfig = config.tools;
const enabledTools = toolsConfig.enabled.filter(tool => !toolsConfig.disabled.includes(tool));
if (enabledTools.includes('generate_mushcode')) {
this.registry.registerTool(generateMushcodeTool);
this.registry.registerToolHandler('generate_mushcode', async (args) => {
return await generateMushcodeHandler(args, knowledgeBase);
});
}
if (enabledTools.includes('validate_mushcode')) {
this.registry.registerTool(validateMushcodeTool);
this.registry.registerToolHandler('validate_mushcode', async (args) => {
return await validateMushcodeHandler(args, knowledgeBase);
});
}
if (enabledTools.includes('optimize_mushcode')) {
this.registry.registerTool(optimizeMushcodeTool);
this.registry.registerToolHandler('optimize_mushcode', async (args) => {
return await optimizeMushcodeHandler(args, knowledgeBase);
});
}
if (enabledTools.includes('explain_mushcode')) {
this.registry.registerTool(explainMushcodeTool);
this.registry.registerToolHandler('explain_mushcode', async (args) => {
return await explainMushcodeHandler(args, knowledgeBase);
});
}
if (enabledTools.includes('get_examples')) {
this.registry.registerTool(getExamplesTool);
this.registry.registerToolHandler('get_examples', async (args) => {
return await getExamplesHandler(args, knowledgeBase);
});
}
if (enabledTools.includes('format_mushcode')) {
this.registry.registerTool(formatMushcodeTool);
this.registry.registerToolHandler('format_mushcode', async (args) => {
return await formatMushcodeHandler(args, knowledgeBase);
});
}
if (enabledTools.includes('compress_mushcode')) {
this.registry.registerTool(compressMushcodeTool);
this.registry.registerToolHandler('compress_mushcode', async (args) => {
return await compressMushcodeHandler(args, knowledgeBase);
});
}
}
/**
* Get the tool registry instance
*/
getRegistry() {
return this.registry;
}
/**
* Check if the server is currently running
*/
isServerRunning() {
return this.isRunning;
}
/**
* Start the MCP server
*/
async start() {
if (this.isRunning) {
throw new ProtocolError('Server is already running');
}
try {
// Register tools before starting
await this.registerDefaultTools();
const transport = new StdioServerTransport();
await this.server.connect(transport);
this.isRunning = true;
}
catch (error) {
throw new ProtocolError('Failed to start server', { error: error instanceof Error ? error.message : String(error) });
}
}
/**
* Stop the MCP server
*/
async stop() {
if (!this.isRunning) {
return;
}
try {
await this.server.close();
this.isRunning = false;
}
catch (error) {
throw new ProtocolError('Failed to stop server', { error: error instanceof Error ? error.message : String(error) });
}
}
}
//# sourceMappingURL=protocol.js.map