Skip to main content
Glama

MCP Firebird

smithery.ts6.55 kB
/** * Smithery entry point for MCP Firebird * This file exports a function that creates and configures the MCP server * for deployment on Smithery platform */ import { z } from 'zod'; import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { setupDatabaseTools } from './tools/database.js'; import { setupMetadataTools } from './tools/metadata.js'; import { setupDatabasePrompts } from './prompts/database.js'; import { setupSqlPrompts } from './prompts/sql.js'; import { createLogger } from './utils/logger.js'; import pkg from '../package.json' with { type: 'json' }; const logger = createLogger('smithery'); // Configuration schema for Smithery export const configSchema = z.object({ host: z.string().default('localhost').describe('Hostname or IP address of the Firebird database server'), port: z.number().default(3050).describe('Port number for the Firebird database'), database: z.string().describe('Absolute path to the Firebird database file'), user: z.string().default('SYSDBA').describe('Database username for authentication'), password: z.string().default('masterkey').describe('Database password for authentication'), useNativeDriver: z.boolean().default(false).describe('Enable native driver for wire encryption support'), logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info').describe('Logging verbosity level') }); export type Config = z.infer<typeof configSchema>; /** * Main entry point for Smithery deployment * This function is called by Smithery CLI to create the MCP server instance */ export default function ({ config }: { config: Config }) { logger.info('Initializing MCP Firebird server for Smithery', { config: { ...config, password: '[REDACTED]' } }); // Set environment variables from config process.env.FIREBIRD_HOST = config.host; process.env.FIREBIRD_PORT = String(config.port); process.env.FIREBIRD_DATABASE = config.database; process.env.FIREBIRD_USER = config.user; process.env.FIREBIRD_PASSWORD = config.password; process.env.USE_NATIVE_DRIVER = String(config.useNativeDriver); process.env.LOG_LEVEL = config.logLevel; // Load tools and prompts const databaseTools = setupDatabaseTools(); const metadataTools = setupMetadataTools(databaseTools); const databasePrompts = setupDatabasePrompts(); const sqlPrompts = setupSqlPrompts(); const allPrompts = new Map([...databasePrompts, ...sqlPrompts]); const allTools = new Map([...databaseTools, ...metadataTools]); // Create MCP server instance with modern capabilities const server = new McpServer({ name: pkg.name, version: pkg.version, capabilities: { tools: { listChanged: true }, prompts: { listChanged: true }, resources: { listChanged: true, subscribe: false } } }); // Register tools for (const [name, tool] of allTools.entries()) { // Extract the shape from ZodObject if available let inputSchema = {}; if (tool.inputSchema) { if (tool.inputSchema instanceof z.ZodObject) { inputSchema = tool.inputSchema.shape; } else if (typeof tool.inputSchema === 'object') { inputSchema = tool.inputSchema; } } server.registerTool( name, { title: tool.title || name, description: tool.description, inputSchema: inputSchema }, async (args: any): Promise<{ content: any[], isError?: boolean }> => { try { const result = await tool.handler(args); if (typeof result === 'object' && result !== null && 'content' in result) { return result; } return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } catch (error) { logger.error(`Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`, { error }); const message = error instanceof Error ? error.message : 'Unknown error'; return { content: [{ type: "text", text: `Error executing tool ${name}: ${message}` }], isError: true }; } } ); } // Register prompts for (const [name, promptDef] of allPrompts.entries()) { // Extract the shape from ZodObject if available let argsSchema = {}; if (promptDef.inputSchema) { if (promptDef.inputSchema instanceof z.ZodObject) { argsSchema = promptDef.inputSchema.shape; } else if (typeof promptDef.inputSchema === 'object') { argsSchema = promptDef.inputSchema; } } server.registerPrompt( name, { title: promptDef.title || name, description: promptDef.description, argsSchema: argsSchema }, async (args: any) => { try { let result; if (!args || Object.keys(args).length === 0) { result = { messages: [ { role: 'assistant', content: { type: 'text', text: `Prompt '${name}' metadata: ${promptDef.description}` } } ] }; } else { result = await promptDef.handler(args); } if (!result || !result.messages || !Array.isArray(result.messages)) { return { messages: [ { role: 'assistant', content: { type: 'text', text: `Internal error: invalid response format` } } ] }; } const safeMessages = result.messages.map((msg: any) => ({ role: (msg.role === 'user' || msg.role === 'assistant') ? msg.role : 'assistant', content: (msg.content && typeof msg.content === 'object' && msg.content.type === 'text') ? msg.content : { type: 'text', text: String(msg.content) } })); return { messages: safeMessages }; } catch (error) { logger.error(`Error executing prompt ${name}: ${error instanceof Error ? error.message : String(error)}`, { error }); const message = error instanceof Error ? error.message : 'Unknown error'; return { messages: [ { role: 'assistant', content: { type: 'text', text: `Error executing prompt ${name}: ${message}` } } ] }; } } ); } logger.info('MCP Firebird server initialized successfully'); return server.server; }

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