Skip to main content
Glama

NervusDB MCP Server

Official
by nervusdb
queryService.spec.ts6.36 kB
import { describe, expect, it, vi } from 'vitest'; import { QueryService } from '../../../src/domain/query/queryService.js'; import type { IndexMetadata } from '../../../src/domain/types/indexMetadata.js'; const createMetadata = (): IndexMetadata => ({ schemaVersion: 1, state: 'complete', projectPath: '/repo', projectHash: 'hash', indexedAt: new Date().toISOString(), fileCount: 10, fingerprint: { value: 'abc123', commit: 'abc123', branch: 'main', dirty: false, }, versions: {}, output: { dbFile: '/repo/.synapsedb/hash/graph.synapsedb', }, }); describe('QueryService', () => { it('normalises facts when querying callers', async () => { const metadata = createMetadata(); const validate = vi.fn().mockResolvedValue(metadata); const all = vi.fn().mockResolvedValue([ { subject: 'function:caller', predicate: 'CALLS', object: 'function:target', objectProperties: { occurrences: 2 }, }, ]); const find = vi.fn().mockReturnValue({ all }); const close = vi.fn().mockResolvedValue(undefined); const openDatabase = vi.fn().mockResolvedValue({ find, close, }); const service = new QueryService({ fingerprint: { validate }, openDatabase }); const result = await service.findCallers('/repo', 'target'); expect(validate).toHaveBeenCalledWith('/repo'); expect(openDatabase).toHaveBeenCalledWith('/repo/.synapsedb/hash/graph.synapsedb', { enableLock: false, registerReader: false, experimental: { cypher: true }, }); expect(find).toHaveBeenCalledWith({ predicate: 'CALLS', object: 'function:target' }); expect(result).toEqual([ { subject: 'function:caller', predicate: 'CALLS', object: 'function:target', properties: { occurrences: 2 }, }, ]); expect(close).toHaveBeenCalled(); }); it('respects query limit when listing facts', async () => { const metadata = createMetadata(); const validate = vi.fn().mockResolvedValue(metadata); const facts = Array.from({ length: 5 }, (_, index) => ({ subject: `file:${index}`, predicate: 'CONTAINS', object: `function:f${index}`, })); const all = vi.fn().mockResolvedValue(facts); const find = vi.fn().mockReturnValue({ all }); const close = vi.fn().mockResolvedValue(undefined); const openDatabase = vi.fn().mockResolvedValue({ find, close }); const service = new QueryService({ fingerprint: { validate }, openDatabase }); const result = await service.findFacts('/repo', { predicate: 'CONTAINS' }, { limit: 2 }); expect(result).toHaveLength(2); expect(result[0].subject).toBe('file:0'); expect(close).toHaveBeenCalled(); }); it('does not duplicate prefixes for file and function helpers', async () => { const metadata = createMetadata(); const validate = vi.fn().mockResolvedValue(metadata); const all = vi.fn().mockResolvedValue([]); const find = vi.fn().mockReturnValue({ all }); const close = vi.fn().mockResolvedValue(undefined); const openDatabase = vi.fn().mockResolvedValue({ find, close }); const service = new QueryService({ fingerprint: { validate }, openDatabase }); await service.findCallers('/repo', 'function:target'); await service.findFileMembership('/repo', 'file:src/index.ts'); expect(find).toHaveBeenNthCalledWith(1, { predicate: 'CALLS', object: 'function:target' }); expect(find).toHaveBeenNthCalledWith(2, { predicate: 'CONTAINS', object: 'file:src/index.ts', }); }); it('findDefinitions with empty string should query all definitions without subject filter', async () => { const metadata = createMetadata(); const validate = vi.fn().mockResolvedValue(metadata); const all = vi.fn().mockResolvedValue([ { subject: 'file:src/tools/index.ts', predicate: 'DEFINES', object: 'function:src/tools/index.ts#registerTools', objectProperties: { name: 'registerTools', type: 'function', signature: 'export function registerTools(server: McpServer, options: RegisterToolsOptions): void', }, }, { subject: 'file:src/services/projectService.ts', predicate: 'DEFINES', object: 'class:src/services/projectService.ts#ProjectService', objectProperties: { name: 'ProjectService', type: 'class', }, }, ]); const find = vi.fn().mockReturnValue({ all }); const close = vi.fn().mockResolvedValue(undefined); const openDatabase = vi.fn().mockResolvedValue({ find, close }); const service = new QueryService({ fingerprint: { validate }, openDatabase }); const result = await service.findDefinitions('/repo', ''); // Should query with only predicate, no subject filter expect(find).toHaveBeenCalledWith({ predicate: 'DEFINES' }); expect(result).toHaveLength(2); expect(result[0].name).toBe('registerTools'); expect(result[0].type).toBe('function'); expect(result[1].name).toBe('ProjectService'); expect(result[1].type).toBe('class'); expect(close).toHaveBeenCalled(); }); it('findDefinitions with filePath should filter by file subject', async () => { const metadata = createMetadata(); const validate = vi.fn().mockResolvedValue(metadata); const all = vi.fn().mockResolvedValue([ { subject: 'file:src/tools/index.ts', predicate: 'DEFINES', object: 'function:src/tools/index.ts#registerTools', objectProperties: { name: 'registerTools', type: 'function', }, }, ]); const find = vi.fn().mockReturnValue({ all }); const close = vi.fn().mockResolvedValue(undefined); const openDatabase = vi.fn().mockResolvedValue({ find, close }); const service = new QueryService({ fingerprint: { validate }, openDatabase }); const result = await service.findDefinitions('/repo', 'src/tools/index.ts'); // Should query with both predicate and subject expect(find).toHaveBeenCalledWith({ predicate: 'DEFINES', subject: 'file:src/tools/index.ts', }); expect(result).toHaveLength(1); expect(result[0].name).toBe('registerTools'); expect(close).toHaveBeenCalled(); }); });

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/nervusdb/nervusdb-mcp'

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