Skip to main content
Glama
portel-dev

NCP - Natural Context Provider

by portel-dev
cli-indexer.ts4.47 kB
/** * CLI Tool Indexer * Indexes CLI tools for discovery through NCP's search */ import { CLIParser, CLIToolInfo, CLIOperation } from './cli-parser.js'; import { CachePatcher, Tool } from '../cache/cache-patcher.js'; import { logger } from '../utils/logger.js'; export interface CLIToolConfig { baseCommand: string; description?: string; operations?: CLIOperation[]; // Optional pre-defined operations } export class CLIIndexer { private parser: CLIParser; private cachePatcher: CachePatcher; constructor() { this.parser = new CLIParser(); this.cachePatcher = new CachePatcher(); } /** * Index a CLI tool for discovery * Returns the number of operations/tools indexed */ async indexCliTool(config: CLIToolConfig): Promise<number> { try { logger.info(`🔍 Indexing CLI tool: ${config.baseCommand}`); // Check if tool is available const isAvailable = await this.parser.isCliAvailable(config.baseCommand); if (!isAvailable) { throw new Error(`CLI tool not found: ${config.baseCommand}. Please install it first.`); } // Parse tool to get operations let toolInfo: CLIToolInfo; if (config.operations && config.operations.length > 0) { // Use pre-defined operations toolInfo = { baseCommand: config.baseCommand, description: config.description || `CLI tool: ${config.baseCommand}`, operations: config.operations }; } else { // Parse automatically toolInfo = await this.parser.parseCliTool(config.baseCommand); } logger.info(`📦 Found ${toolInfo.operations.length} operations in ${config.baseCommand}`); // Convert operations to Tool format for cache const tools: Tool[] = toolInfo.operations.map(op => ({ name: op.name, description: op.description, inputSchema: { type: 'object', properties: { command_template: { type: 'string', description: op.commandTemplate || `${config.baseCommand} command template`, default: op.commandTemplate }, parameters: { type: 'object', description: 'Parameters to substitute in command template' } }, // Include examples and keywords in schema for better discovery examples: op.examples || [], keywords: op.keywords || [] } })); // Add to tool metadata cache const mcpConfig = { command: config.baseCommand, args: [], env: {} }; const serverInfo = { name: config.baseCommand, version: toolInfo.version || '1.0.0', description: toolInfo.description || `CLI tool: ${config.baseCommand}` }; await this.cachePatcher.patchAddMCP( config.baseCommand, mcpConfig, tools, serverInfo ); logger.info(`✅ Indexed ${tools.length} tools from ${config.baseCommand}`); // Note: Embeddings will be generated automatically when the orchestrator // loads these tools from the cache during initialization return tools.length; } catch (error: any) { logger.error(`Failed to index CLI tool ${config.baseCommand}:`, error); throw error; } } /** * Remove CLI tool from index */ async removeCliTool(baseCommand: string): Promise<void> { logger.info(`🗑️ Removing CLI tool: ${baseCommand}`); await this.cachePatcher.patchRemoveMCP(baseCommand); await this.cachePatcher.patchRemoveEmbeddings(baseCommand); logger.info(`✅ Removed ${baseCommand} from index`); } /** * Check if CLI tool is already indexed */ async isIndexed(baseCommand: string): Promise<boolean> { const cache = await this.cachePatcher.loadToolMetadataCache(); return baseCommand in cache.mcps; } /** * List all indexed CLI tools */ async listIndexedCliTools(): Promise<string[]> { const cache = await this.cachePatcher.loadToolMetadataCache(); const cliTools: string[] = []; for (const mcpName in cache.mcps) { const mcp = cache.mcps[mcpName]; // CLI tools have empty args and just a command if (mcp.configHash && !mcp.tools.some(t => t.inputSchema?.type === 'stdin')) { // Simple heuristic: if it looks like a CLI tool cliTools.push(mcpName); } } return cliTools; } }

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/portel-dev/ncp'

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