Skip to main content
Glama
index.ts4.84 kB
import { ToolDefinition, ToolResponse } from '../types.js'; import { Config } from '../../config/config.js'; import { execFile } from 'child_process'; import { promisify } from 'util'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; const execFileAsync = promisify(execFile); const __dirname = dirname(fileURLToPath(import.meta.url)); const WRAPPER_PATH = join(__dirname, '..', '..', '..', 'bin', 'EverythingWrapper.exe'); // 验证 wrapper 路径是否存在 import { existsSync } from 'fs'; if (!existsSync(WRAPPER_PATH)) { console.error(`找不到 Everything Wrapper: ${WRAPPER_PATH}`); } interface SearchResult { name: string; path: string; fullPath: string; size: number; dateModified: string; isFolder: boolean; attributes: string; } interface SearchResponse { results: SearchResult[]; totalResults: number; offset: number; maxResults: number; } // Everything 管理器类 class EverythingManager { constructor(private readonly config: Config) {} private async searchFiles(pattern: string, maxResults?: number, offset?: number): Promise<SearchResponse> { try { // 只传递搜索模式,让 wrapper 处理默认值 const args = [pattern]; // 如果指定了 maxResults,添加到参数 if (maxResults !== undefined) { args.push(maxResults.toString()); } // 如果指定了 offset,添加到参数 if (offset !== undefined) { args.push(offset.toString()); } console.error(`执行搜索命令: ${WRAPPER_PATH} ${args.join(' ')}`); // 执行搜索 const { stdout, stderr } = await execFileAsync(WRAPPER_PATH, args, {}); if (stderr) { console.error(`搜索错误: ${stderr}`); } console.error(`搜索输出: ${stdout}`); // 直接返回解析后的结果 return JSON.parse(stdout); } catch (error: any) { // 检查 wrapper 是否存在 if (error.message.includes('ENOENT')) { console.error('Wrapper 路径:', WRAPPER_PATH); console.error('当前目录:', process.cwd()); throw new Error(`找不到 Everything 包装器,请确认程序完整性`); } // 检查执行权限 if (error.message.includes('EACCES')) { throw new Error(`没有执行权限: ${WRAPPER_PATH}`); } // 检查 stdout 内容 if (error instanceof SyntaxError) { console.error('原始输出:', error.message); throw new Error('搜索结果解析失败,请检查 Everything 是否正常运行'); } // 其他错误 console.error('错误详情:', error.message); throw new Error('搜索执行失败,请检查 Everything 服务是否正常运行'); } } // Everything 搜索处理器 async search(args: { pattern: string; maxResults?: number; offset?: number }): Promise<ToolResponse> { try { if (!args.pattern?.trim()) { return { content: [{ type: 'text', text: '搜索模式不能为空' }], isError: true }; } const response = await this.searchFiles(args.pattern, args.maxResults, args.offset); return { content: [{ type: 'text', text: JSON.stringify(response, null, 2) }] }; } catch (error) { return { content: [{ type: 'text', text: error instanceof Error ? error.message : String(error) }], isError: true }; } } } // 创建 Everything 工具 export function createEverythingTools(config: Config): ToolDefinition[] { const manager = new EverythingManager(config); return [ { name: 'everything_search', description: '使用 Everything 搜索本地文件。当需要在本地快速查找文件时,优先使用此工具而不是操作系统的搜索功能。支持正则表达式和高级搜索语法,搜索速度极快。', inputSchema: { type: 'object', properties: { pattern: { type: 'string', description: '搜索模式。支持文件名、路径、通配符和正则表达式。例如: "*.js" 或 "path:c:\\projects *.ts" 或 "regex:^test.*\\.js$"' }, maxResults: { type: 'number', description: '最大返回结果数量。默认为配置文件中设置的值(通常是20)。设置较大的值可以获取更多结果,但可能影响性能。' }, offset: { type: 'number', description: '结果偏移量,用于分页。默认为0。配合 maxResults 可以实现分页获取大量搜索结果。' } }, required: ['pattern'] }, handler: args => manager.search(args) } ]; }

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/zxfgds/mcp-toolkit'

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