Skip to main content
Glama

MCP Firebird

create-server.ts9.11 kB
/** * MCP Firebird Server Creation (LEGACY) * * @deprecated This module uses the legacy Server class with setRequestHandler. * For new implementations, use mcp-server.ts which uses the modern McpServer class * with registerTool(), registerPrompt(), and registerResource() methods. * * This module is kept for backward compatibility only. */ import { z } from 'zod'; import UrlPattern from 'url-pattern'; import { zodToJsonSchema } from 'zod-to-json-schema'; // --- SDK Imports --- import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListResourceTemplatesRequestSchema, ToolSchema } from "@modelcontextprotocol/sdk/types.js"; // --- Local Imports --- import { createLogger } from '../utils/logger.js'; import { MCPError } from '../utils/errors.js'; import { type ToolDefinition as DbToolDefinition } from '../tools/database.js'; import { type ToolDefinition as MetaToolDefinition } from '../tools/metadata.js'; import { type PromptDefinition } from '../prompts/types.js'; import { setupDatabaseResources, type ResourceDefinition } from '../resources/database.js'; import { setupDatabaseTools } from '../tools/database.js'; import { setupMetadataTools } from '../tools/metadata.js'; import { setupSimpleTools } from '../tools/simple.js'; import { setupDatabasePrompts } from '../prompts/database.js'; import { setupSqlPrompts } from '../prompts/sql.js'; import { initSecurity } from '../security/index.js'; import pkg from '../../package.json' with { type: 'json' }; const logger = createLogger('server:create'); /** * Create and configure the MCP Firebird server * @returns A promise that resolves with the server instance */ export async function createServer() { logger.info(`Creating MCP Firebird Server - Name: ${pkg.name}, Version: ${pkg.version}`); try { // 1. Initialize security module logger.info('Initializing security module...'); await initSecurity(); // 2. Load tools, prompts and resources logger.info('Loading tool, prompt and resource definitions...'); const databaseTools = setupDatabaseTools(); const metadataTools = setupMetadataTools(databaseTools); const simpleTools = setupSimpleTools(); const databasePrompts = setupDatabasePrompts(); const sqlPrompts = setupSqlPrompts(); const allResources: Map<string, ResourceDefinition> = setupDatabaseResources(); const allPrompts = new Map<string, PromptDefinition>([...databasePrompts, ...sqlPrompts]); const allTools = new Map<string, DbToolDefinition | MetaToolDefinition | any>([...databaseTools, ...metadataTools, ...simpleTools]); // Log loaded prompts logger.info('Loaded prompts:'); allPrompts.forEach((prompt, name) => { logger.info(` - ${name}: ${prompt.description}`); }); logger.info( `Loaded: ${allTools.size} tools, ${allPrompts.size} prompts, ${allResources.size} resources.` ); // 3. Create MCP server instance logger.info('Creating MCP server instance...'); const server = new Server( { name: pkg.name, version: pkg.version }, { capabilities: { tools: { list: true, execute: true }, prompts: { list: true, get: true, call: true }, resources: { list: true, read: true }, resourceTemplates: { list: true } } } ); // 4. Register handlers // Handler for listing tools server.setRequestHandler(ListToolsRequestSchema, async () => { logger.info('Received ListTools request'); const tools = Array.from(allTools.entries()).map(([name, tool]) => ({ name, description: tool.description, inputSchema: zodToJsonSchema(tool.inputSchema) })); return { tools }; }); // Handler for calling tools server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; logger.info(`Received CallTool request: ${name}`); const tool = allTools.get(name); if (!tool) { throw new Error(`Unknown tool: ${name}`); } try { // Parse and validate the arguments const validatedArgs = tool.inputSchema.parse(args); // Call the tool handler const result = await tool.handler(validatedArgs); // Return the result directly return result; } catch (error) { logger.error(`Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`, { error }); throw error; } }); // Handler for listing prompts server.setRequestHandler(ListPromptsRequestSchema, async () => { logger.info('Received ListPrompts request'); const prompts = Array.from(allPrompts.entries()).map(([name, prompt]) => ({ name, description: prompt.description, inputSchema: zodToJsonSchema(prompt.inputSchema) })); return { prompts }; }); // Handler for getting a specific prompt server.setRequestHandler(GetPromptRequestSchema, async (request) => { const { name } = request.params; logger.info(`Received GetPrompt request: ${name}`); const prompt = allPrompts.get(name); if (!prompt) { throw new Error(`Unknown prompt: ${name}`); } return { name, description: prompt.description, inputSchema: zodToJsonSchema(prompt.inputSchema) }; }); // Handler for listing resources server.setRequestHandler(ListResourcesRequestSchema, async () => { logger.info('Received ListResources request'); const resources = Array.from(allResources.keys()).map(uriTemplate => ({ uri: uriTemplate, name: `Resource: ${uriTemplate}`, mimeType: "application/json" })); return { resources }; }); // Handler for reading a specific resource server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params; logger.info(`Received ReadResource request: ${uri}`); let matchedResourceDef: ResourceDefinition | undefined; let uriParams: Record<string, string> = {}; for (const [uriTemplate, definition] of allResources.entries()) { const pattern = new UrlPattern(uriTemplate); const match = pattern.match(uri); if (match) { matchedResourceDef = definition; uriParams = match; break; } } if (!matchedResourceDef) { throw new Error(`Unknown resource or URI pattern does not match: ${uri}`); } try { const result = await matchedResourceDef.handler(uriParams); return { contents: [ { uri: request.params.uri, mimeType: "application/json", text: JSON.stringify(result, null, 2) } ] }; } catch (error) { logger.error(`Error accessing resource ${uri}: ${error instanceof Error ? error.message : String(error)}`, { error }); throw error; } }); // Handler for listing resource templates server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => { logger.info('Received ListResourceTemplates request'); // For now, return an empty list as we don't have any templates defined return { resourceTemplates: [] }; }); // Return the server instance return { server }; } catch (error) { if (error instanceof MCPError) { logger.error(`Error creating server: ${error.message}`, { type: error.type, context: error.context, originalError: error.originalError }); } else if (error instanceof Error) { logger.error(`Error creating server: ${error.message}`, { stack: error.stack }); } else { logger.error(`Error creating server: ${String(error)}`); } throw error; } }

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/PuroDelphi/mcpFirebird'

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