Skip to main content
Glama

COA Goldfish MCP

by anortham
intel-tool.test.tsโ€ข12.3 kB
/** * Tests for Intel Tool - Project Knowledge Management */ import { Storage } from '../core/storage.js'; import { handleIntel, getIntelToolSchema } from '../tools/intel.js'; import fs from 'fs-extra'; import { join } from 'path'; describe('Intel Tool', () => { let storage: Storage; let testWorkspace: string; let tempDir: string; beforeEach(async () => { testWorkspace = 'intel-test-workspace'; tempDir = join(process.cwd(), 'test-storage', `intel-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`); // Create isolated storage for testing storage = new Storage(testWorkspace, tempDir); // Clean up any existing test files await fs.remove(tempDir); await fs.ensureDir(tempDir); }); afterEach(async () => { try { await fs.remove(tempDir); } catch { // Ignore cleanup errors } }); describe('Basic Intel Operations', () => { test('should handle quick capture of intelligence', async () => { const result = await handleIntel(storage, { capture: 'Generic < breaks parser at line 234' }); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('Intelligence captured'); expect(result.content[0].text).toContain('Generic < breaks parser'); }); test('should handle structured insight capture', async () => { const result = await handleIntel(storage, { insight: { what: 'SearchEngine.ParseQuery() is a stub', where: 'search.ts:145', why: 'Implementation was never completed' } }); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('Intelligence captured'); expect(result.content[0].text).toContain('SearchEngine.ParseQuery() is a stub'); }); test('should list intelligence when no arguments provided', async () => { // First add some intelligence await handleIntel(storage, { capture: 'Test discovery' }); // Then list it const result = await handleIntel(storage); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('Current Project Intelligence'); expect(result.content[0].text).toContain('Test discovery'); }); test('should handle empty intelligence list', async () => { const result = await handleIntel(storage); expect(result.content).toBeDefined(); // In test environment, it returns the template instead of empty message const resultText = result.content[0].text; expect(resultText).toMatch(/No project intelligence captured yet|Current Project Intelligence/); }); test('should handle permanent intelligence', async () => { await handleIntel(storage, { capture: 'Never build in release mode', permanent: true }); const result = await handleIntel(storage, { action: 'list' }); expect(result.content[0].text).toContain('Permanent Rules'); expect(result.content[0].text).toContain('Never build in release mode'); }); }); describe('Intelligence Categorization', () => { test('should add to permanent section when permanent flag is true', async () => { await handleIntel(storage, { capture: 'Always use ConfigureAwait(false)', permanent: true }); const intelContent = await storage.readIntelFile(); expect(intelContent).toContain('## Permanent Rules'); expect(intelContent).toContain('Always use ConfigureAwait(false)'); }); test('should add to active section by default', async () => { await handleIntel(storage, { capture: 'Bug in authentication flow' }); const intelContent = await storage.readIntelFile(); expect(intelContent).toContain('## Active Investigations'); expect(intelContent).toContain('Bug in authentication flow'); }); test('should add to specified section', async () => { await handleIntel(storage, { capture: 'Fixed memory leak', section: 'resolved' }); const intelContent = await storage.readIntelFile(); expect(intelContent).toContain('## Resolved (Archive)'); expect(intelContent).toContain('Fixed memory leak'); }); }); describe('Markdown Template and Formatting', () => { test('should create initial template when no file exists', async () => { await handleIntel(storage, { capture: 'First discovery' }); const intelContent = await storage.readIntelFile(); expect(intelContent).toContain('# Project Intelligence'); expect(intelContent).toContain('## Permanent Rules'); expect(intelContent).toContain('## Active Investigations'); expect(intelContent).toContain('## Resolved (Archive)'); expect(intelContent).toContain('First discovery'); }); test('should preserve existing content when adding new entries', async () => { // Add first entry await handleIntel(storage, { capture: 'First discovery' }); // Add second entry await handleIntel(storage, { capture: 'Second discovery' }); const intelContent = await storage.readIntelFile(); expect(intelContent).toContain('First discovery'); expect(intelContent).toContain('Second discovery'); }); test('should format structured insights properly', async () => { await handleIntel(storage, { insight: { what: 'Parser fails on special characters', where: 'parser.ts:234', why: 'Missing escape handling' } }); const intelContent = await storage.readIntelFile(); expect(intelContent).toContain('Parser fails on special characters'); expect(intelContent).toContain('(parser.ts:234)'); expect(intelContent).toContain('Missing escape handling'); }); }); describe('Error Handling', () => { test('should handle missing capture and insight parameters', async () => { const result = await handleIntel(storage, { action: 'capture' }); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('Either capture or insight parameter is required'); }); test('should handle invalid actions gracefully', async () => { const result = await handleIntel(storage, { action: 'invalid' as any }); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('Unknown intel action: invalid'); }); test('should handle storage errors gracefully', async () => { // Create a storage instance with invalid path to simulate errors const invalidStorage = new Storage(testWorkspace, '/invalid/nonexistent/path/that/cannot/be/created'); const result = await handleIntel(invalidStorage, { capture: 'Test discovery' }); expect(result.content).toBeDefined(); // The operation might succeed if the path can be created, or fail gracefully const resultText = result.content[0].text; expect(resultText).toMatch(/Failed to handle intel|Intelligence captured/); }); }); describe('Management Actions', () => { test('should provide clean action information', async () => { const result = await handleIntel(storage, { action: 'clean' }); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('To clean intel, edit INTEL.md manually'); }); test('should provide archive action information', async () => { const result = await handleIntel(storage, { action: 'archive' }); expect(result.content).toBeDefined(); expect(result.content[0].text).toContain('Archive functionality coming soon'); }); }); describe('Tool Schema', () => { test('should provide proper tool schema', () => { const schema = getIntelToolSchema(); expect(schema.name).toBe('intel'); expect(schema.description).toContain('PROACTIVELY capture critical project discoveries'); expect(schema.description).toContain('Find a bug\'s root cause'); expect(schema.description).toContain('Quick capture: intel("your discovery here")'); expect(schema.inputSchema.properties).toHaveProperty('capture'); expect(schema.inputSchema.properties).toHaveProperty('insight'); expect(schema.inputSchema.properties).toHaveProperty('action'); expect(schema.inputSchema.properties).toHaveProperty('permanent'); }); test('should include proactive usage examples in description', () => { const schema = getIntelToolSchema(); expect(schema.description).toContain('< symbol breaks parser'); expect(schema.description).toContain('UserService.auth() is just a stub'); expect(schema.description).toContain('Never build in release mode'); expect(schema.description).toContain('prevents repeated investigations'); }); }); describe('Integration with Storage', () => { test('should use correct workspace directory', async () => { await handleIntel(storage, { capture: 'Test workspace discovery' }); const workspaceDir = join(tempDir, testWorkspace); const intelPath = join(workspaceDir, 'INTEL.md'); expect(await fs.pathExists(intelPath)).toBe(true); const content = await fs.readFile(intelPath, 'utf-8'); expect(content).toContain('Test workspace discovery'); }); test('should handle multiple intelligence entries correctly', async () => { const entries = [ 'First discovery about authentication', 'Second discovery about database connections', 'Third discovery about error handling' ]; for (const entry of entries) { await handleIntel(storage, { capture: entry }); } const result = await handleIntel(storage, { action: 'list' }); for (const entry of entries) { expect(result.content[0].text).toContain(entry); } }); }); describe('Content Organization', () => { test('should maintain section order in template', async () => { await handleIntel(storage, { capture: 'Test discovery' }); const intelContent = await storage.readIntelFile(); const lines = intelContent.split('\n'); const permanentIndex = lines.findIndex(line => line.includes('## Permanent Rules')); const activeIndex = lines.findIndex(line => line.includes('## Active Investigations')); const resolvedIndex = lines.findIndex(line => line.includes('## Resolved (Archive)')); expect(permanentIndex).toBeGreaterThan(-1); expect(activeIndex).toBeGreaterThan(permanentIndex); expect(resolvedIndex).toBeGreaterThan(activeIndex); }); test('should insert entries in correct sections', async () => { // Add to different sections await handleIntel(storage, { capture: 'Permanent rule', permanent: true }); await handleIntel(storage, { capture: 'Active investigation' }); await handleIntel(storage, { capture: 'Resolved issue', section: 'resolved' }); const intelContent = await storage.readIntelFile(); const lines = intelContent.split('\n'); // Find section boundaries const permanentStart = lines.findIndex(line => line.includes('## Permanent Rules')); const activeStart = lines.findIndex(line => line.includes('## Active Investigations')); const resolvedStart = lines.findIndex(line => line.includes('## Resolved (Archive)')); // Check entries are in correct sections const permanentRuleIndex = lines.findIndex(line => line.includes('Permanent rule')); const activeInvestigationIndex = lines.findIndex(line => line.includes('Active investigation')); const resolvedIssueIndex = lines.findIndex(line => line.includes('Resolved issue')); expect(permanentRuleIndex).toBeGreaterThan(permanentStart); expect(permanentRuleIndex).toBeLessThan(activeStart); expect(activeInvestigationIndex).toBeGreaterThan(activeStart); expect(activeInvestigationIndex).toBeLessThan(resolvedStart); expect(resolvedIssueIndex).toBeGreaterThan(resolvedStart); }); }); });

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/anortham/coa-goldfish-mcp'

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