Skip to main content
Glama
registry.tsβ€’8.64 kB
/** * Tool registry module - handles tool registration mechanics and discovery */ import { ResourceType } from '../../types/attio.js'; import { ToolConfig } from '../tool-types.js'; import { createScopedLogger } from '../../utils/logger.js'; import { isToolAllowed } from '../../config/tool-mode.js'; import { resolveToolName } from '@/config/tool-aliases.js'; // Type for return values that can include special resource markers type ToolConfigResult = { resourceType: ResourceType | 'UNIVERSAL' | 'GENERAL'; toolConfig: ToolConfig; toolType: string; }; // Import consolidated tool configurations from modular files import { companyToolConfigs, companyToolDefinitions, } from '../tool-configs/companies/index.js'; import { peopleToolConfigs, peopleToolDefinitions, } from '../tool-configs/people/index.js'; import { dealToolConfigs, dealToolDefinitions, } from '../tool-configs/deals/index.js'; import { listsToolConfigs, listsToolDefinitions, } from '../tool-configs/lists.js'; import { tasksToolConfigs, tasksToolDefinitions, } from '../tool-configs/tasks.js'; import { recordToolConfigs, recordToolDefinitions, } from '../tool-configs/records/index.js'; import { generalToolConfigs, generalToolDefinitions, } from '../tool-configs/general/index.js'; import { workspaceMembersToolConfigs, workspaceMembersToolDefinitions, } from '../tool-configs/workspace-members.js'; // Import universal tool configurations for consolidated operations import { universalToolConfigs, universalToolDefinitions, } from '../tool-configs/universal/index.js'; /** * Universal tool consolidation (Issue #352): Only expose universal tools * This replaces the legacy resource-specific tools with consolidated universal tools * that can handle all resource types (companies, people, records, tasks) through * a single, consistent interface. * * Legacy tools are kept for backward compatibility but not exposed by default. */ const USE_UNIVERSAL_TOOLS_ONLY = process.env.DISABLE_UNIVERSAL_TOOLS !== 'true'; /** * Consolidated tool configurations from modular files */ export const TOOL_CONFIGS = USE_UNIVERSAL_TOOLS_ONLY ? { // Universal tools for consolidated operations (Issue #352) UNIVERSAL: universalToolConfigs, // Lists are relationship containers - always expose them (Issue #470) [ResourceType.LISTS]: listsToolConfigs, // Workspace members for user discovery (Issue #684) [ResourceType.WORKSPACE_MEMBERS]: workspaceMembersToolConfigs, } : { // Legacy resource-specific tools (deprecated, use DISABLE_UNIVERSAL_TOOLS=true to enable) [ResourceType.COMPANIES]: companyToolConfigs, [ResourceType.PEOPLE]: peopleToolConfigs, [ResourceType.DEALS]: dealToolConfigs, [ResourceType.LISTS]: listsToolConfigs, [ResourceType.TASKS]: tasksToolConfigs, [ResourceType.RECORDS]: recordToolConfigs, [ResourceType.WORKSPACE_MEMBERS]: workspaceMembersToolConfigs, GENERAL: generalToolConfigs, // Add other resource types as needed }; /** * Consolidated tool definitions from modular files */ export const TOOL_DEFINITIONS = USE_UNIVERSAL_TOOLS_ONLY ? { // Universal tools for consolidated operations (Issue #352) UNIVERSAL: universalToolDefinitions, // Lists are relationship containers - always expose them (Issue #470) [ResourceType.LISTS]: listsToolDefinitions, // Workspace members for user discovery (Issue #684) [ResourceType.WORKSPACE_MEMBERS]: workspaceMembersToolDefinitions, } : { // Legacy resource-specific tools (deprecated, use DISABLE_UNIVERSAL_TOOLS=true to enable) [ResourceType.COMPANIES]: companyToolDefinitions, [ResourceType.PEOPLE]: peopleToolDefinitions, [ResourceType.DEALS]: dealToolDefinitions, [ResourceType.LISTS]: listsToolDefinitions, [ResourceType.TASKS]: tasksToolDefinitions, [ResourceType.RECORDS]: recordToolDefinitions, [ResourceType.WORKSPACE_MEMBERS]: workspaceMembersToolDefinitions, GENERAL: generalToolDefinitions, // Add other resource types as needed }; /** * Find the tool config for a given tool name * * @param toolName - The name of the tool * @returns Tool configuration or undefined if not found */ export function findToolConfig(toolName: string): ToolConfigResult | undefined { // Debug logging for tool lookup in development const debugMode = process.env.NODE_ENV === 'development' || process.env.DEBUG; // Debug logging for all tool lookups in development const log = createScopedLogger('tools.registry', 'findToolConfig'); if (debugMode) { log.debug(`Looking for tool: ${toolName}`); } const { name: canonicalToolName } = resolveToolName(toolName); // Search in resource-specific tools first for (const resourceType of Object.values(ResourceType)) { const resourceConfig = TOOL_CONFIGS[resourceType]; if (!resourceConfig) { if (debugMode) { log.debug(`No config found for resource type: ${resourceType}`); } continue; } // For debugging, log all available tools for a resource type if (debugMode) { const toolTypes = Object.keys(resourceConfig); if (toolTypes.includes(canonicalToolName.replace(/-/g, ''))) { log.info( 'Tool might be found under a different name. Available tool types', { toolTypes } ); } // Specific logging for commonly problematic tools const commonProblematicTools = [ 'discover-company-attributes', 'get-company-basic-info', ]; if ( commonProblematicTools.includes(canonicalToolName) && resourceType === ResourceType.COMPANIES ) { const toolTypeKey = canonicalToolName === 'discover-company-attributes' ? 'discoverAttributes' : 'basicInfo'; // Use a type-safe way to check for existence const hasToolType = Object.keys(resourceConfig).includes(toolTypeKey); if (hasToolType) { const config = resourceConfig[toolTypeKey as keyof typeof resourceConfig]; log.info('Found config for legacy mapping', { toolTypeKey, name: (config as ToolConfig).name, hasHandler: typeof (config as ToolConfig).handler === 'function', hasFormatter: typeof (config as ToolConfig).formatResult === 'function', }); } else { log.warn(`${toolTypeKey} not found in ${resourceType} configs`); } } } for (const [toolType, config] of Object.entries(resourceConfig)) { if (config && config.name === canonicalToolName) { if (debugMode) { log.info('Found tool in resource config', { toolName: canonicalToolName, toolType, resourceType, }); } if (isToolAllowed(canonicalToolName)) { return { resourceType: resourceType as ResourceType, toolConfig: config as ToolConfig, toolType, }; } return undefined; } } } // Search in universal tools (high priority for consolidation) const universalConfig = TOOL_CONFIGS.UNIVERSAL; if (universalConfig) { for (const [toolType, config] of Object.entries(universalConfig)) { if (config && config.name === canonicalToolName) { if (debugMode) { log.info('Found universal tool', { toolName: canonicalToolName, toolType, }); } if (isToolAllowed(canonicalToolName)) { return { resourceType: 'UNIVERSAL' as const, toolConfig: config as ToolConfig, toolType, }; } return undefined; } } } // Search in general tools if not found in resource-specific or universal tools const generalConfig = TOOL_CONFIGS.GENERAL; if (generalConfig) { for (const [toolType, config] of Object.entries(generalConfig)) { if (config && config.name === canonicalToolName) { if (debugMode) { log.info('Found general tool', { toolName: canonicalToolName, toolType, }); } if (isToolAllowed(canonicalToolName)) { return { resourceType: 'GENERAL' as const, toolConfig: config as ToolConfig, toolType, }; } return undefined; } } } if (debugMode) { log.warn('Tool not found', { toolName: canonicalToolName }); } return undefined; }

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/kesslerio/attio-mcp-server'

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