@toponextech/smartembed-mcp-server
Version:
MCP server for intelligent embedded development with PlatformIO - AI-powered project creation, error diagnosis, and device detection
177 lines • 6.28 kB
JavaScript
"use strict";
/**
* SmartEmbed MCP Server Implementation
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.SmartEmbedServer = void 0;
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const index_js_2 = require("./tools/index.js");
class SmartEmbedServer {
server;
transport;
toolRegistry;
_isRunning = false;
debug;
constructor() {
// Enable debug logging if DEBUG environment variable is set
this.debug = process.env.DEBUG === 'true' || process.env.DEBUG === '1';
// Initialize MCP Server with metadata
this.server = new index_js_1.Server({
name: 'smartembed-mcp-server',
version: '0.1.0',
}, {
capabilities: {
tools: {},
},
});
this.transport = new stdio_js_1.StdioServerTransport();
this.toolRegistry = new index_js_2.DefaultToolRegistry();
// Register built-in tools
this.registerBuiltinTools();
// Setup handlers
this.setupHandlers();
this.setupLifecycleManagement();
this.log('SmartEmbed MCP Server initialized');
}
registerBuiltinTools() {
// Register core tools
this.toolRegistry.register(index_js_2.projectCreationTool);
this.toolRegistry.register(index_js_2.errorDiagnosisTool);
this.toolRegistry.register(index_js_2.suggestionTool);
this.log(`Registered ${this.toolRegistry.getToolNames().length} built-in tools`);
}
setupHandlers() {
// List available tools
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
this.log('Received list tools request', 'debug');
const tools = this.toolRegistry.getDefinitions();
this.log(`Returning ${tools.length} tools`, 'debug');
return { tools };
});
// Handle tool calls
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
this.log(`Received tool call: ${name}`, 'info');
this.log(`Arguments: ${JSON.stringify(args)}`, 'debug');
const handler = this.toolRegistry.getHandler(name);
if (!handler) {
throw new Error(`Unknown tool: ${name}`);
}
try {
const result = await handler(args);
this.log(`Tool ${name} executed successfully`, 'info');
return result;
}
catch (error) {
this.log(`Tool ${name} failed: ${error}`, 'error');
throw error;
}
});
this.log('Request handlers configured');
}
/**
* Start the MCP server and begin listening for requests
*/
async start() {
if (this._isRunning) {
this.log('Server is already running', 'warn');
return;
}
try {
this.log('Starting SmartEmbed MCP Server...');
await this.server.connect(this.transport);
this._isRunning = true;
this.log('SmartEmbed MCP Server started successfully');
}
catch (error) {
this.log(`Failed to start server: ${error}`, 'error');
throw error;
}
}
/**
* Stop the MCP server gracefully
*/
async stop() {
if (!this._isRunning) {
this.log('Server is not running', 'warn');
return;
}
try {
this.log('Stopping SmartEmbed MCP Server...');
await this.server.close();
this._isRunning = false;
this.log('SmartEmbed MCP Server stopped successfully');
}
catch (error) {
this.log(`Error while stopping server: ${error}`, 'error');
throw error;
}
}
/**
* Setup lifecycle management for graceful shutdown
*/
setupLifecycleManagement() {
// Handle graceful shutdown on process termination
process.on('SIGTERM', async () => {
this.log('Received SIGTERM, shutting down gracefully...');
await this.stop();
process.exit(0);
});
process.on('SIGINT', async () => {
this.log('Received SIGINT, shutting down gracefully...');
await this.stop();
process.exit(0);
});
// Handle unexpected errors
process.on('uncaughtException', (error) => {
this.log(`Uncaught exception: ${error}`, 'error');
process.exit(1);
});
process.on('unhandledRejection', (reason, promise) => {
this.log(`Unhandled rejection at ${promise}: ${reason}`, 'error');
process.exit(1);
});
}
/**
* Get the current running state of the server
*/
get isRunning() {
return this._isRunning;
}
/**
* Get tool definitions for testing and debugging
*/
getToolDefinitions() {
return this.toolRegistry.getDefinitions();
}
/**
* Handle tool calls directly (useful for testing)
*/
async handleToolCall(name, args) {
const handler = this.toolRegistry.getHandler(name);
if (!handler) {
throw new Error(`Unknown tool: ${name}`);
}
return await handler(args);
}
/**
* Logging utility that writes to stderr to avoid interfering with stdio transport
*/
log(message, level = 'info') {
const timestamp = new Date().toISOString();
const prefix = `[${timestamp}] [${level.toUpperCase()}]`;
// Always log errors and warnings
if (level === 'error' || level === 'warn') {
console.error(`${prefix} ${message}`);
return;
}
// Log info messages in production, all messages in debug mode
if (level === 'info' || (level === 'debug' && this.debug)) {
console.error(`${prefix} ${message}`);
}
}
}
exports.SmartEmbedServer = SmartEmbedServer;
//# sourceMappingURL=server.js.map