Skip to main content
Glama

Context Optimizer MCP Server

askAboutFile.test.ts6.44 kB
/** * Tests for askAboutFile tool */ import { AskAboutFileTool } from '../src/tools/askAboutFile'; import { ConfigurationManager } from '../src/config/manager'; import { PathValidator } from '../src/security/pathValidator'; import { LLMProviderFactory } from '../src/providers/factory'; import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; // Mock dependencies jest.mock('../src/config/manager'); jest.mock('../src/security/pathValidator'); jest.mock('../src/providers/factory'); jest.mock('fs/promises'); const mockConfigManager = ConfigurationManager as jest.Mocked<typeof ConfigurationManager>; const mockPathValidator = PathValidator as jest.Mocked<typeof PathValidator>; const mockLLMProviderFactory = LLMProviderFactory as jest.Mocked<typeof LLMProviderFactory>; const mockFs = fs as jest.Mocked<typeof fs>; describe('AskAboutFileTool', () => { let tool: AskAboutFileTool; beforeEach(() => { tool = new AskAboutFileTool(); jest.clearAllMocks(); // Default configuration mock mockConfigManager.getConfig.mockReturnValue({ security: { allowedBasePaths: ['/test/path'], maxFileSize: 1024 * 1024, commandTimeout: 30000, sessionTimeout: 1800000 }, llm: { provider: 'gemini', geminiKey: 'test-api-key' }, research: { exaKey: 'test-exa-key' }, server: { logLevel: 'info' } }); }); describe('execute', () => { it('should successfully analyze a file and return LLM response', async () => { const testFilePath = '/test/path/file.ts'; const testFileContent = 'export function hello() { return "world"; }'; const testQuestion = 'What function is exported?'; // Mock path validation mockPathValidator.validateFilePath.mockResolvedValue({ valid: true, resolvedPath: testFilePath }); // Mock file reading mockFs.readFile.mockResolvedValue(testFileContent); // Mock LLM provider const mockProvider = { processRequest: jest.fn().mockResolvedValue({ success: true, content: 'The exported function is `hello()`' }) }; mockLLMProviderFactory.createProvider.mockReturnValue(mockProvider); const result = await tool.execute({ filePath: 'file.ts', question: testQuestion }); expect(result.isError).toBeFalsy(); expect(result.content).toHaveLength(1); expect(result.content[0]?.text).toBe('The exported function is `hello()`'); expect(mockPathValidator.validateFilePath).toHaveBeenCalledWith('file.ts'); expect(mockFs.readFile).toHaveBeenCalledWith(testFilePath, 'utf8'); expect(mockProvider.processRequest).toHaveBeenCalledWith( expect.stringContaining(testQuestion), undefined, 'test-api-key' ); }); it('should return error for missing required fields', async () => { const result = await tool.execute({ filePath: 'test.ts' // Missing question }); expect(result.isError).toBe(true); expect(result.content).toHaveLength(1); expect(result.content[0]?.text).toContain('Missing required field: question'); }); it('should return error for invalid file path', async () => { mockPathValidator.validateFilePath.mockResolvedValue({ valid: false, error: 'Path outside allowed directories' }); const result = await tool.execute({ filePath: '/unauthorized/path/file.ts', question: 'What is this?' }); expect(result.isError).toBe(true); expect(result.content).toHaveLength(1); expect(result.content[0]?.text).toContain('Path outside allowed directories'); }); it('should return error when LLM processing fails', async () => { const testFilePath = '/test/path/file.ts'; mockPathValidator.validateFilePath.mockResolvedValue({ valid: true, resolvedPath: testFilePath }); mockFs.readFile.mockResolvedValue('test content'); const mockProvider = { processRequest: jest.fn().mockResolvedValue({ success: false, error: 'API quota exceeded' }) }; mockLLMProviderFactory.createProvider.mockReturnValue(mockProvider); const result = await tool.execute({ filePath: 'file.ts', question: 'What is this?' }); expect(result.isError).toBe(true); expect(result.content).toHaveLength(1); expect(result.content[0]?.text).toContain('LLM processing failed: API quota exceeded'); }); it('should handle file reading errors', async () => { const testFilePath = '/test/path/file.ts'; mockPathValidator.validateFilePath.mockResolvedValue({ valid: true, resolvedPath: testFilePath }); mockFs.readFile.mockRejectedValue(new Error('File not found')); const result = await tool.execute({ filePath: 'file.ts', question: 'What is this?' }); expect(result.isError).toBe(true); expect(result.content).toHaveLength(1); expect(result.content[0]?.text).toContain('File analysis failed: File not found'); }); }); describe('toMCPTool', () => { it('should return correct MCP tool definition', () => { const mcpTool = tool.toMCPTool(); expect(mcpTool.name).toBe('askAboutFile'); expect(mcpTool.description).toBe('Extract specific information from files without reading their entire contents into chat context. Works with text files, code files, images, PDFs, and more.'); expect(mcpTool.inputSchema).toEqual({ type: 'object', properties: { filePath: { type: 'string', description: 'Full absolute path to the file to analyze (e.g., "C:\\Users\\username\\project\\src\\file.ts", "/home/user/project/docs/README.md")' }, question: { type: 'string', description: 'Specific question about the file content (e.g., "Does this file export a validateEmail function?", "What is the main purpose described in this spec?", "Extract all import statements")' } }, required: ['filePath', 'question'] }); }); }); });

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/malaksedarous/context-optimizer-mcp-server'

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