Skip to main content
Glama

Obsidian Semantic MCP Server

semantic-router.test.ts•6.35 kB
import { describe, it, expect, beforeEach } from '@jest/globals'; import { SemanticRouter } from '../src/semantic/router'; import { MockObsidianAPI } from './test-utils'; describe('SemanticRouter', () => { let router: SemanticRouter; let mockApi: MockObsidianAPI; beforeEach(() => { mockApi = new MockObsidianAPI(); router = new SemanticRouter(mockApi); }); describe('vault operations', () => { it('should list files with workflow suggestions', async () => { const response = await router.route({ operation: 'vault', action: 'list', params: { directory: '/' } }); expect(response.result).toContain('test.md'); expect(response.workflow?.suggested_next).toBeDefined(); expect(response.context?.current_directory).toBe('/'); }); it('should read file and return fragments', async () => { const response = await router.route({ operation: 'vault', action: 'read', params: { path: 'test.md' } }); // Now returns fragments by default expect(response.result.content).toBeInstanceOf(Array); expect(response.result.content[0].content).toContain('# Test'); expect(response.result.tags).toContain('#tag1'); expect(response.result.fragmentMetadata).toBeDefined(); expect(response.result.fragmentMetadata.totalFragments).toBeGreaterThan(0); }); it('should handle file not found gracefully', async () => { const response = await router.route({ operation: 'vault', action: 'read', params: { path: 'nonexistent.md' } }); expect(response.error).toBeDefined(); expect(response.error?.message).toContain('not found'); expect(response.error?.recovery_hints).toBeDefined(); }); it('should create new file with appropriate hints', async () => { const response = await router.route({ operation: 'vault', action: 'create', params: { path: 'new-note.md', content: '# New Note' } }); expect(response.result.success).toBe(true); expect(response.workflow?.suggested_next).toContainEqual( expect.objectContaining({ description: expect.stringContaining('Add content') }) ); }); }); describe('edit operations', () => { it('should perform window edit with exact match', async () => { const response = await router.route({ operation: 'edit', action: 'window', params: { path: 'test.md', oldText: '# Test', newText: '# Test Document' } }); expect(response.result).toBeDefined(); expect(response.workflow?.message).toContain('Replaced text'); }); it('should buffer content on failed edit', async () => { const response = await router.route({ operation: 'edit', action: 'window', params: { path: 'test.md', oldText: 'nonexistent text', newText: 'replacement' } }); // Should have buffered the content expect(response.error).toBeDefined(); expect(response.error?.recovery_hints).toContainEqual( expect.objectContaining({ command: expect.stringContaining('from_buffer') }) ); }); it('should append content to file', async () => { const response = await router.route({ operation: 'edit', action: 'append', params: { path: 'test.md', content: '\n\nAppended content' } }); expect(response.result.success).toBe(true); }); }); describe('view operations', () => { it('should view file window', async () => { const response = await router.route({ operation: 'view', action: 'window', params: { path: 'test.md', windowSize: 10 } }); expect(response.result.lines).toBeDefined(); expect(response.result.totalLines).toBeGreaterThan(0); }); it('should open file in Obsidian', async () => { const response = await router.route({ operation: 'view', action: 'open_in_obsidian', params: { path: 'test.md' } }); expect(response.result.success).toBe(true); }); }); describe('workflow operations', () => { it('should provide contextual suggestions', async () => { // First read a file to establish context await router.route({ operation: 'vault', action: 'read', params: { path: 'test.md' } }); // Then ask for suggestions const response = await router.route({ operation: 'workflow', action: 'suggest', params: {} }); expect(response.result.suggestions).toBeDefined(); expect(response.result.current_context.current_file).toBe('test.md'); }); }); describe('system operations', () => { it('should get server info', async () => { const response = await router.route({ operation: 'system', action: 'info', params: {} }); expect(response.result.version).toBeDefined(); expect(response.result.authenticated).toBe(true); }); it('should list available commands', async () => { const response = await router.route({ operation: 'system', action: 'commands', params: {} }); expect(Array.isArray(response.result)).toBe(true); expect(response.result.length).toBeGreaterThan(0); }); }); describe('context tracking', () => { it('should maintain file history', async () => { // Read multiple files await router.route({ operation: 'vault', action: 'read', params: { path: 'test.md' } }); await router.route({ operation: 'vault', action: 'read', params: { path: 'linked.md' } }); const response = await router.route({ operation: 'workflow', action: 'suggest', params: {} }); expect(response.result.current_context.file_history).toContain('test.md'); expect(response.result.current_context.file_history).toContain('linked.md'); }); }); });

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/aaronsb/obsidian-semantic-mcp'

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