Skip to main content
Glama

Chat Context MCP

by aolshaun
metadata-db.test.tsβ€’12.4 kB
/** * Tests for metadata database */ import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import { MetadataDB } from '../../src/core/metadata-db.js'; import fs from 'fs'; import path from 'path'; import os from 'os'; describe('MetadataDB', () => { let db: MetadataDB; let dbPath: string; beforeEach(() => { // Create temp database for each test const tmpDir = os.tmpdir(); dbPath = path.join(tmpDir, `.test-metadata-${Date.now()}.db`); db = new MetadataDB(dbPath); }); afterEach(() => { // Clean up db.close(); if (fs.existsSync(dbPath)) { fs.unlinkSync(dbPath); } }); describe('Initialization', () => { it('should create database file on first use', () => { // Database is created lazily on first operation db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); expect(fs.existsSync(dbPath)).toBe(true); }); it('should create schema on first use', () => { db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); const stats = db.getStats(); expect(stats.total_sessions).toBe(1); }); it('should report connection status', () => { expect(db.isConnected()).toBe(false); db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); expect(db.isConnected()).toBe(true); }); }); describe('CRUD Operations', () => { it('should upsert session metadata', () => { db.upsertSessionMetadata({ session_id: 'test-session', project_path: '/path/to/project', project_name: 'test-project', has_project: true, message_count: 10 }); const metadata = db.getSessionMetadata('test-session'); expect(metadata).not.toBeNull(); expect(metadata?.session_id).toBe('test-session'); expect(metadata?.project_path).toBe('/path/to/project'); expect(metadata?.has_project).toBe(true); expect(metadata?.message_count).toBe(10); }); it('should update existing metadata on upsert', () => { db.upsertSessionMetadata({ session_id: 'test-session', message_count: 10, has_project: false }); db.upsertSessionMetadata({ session_id: 'test-session', message_count: 20, has_project: false }); const metadata = db.getSessionMetadata('test-session'); expect(metadata?.message_count).toBe(20); }); it('should return null for non-existent session', () => { const metadata = db.getSessionMetadata('non-existent'); expect(metadata).toBeNull(); }); it('should delete session metadata', () => { db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); expect(db.getSessionMetadata('test-session')).not.toBeNull(); db.deleteSessionMetadata('test-session'); expect(db.getSessionMetadata('test-session')).toBeNull(); }); }); describe('Nickname Operations', () => { it('should set nickname for existing session', () => { db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); db.setNickname('test-session', 'my-nickname'); const metadata = db.getSessionMetadata('test-session'); expect(metadata?.nickname).toBe('my-nickname'); }); it('should create session if setting nickname for new session', () => { db.setNickname('new-session', 'new-nickname'); const metadata = db.getSessionMetadata('new-session'); expect(metadata).not.toBeNull(); expect(metadata?.nickname).toBe('new-nickname'); }); it('should get session by nickname', () => { db.setNickname('test-session', 'my-nickname'); const metadata = db.getSessionByNickname('my-nickname'); expect(metadata?.session_id).toBe('test-session'); }); it('should return null for non-existent nickname', () => { const metadata = db.getSessionByNickname('non-existent'); expect(metadata).toBeNull(); }); it('should enforce unique nicknames', () => { db.setNickname('session-1', 'unique-name'); expect(() => { db.setNickname('session-2', 'unique-name'); }).toThrow(/already in use/); }); it('should allow same nickname for same session', () => { db.setNickname('test-session', 'my-nickname'); // Setting same nickname again should not throw expect(() => { db.setNickname('test-session', 'my-nickname'); }).not.toThrow(); }); it('should list all nicknames', () => { db.setNickname('session-1', 'nickname-1'); db.setNickname('session-2', 'nickname-2'); db.setNickname('session-3', 'nickname-3'); const nicknames = db.listNicknames(); expect(nicknames).toHaveLength(3); expect(nicknames).toContain('nickname-1'); expect(nicknames).toContain('nickname-2'); expect(nicknames).toContain('nickname-3'); }); }); describe('Tag Operations', () => { it('should add tag to existing session', () => { db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); db.addTag('test-session', 'important'); const metadata = db.getSessionMetadata('test-session'); expect(metadata?.tags).toContain('important'); }); it('should create session if adding tag to new session', () => { db.addTag('new-session', 'tag-1'); const metadata = db.getSessionMetadata('new-session'); expect(metadata).not.toBeNull(); expect(metadata?.tags).toContain('tag-1'); }); it('should add multiple tags', () => { db.addTag('test-session', 'tag-1'); db.addTag('test-session', 'tag-2'); db.addTag('test-session', 'tag-3'); const metadata = db.getSessionMetadata('test-session'); expect(metadata?.tags).toHaveLength(3); expect(metadata?.tags).toContain('tag-1'); expect(metadata?.tags).toContain('tag-2'); expect(metadata?.tags).toContain('tag-3'); }); it('should not add duplicate tags', () => { db.addTag('test-session', 'tag-1'); db.addTag('test-session', 'tag-1'); const metadata = db.getSessionMetadata('test-session'); expect(metadata?.tags).toHaveLength(1); }); it('should remove tag from session', () => { db.addTag('test-session', 'tag-1'); db.addTag('test-session', 'tag-2'); db.removeTag('test-session', 'tag-1'); const metadata = db.getSessionMetadata('test-session'); expect(metadata?.tags).not.toContain('tag-1'); expect(metadata?.tags).toContain('tag-2'); }); it('should handle removing tag from session without tags', () => { db.upsertSessionMetadata({ session_id: 'test-session', has_project: false }); // Should not throw expect(() => { db.removeTag('test-session', 'non-existent'); }).not.toThrow(); }); it('should find sessions by tag', () => { db.addTag('session-1', 'important'); db.addTag('session-2', 'important'); db.addTag('session-3', 'other'); const sessions = db.findByTag('important'); expect(sessions).toHaveLength(2); expect(sessions.map(s => s.session_id)).toContain('session-1'); expect(sessions.map(s => s.session_id)).toContain('session-2'); }); it('should list all tags with counts', () => { db.addTag('session-1', 'tag-a'); db.addTag('session-2', 'tag-a'); db.addTag('session-3', 'tag-b'); const tags = db.listAllTags(); expect(tags).toHaveLength(2); const tagA = tags.find(t => t.tag === 'tag-a'); const tagB = tags.find(t => t.tag === 'tag-b'); expect(tagA?.count).toBe(2); expect(tagB?.count).toBe(1); }); }); describe('Project Operations', () => { it('should list sessions by project', () => { db.upsertSessionMetadata({ session_id: 'session-1', project_path: '/path/to/project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-2', project_path: '/path/to/project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-3', project_path: '/path/to/project-b', has_project: true }); const sessions = db.listSessionsByProject('/path/to/project-a'); expect(sessions).toHaveLength(2); expect(sessions.map(s => s.session_id)).toContain('session-1'); expect(sessions.map(s => s.session_id)).toContain('session-2'); }); it('should list all projects', () => { db.upsertSessionMetadata({ session_id: 'session-1', project_path: '/path/to/project-a', project_name: 'project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-2', project_path: '/path/to/project-a', project_name: 'project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-3', project_path: '/path/to/project-b', project_name: 'project-b', has_project: true }); const projects = db.listProjects(); expect(projects).toHaveLength(2); const projectA = projects.find(p => p.name === 'project-a'); const projectB = projects.find(p => p.name === 'project-b'); expect(projectA?.session_count).toBe(2); expect(projectB?.session_count).toBe(1); }); }); describe('List Sessions with Filters', () => { beforeEach(() => { db.upsertSessionMetadata({ session_id: 'session-1', nickname: 'nick-1', project_path: '/project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-2', project_path: '/project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-3', nickname: 'nick-3', project_path: '/project-b', has_project: true }); }); it('should list all sessions', () => { const sessions = db.listSessions(); expect(sessions).toHaveLength(3); }); it('should filter by project', () => { const sessions = db.listSessions({ project: '/project-a' }); expect(sessions).toHaveLength(2); }); it('should filter by tagged_only', () => { const sessions = db.listSessions({ tagged_only: true }); expect(sessions).toHaveLength(2); expect(sessions.every(s => s.nickname)).toBe(true); }); it('should apply limit', () => { const sessions = db.listSessions({ limit: 2 }); expect(sessions).toHaveLength(2); }); it('should combine filters', () => { const sessions = db.listSessions({ project: '/project-a', tagged_only: true, limit: 10 }); expect(sessions).toHaveLength(1); expect(sessions[0]?.session_id).toBe('session-1'); }); }); describe('Statistics', () => { it('should return correct stats', () => { db.upsertSessionMetadata({ session_id: 'session-1', nickname: 'nick-1', project_path: '/project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-2', project_path: '/project-a', has_project: true }); db.upsertSessionMetadata({ session_id: 'session-3', has_project: false }); const stats = db.getStats(); expect(stats.total_sessions).toBe(3); expect(stats.sessions_with_nicknames).toBe(1); expect(stats.sessions_with_projects).toBe(2); expect(stats.total_projects).toBe(1); }); it('should return zero stats for empty database', () => { const stats = db.getStats(); expect(stats.total_sessions).toBe(0); expect(stats.sessions_with_nicknames).toBe(0); expect(stats.sessions_with_projects).toBe(0); expect(stats.total_projects).toBe(0); }); }); });

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/aolshaun/chat-context-mcp'

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