UNPKG

defect-inspection-tools-mcp-server

Version:
122 lines (121 loc) 5.12 kB
#!/usr/bin/env node import dotenv from 'dotenv'; import path from 'path'; import fs from 'fs'; import { fileURLToPath } from 'url'; import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { toolDefinitions } from "./tools/schemas.js"; import * as toolHandlers from "./tools/handlers.js"; import * as resourceHandlers from "./resources/handlers.js"; import { resourceDefinitions } from "./resources/resources.js"; // Load environment-specific .env file const NODE_ENV = process.env.NODE_ENV || 'development'; const envPath = path.resolve(process.cwd(), `.env.${NODE_ENV}`); const defaultEnvPath = path.resolve(process.cwd(), '.env'); if (fs.existsSync(envPath)) { dotenv.config({ path: envPath }); } else { dotenv.config({ path: defaultEnvPath }); } // Register tools export function registerTools(server) { Object.values(toolDefinitions).forEach((tool) => { const handler = toolHandlers[tool.name]; if (!handler) { throw new Error(`Handler not found for tool: ${tool.name}`); } server.tool(tool.name, tool.description, tool.schema, handler); }); } // Register resources export function registerResources(server) { Object.values(resourceDefinitions).forEach((resource) => { const handler = resourceHandlers[resource.method]; if (!handler) { throw new Error(`Handler not found for resource: ${resource.method}`); } console.error(`Registering resource: ${resource.name} at ${resource.uri}`); // Convert URI format from <param> to {param} for ResourceTemplate const templateUri = resource.uri.replace(/<([^>]+)>/g, '{$1}'); const template = new ResourceTemplate(templateUri, { list: undefined, // Not listing all resources }); try { server.resource(resource.name, template, { description: resource.description, mimeType: resource.mimeType, }, async (uri, variables) => { console.error(`Resource read requested: ${uri.toString()}`); console.error(`Variables:`, JSON.stringify(variables)); // Extract the identifier from the variables object // For "user://details/{user_id}", variables will contain { user_id: "..." } // For "vessel://managers/{imo}", variables will contain { imo: "..." } const userId = variables.user_id; const imo = variables.imo; const identifier = (Array.isArray(userId) ? userId[0] : userId) || (Array.isArray(imo) ? imo[0] : imo) || ''; console.error(`Calling handler with identifier: ${identifier}`); const result = await handler(identifier); return { contents: [ { uri: uri.toString(), mimeType: resource.mimeType, text: JSON.stringify(result, null, 2), }, ], }; }); console.error(`✓ Successfully registered resource: ${resource.name}`); } catch (error) { console.error(`✗ Failed to register resource: ${resource.name}`, error); throw error; } }); } // Create server instance // Get the directory of the current module (for ES modules) const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Read package.json from the package root // When built, index.js is in build/, so package.json is one level up // When installed via npm, the structure is the same let packageJsonPath = path.resolve(__dirname, '..', 'package.json'); // Fallback: if not found, try current directory (for development) if (!fs.existsSync(packageJsonPath)) { packageJsonPath = path.resolve(__dirname, 'package.json'); } // If still not found, try process.cwd() as last resort if (!fs.existsSync(packageJsonPath)) { packageJsonPath = path.resolve(process.cwd(), 'package.json'); } const packageJson = fs.readFileSync(packageJsonPath, 'utf8'); const packageJsonObject = JSON.parse(packageJson); const server = new McpServer({ name: packageJsonObject.name, version: packageJsonObject.version, }); // Register tools and resources console.error("Registering tools..."); registerTools(server); console.error("Registering resources..."); registerResources(server); console.error(`Registered ${Object.keys(resourceDefinitions).length} resources`); async function main() { try { const transport = new StdioServerTransport(); await server.connect(transport); console.error(`${packageJsonObject.name} MCP Server running on stdio`); } catch (error) { console.error("Error connecting transport:", error); throw error; } } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });