Skip to main content
Glama
vibase-ai
by vibase-ai
plugins.ts4.17 kB
import { MessageExtraInfo } from "@modelcontextprotocol/sdk/types.js"; import type { Pool } from "pg"; import type { PostgresSqlTool } from "./validate-config.js"; // Hook types - extensible union export type PluginHook = 'beforeQuery'; // Hook-specific context types export interface BeforeQueryContext { toolName: string; toolConfig: PostgresSqlTool; pool: Pool; parsedArgs: Record<string, any>; extra: MessageExtraInfo; // MessageExtraInfo from MCP SDK query: string; } // Hook-specific result types export interface BeforeQueryResult { pgSettings?: Map<string, string>; } // Hook-specific callback types export type BeforeQueryCallback = (context: BeforeQueryContext) => BeforeQueryResult | Promise<BeforeQueryResult>; // Type mappings for hooks (extensible design) export interface HookCallbacks { beforeQuery: BeforeQueryCallback; } export interface HookContexts { beforeQuery: BeforeQueryContext; } export interface HookResults { beforeQuery: BeforeQueryResult; } // Plugin interface with structured callbacks export interface Plugin { name: string; callbacks: Partial<HookCallbacks>; } // Plugin registry with type-safe hook management export class PluginRegistry { private callbacksByHook = new Map<PluginHook, Array<{ pluginName: string; callback: HookCallbacks[PluginHook] }>>(); private registeredPlugins = new Map<string, Plugin>(); register(plugin: Plugin): void { // Store the plugin for reference this.registeredPlugins.set(plugin.name, plugin); // Register each callback by hook for (const [hookName, callback] of Object.entries(plugin.callbacks)) { const hook = hookName as PluginHook; if (!this.callbacksByHook.has(hook)) { this.callbacksByHook.set(hook, []); } this.callbacksByHook.get(hook)!.push({ pluginName: plugin.name, callback: callback as HookCallbacks[PluginHook] }); } } // Legacy method for backward compatibility (deprecated) registerHook<T extends PluginHook>(hook: T, callback: HookCallbacks[T], pluginName?: string): void { if (!this.callbacksByHook.has(hook)) { this.callbacksByHook.set(hook, []); } this.callbacksByHook.get(hook)!.push({ pluginName: pluginName || 'anonymous', callback }); } async executeHook<T extends PluginHook>(hook: T, context: HookContexts[T]): Promise<HookResults[T]> { const callbacks = this.callbacksByHook.get(hook) || []; if (hook === 'beforeQuery') { return this.executeBeforeQueryHook(context as BeforeQueryContext, callbacks as Array<{ pluginName: string; callback: BeforeQueryCallback }>) as HookResults[T]; } // Future hooks would be handled here throw new Error(`Unknown hook: ${hook}`); } private async executeBeforeQueryHook(context: BeforeQueryContext, callbacks: Array<{ pluginName: string; callback: BeforeQueryCallback }>): Promise<BeforeQueryResult> { const mergedResult: BeforeQueryResult = { pgSettings: new Map<string, string>() }; // Execute all callbacks and merge their results for (const { pluginName, callback } of callbacks) { try { const result = await callback(context); // Merge pgSettings (last plugin wins for conflicts) if (result.pgSettings) { for (const [key, value] of result.pgSettings.entries()) { mergedResult.pgSettings!.set(key, value); } } } catch (error) { console.error(`Plugin '${pluginName}' failed during beforeQuery hook:`, error); throw error; } } return mergedResult; } // Utility methods getRegisteredPlugins(): Plugin[] { return Array.from(this.registeredPlugins.values()); } getPlugin(name: string): Plugin | undefined { return this.registeredPlugins.get(name); } } // Plugin interface for dependency injection export interface Plugins { register(plugin: Plugin): void; registerHook<T extends PluginHook>(hook: T, callback: HookCallbacks[T], pluginName?: string): void; // Legacy support executeHook<T extends PluginHook>(hook: T, context: HookContexts[T]): Promise<HookResults[T]>; }

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/vibase-ai/vibase'

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