Skip to main content
Glama
index.ts3.85 kB
/** * Tool Documentation Controller * * Main entry point for the documentation system that coordinates * validation, command execution, and caching of tool documentation. */ import type { DocumentationResponse, ToolSelection } from '@/types/index'; import { validateToolName } from './security'; import { validateProjectPath, confirmDirectoryExists } from './path-validator'; import { isToolExecutable } from './command-executor'; import { docCache } from './cache'; import { getToolVersion } from './version-fetcher'; import { getToolHelpText } from './help-fetcher'; import { logger } from './logger'; import { getToolInfo } from './path-scanner'; import { isPackageManagerCommand, getPackageManagerInstallInstructions } from './tool-types'; import { ERROR_MESSAGES } from '@/constants'; /** * Fetches documentation for a command-line tool * @param tool Tool selection containing name and project path * @returns Promise<DocumentationResponse> */ export async function fetchToolDocumentation(tool: ToolSelection): Promise<DocumentationResponse> { // Security: Validate project path first if (!await validateProjectPath(tool.projectPath)) { logger.warn(`Invalid project path: ${tool.projectPath}`); return { success: false, error: ERROR_MESSAGES.INVALID_PROJECT_PATH }; } try { // Get tool info from our registry first const toolInfo = await getToolInfo(tool.projectPath, tool.name); if (!toolInfo) { const baseCommand = tool.name.split(' ')[0]; const isPackageManager = isPackageManagerCommand(tool.name); logger.warn(`Tool not found: ${tool.name}`); return { success: false, error: isPackageManager ? `Package manager "${baseCommand}" not found. ${getPackageManagerInstallInstructions(baseCommand)}\n` + 'Make sure the package manager is available in your PATH after installation.' : ERROR_MESSAGES.TOOL_NOT_FOUND(tool.name) }; } // Security: Now validate the tool name format if (!await validateToolName(tool.name, tool.projectPath)) { logger.warn(`Invalid tool name: ${tool.name}`); return { success: false, error: ERROR_MESSAGES.INVALID_TOOL_NAME(tool.name) }; } // Check if tool is executable const isExecutable = await isToolExecutable(toolInfo); if (!isExecutable) { logger.warn(`Tool not executable: ${tool.name}`); return { success: false, error: ERROR_MESSAGES.TOOL_NOT_EXECUTABLE(tool.name) }; } // SECURITY: Confirm directory exists and is accessible const dirExists = await confirmDirectoryExists(tool.projectPath); if (!dirExists) { logger.warn(`Directory not accessible: ${tool.projectPath}`); return { success: false, error: ERROR_MESSAGES.INVALID_PROJECT_PATH }; } // Check cache first const cached = docCache.get(tool.name, tool.projectPath); if (cached) { return cached; } // Fetch version and help text using the full tool info const version = await getToolVersion(toolInfo, tool.projectPath); const helpText = await getToolHelpText(toolInfo, tool.projectPath); const response: DocumentationResponse = { success: true, data: { name: tool.name, version, helpText, lastUpdated: Date.now() } }; // Cache the result docCache.set(tool.name, tool.projectPath, response); return response; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.error(`Error fetching documentation for ${tool.name}:`, error); return { success: false, error: `Failed to retrieve documentation: ${errorMessage}. Please ensure the command is valid and try again.` }; } }

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/patelnav/my-tools-mcp'

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