Skip to main content
Glama
index.ts3.59 kB
import type { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { CallToolRequestSchema, ListToolsRequestSchema, type CallToolRequest, type Tool, type ServerResult } from "@modelcontextprotocol/sdk/types.js"; import { DatabaseService } from "../services/database.js"; import AjvModule from "ajv"; import { logger } from "../services/logger.js"; // Import tools import { tool as queryTool } from './steampipe_query.js'; import { tool as tableListTool } from './steampipe_table_list.js'; import { tool as tableShowTool } from './steampipe_table_show.js'; import { tool as pluginListTool } from './steampipe_plugin_list.js'; import { tool as pluginShowTool } from './steampipe_plugin_show.js'; // Initialize JSON Schema validator const Ajv = AjvModule.default || AjvModule; const ajv = new Ajv(); // Define tool type type DbTool = Tool & { handler: (db: DatabaseService, args: any) => Promise<ServerResult>; }; // Export all tools for server capabilities export const tools = { steampipe_query: queryTool as DbTool, steampipe_table_list: tableListTool as DbTool, steampipe_table_show: tableShowTool as DbTool, steampipe_plugin_list: pluginListTool as DbTool, steampipe_plugin_show: pluginShowTool as DbTool, } as const; // Initialize tool handlers export function setupTools(server: Server, db: DatabaseService) { // Register tool list handler server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: Object.entries(tools).map(([name, tool]) => ({ name, description: tool.description, inputSchema: tool.inputSchema })) }; }); // Register tool handlers server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest) => { try { const { name, arguments: args = {} } = request.params; const tool = tools[name as keyof typeof tools]; if (!tool) { throw new Error(`Unknown tool: ${name}`); } // Validate arguments against the tool's schema if (tool.inputSchema) { const validate = ajv.compile(tool.inputSchema); if (!validate(args)) { logger.error(`Invalid arguments for tool ${name}:`, validate.errors); // Format validation errors in a user-friendly way const errors = validate.errors || []; const errorMessages = errors.map(err => { const path = err.instancePath.replace(/^\//, '') || 'input'; switch (err.keyword) { case 'required': return `Missing required field: ${err.params.missingProperty}`; case 'type': return `${path} must be a ${err.params.type}`; case 'enum': return `${path} must be one of: ${err.params.allowedValues?.join(', ')}`; case 'additionalProperties': return `Unexpected field: ${err.params.additionalProperty}`; default: return `${path}: ${err.message}`; } }); return { content: [{ type: "text", text: errorMessages.join('\n') }], isError: true }; } } // Call the tool handler with database return await (tool as DbTool).handler(db, args); } catch (error) { logger.error('Error executing tool:', error); return { content: [{ type: "text", text: error instanceof Error ? error.message : 'An unknown error occurred' }], isError: true }; } }); }

Implementation Reference

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/turbot/steampipe-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server