@trishchuk/ai-think-gate-mcp
Version:
Model Context Protocol (MCP) server that provides AI-powered thinking and code architecture tools
165 lines (164 loc) • 5.57 kB
JavaScript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { logService } from '../services/logging-service.js';
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { toolRegistry } from './registry.js';
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
/**
* MCP server implementation
*/
export class MCPServer {
constructor() {
this.server = new Server({
name: "thinkgate-mcp",
version: "1.0.0",
}, {
capabilities: {
tools: {},
}
});
}
/**
* Start the MCP server
*/
async start() {
try {
// Connect to transport
const transport = new StdioServerTransport();
await this.server.connect(transport);
// Set up request handlers
this.setupRequestHandlers();
logService.log(`ThinkGate-MCP server started`);
}
catch (error) {
logService.error(`Failed to start MCP server: ${error}`);
throw error;
}
}
/**
* Set up request handlers for the server
*/
setupRequestHandlers() {
// Handle tools listing request
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
logService.debug("Handling tools/list request");
// Convert to expected type format using type assertion
const tools = toolRegistry.getAllTools();
return { tools };
});
// Handle tool call request
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args, _meta } = request.params;
logService.log(`Handling tools/call request for ${name}`);
const tool = toolRegistry.getToolByName(name);
if (!tool) {
return this.createErrorResponse(`Tool '${name}' not found`);
}
try {
const result = await this.executeToolWithProgress(tool, args, _meta?.progressToken);
return {
content: result.content,
isError: result.isError
};
}
catch (error) {
logService.error(`Error executing tool ${name}: ${error}`);
return this.createErrorResponse(`Error executing tool ${name}: ${error?.message || 'Unknown error'}`);
}
});
}
/**
* Execute a tool with progress updates
*/
async executeToolWithProgress(tool, args, progressToken) {
try {
// Send initial progress if token is provided
if (progressToken) {
await this.sendProgressNotification(progressToken, 0, 100, `Starting ${tool.name}...`);
}
// Execute the tool
const result = await tool.execute(args);
// Send completion progress if token is provided
if (progressToken) {
await this.sendProgressNotification(progressToken, 100, 100, `Completed ${tool.name}`);
}
return result;
}
catch (error) {
// Send error progress if token is provided
if (progressToken) {
await this.sendProgressNotification(progressToken, 100, 100, `Error in ${tool.name}: ${error?.message || 'Unknown error'}`);
}
throw error;
}
}
/**
* Send a progress notification
*/
async sendProgressNotification(progressToken, progress, total, message) {
try {
await this.server.notification({
method: "notifications/progress",
params: {
progressToken,
progress,
total,
message
}
});
}
catch (error) {
logService.warn(`Failed to send progress notification: ${error}`);
}
}
/**
* Create an error response
*/
createErrorResponse(errorMessage) {
return {
content: [{
type: "text",
text: errorMessage,
annotations: {
priority: 1.0,
audience: ["user", "assistant"]
}
}],
isError: true
};
}
/**
* Send a notification that tools have changed
*/
async sendToolsChangedNotification() {
// Debounce notification to avoid sending too many
if (this.notifyTimeout) {
clearTimeout(this.notifyTimeout);
}
this.notifyTimeout = setTimeout(async () => {
try {
await this.server.notification({
method: "notifications/tools/changed",
params: {}
});
logService.debug("Sent tools changed notification");
}
catch (error) {
logService.warn(`Failed to send tools changed notification: ${error}`);
}
}, 500);
}
/**
* Stop the MCP server
*/
async stop() {
try {
await this.server.close();
logService.log("MCP server stopped");
}
catch (error) {
logService.error(`Error stopping MCP server: ${error}`);
}
}
}
// Export a singleton instance
export const mcpServer = new MCPServer();