Skip to main content
Glama

Memory Bank MCP Server

by t3ta
json-document.test.ts17.2 kB
/** * Tests for v2 JSON document schemas */ import { DocumentMetadataV2Schema, BaseJsonDocumentV2Schema, SCHEMA_VERSION } from '../../../src/v2/json-document.js'; // 相対パスに変更 import { BranchContextJsonV2Schema, ActiveContextJsonV2Schema, ProgressJsonV2Schema, SystemPatternsJsonV2Schema, GenericDocumentJsonV2Schema, } from '../../../src/document-types/index.js'; // 相対パスに変更 describe('DocumentMetadataV2Schema', () => { it('should validate correct metadata', () => { const validMetadata = { title: 'Test Document', documentType: 'test', id: '123e4567-e89b-12d3-a456-426614174000', path: 'test/document.json', tags: ['test', 'example'], lastModified: '2023-10-27T10:00:00.000Z', // Use ISO string createdAt: '2023-10-26T10:00:00.000Z', // Use ISO string version: 1 }; const result = DocumentMetadataV2Schema.safeParse(validMetadata); expect(result.success).toBe(true); }); it('should accept ISO date strings for dates', () => { const validMetadata = { title: 'Test Document', documentType: 'test', id: '123e4567-e89b-12d3-a456-426614174000', path: 'test/document.json', tags: ['test', 'example'], lastModified: '2025-03-27T12:00:00Z', createdAt: '2025-03-26T10:00:00Z', version: 1 }; const result = DocumentMetadataV2Schema.safeParse(validMetadata); expect(result.success).toBe(true); }); it('should reject metadata with missing required fields', () => { const invalidMetadata = { title: 'Test Document', // missing documentType, id, path, etc. }; const result = DocumentMetadataV2Schema.safeParse(invalidMetadata); expect(result.success).toBe(false); if (!result.success) { expect(result.error.issues.length).toBeGreaterThan(0); } }); it('should reject metadata with invalid UUID', () => { const invalidMetadata = { title: 'Test Document', documentType: 'test', id: 'not-a-uuid', // Invalid UUID path: 'test/document.json', tags: ['test'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }; const result = DocumentMetadataV2Schema.safeParse(invalidMetadata); expect(result.success).toBe(false); }); it('should reject metadata with invalid tags', () => { const invalidMetadata = { title: 'Test Document', documentType: 'test', id: '123e4567-e89b-12d3-a456-426614174000', path: 'test/document.json', tags: ['Invalid Tag', 'test'], // Invalid tag with uppercase and space lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }; const result = DocumentMetadataV2Schema.safeParse(invalidMetadata); expect(result.success).toBe(false); }); }); describe('BaseJsonDocumentV2Schema', () => { it('should validate a correct base document structure (schema and documentType)', () => { // Base schema now only defines schema and documentType at the top level const validBaseStructure = { schema: SCHEMA_VERSION, documentType: 'any_valid_type_string', // Needs a non-empty string // metadata and content are not part of the base schema itself anymore }; const result = BaseJsonDocumentV2Schema.safeParse(validBaseStructure); // If this fails, log the Zod error details if (!result.success) { console.error("BaseJsonDocumentV2Schema validation failed:", JSON.stringify(result.error.format(), null, 2)); } expect(result.success).toBe(true); }); it('should reject document with wrong schema version', () => { const invalidDocument = { schema: 'wrong_version', metadata: { title: 'Test Document', documentType: 'test', id: '123e4567-e89b-12d3-a456-426614174000', path: 'test/document.json', tags: ['test'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }, content: { key: 'value' } }; const result = BaseJsonDocumentV2Schema.safeParse(invalidDocument); expect(result.success).toBe(false); }); it('should reject document with empty content', () => { const invalidDocument = { schema: SCHEMA_VERSION, metadata: { title: 'Test Document', documentType: 'test', id: '123e4567-e89b-12d3-a456-426614174000', path: 'test/document.json', tags: ['test'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }, content: {} // Empty content }; const result = BaseJsonDocumentV2Schema.safeParse(invalidDocument); // Base schema requires content not to be empty expect(result.success).toBe(false); }); }); describe('BranchContextJsonV2Schema', () => { it('should validate a correct branch context document', () => { const validDocument = { schema: SCHEMA_VERSION, documentType: 'branch_context' as const, // Move documentType to top level metadata: { title: 'Branch Context', // documentType: 'branch_context', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'branchContext.json', tags: ['branch-context'], lastModified: '2023-10-27T12:00:00.000Z', createdAt: '2023-10-26T12:00:00.000Z', version: 1 }, content: { purpose: 'Feature implementation', background: 'Some background info', // Optional field userStories: [ { description: 'User can do something', completed: false // Default is false, explicitly setting is fine } ] // additionalNotes is missing, but it's optional in the schema } }; const result = BranchContextJsonV2Schema.safeParse(validDocument); expect(result.success).toBe(true); }); it('should reject branch context with wrong document type', () => { const invalidDocument = { schema: SCHEMA_VERSION, documentType: 'wrong_type' as any, // Invalid literal at top level metadata: { title: 'Branch Context', // documentType: 'wrong_type', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'branchContext.json', tags: ['branch-context'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }, content: { purpose: 'Feature implementation', userStories: [] } }; const result = BranchContextJsonV2Schema.safeParse(invalidDocument); expect(result.success).toBe(false); }); it('should reject branch context without required purpose', () => { const invalidDocument = { schema: SCHEMA_VERSION, documentType: 'branch_context' as const, // Correct type at top level metadata: { title: 'Branch Context', // documentType: 'branch_context', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'branchContext.json', tags: ['branch-context'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }, content: { // Missing required field 'purpose' userStories: [] } }; const result = BranchContextJsonV2Schema.safeParse(invalidDocument); expect(result.success).toBe(false); }); }); describe('ActiveContextJsonV2Schema', () => { it('should validate a correct active context document', () => { const validDocument = { schema: SCHEMA_VERSION, documentType: 'active_context' as const, // Move documentType to top level metadata: { title: 'Active Context', // documentType: 'active_context', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'activeContext.json', tags: ['active-context'], lastModified: '2023-10-27T13:00:00.000Z', createdAt: '2023-10-26T13:00:00.000Z', version: 1 }, content: { currentWork: 'Working on feature X', // Optional recentChanges: [], // Optional, default [] activeDecisions: [], // Optional, default [] considerations: [], // Optional, default [] nextSteps: [] // Optional, default [] } }; const result = ActiveContextJsonV2Schema.safeParse(validDocument); expect(result.success).toBe(true); }); it('should accept active context with only optional fields', () => { const validDocument = { schema: SCHEMA_VERSION, documentType: 'active_context' as const, // Move documentType to top level metadata: { title: 'Active Context', // documentType: 'active_context', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'activeContext.json', tags: ['active-context'], lastModified: '2023-10-27T14:00:00.000Z', createdAt: '2023-10-26T14:00:00.000Z', version: 1 }, content: { // All content fields are optional or have defaults in ActiveContext schema } }; const result = ActiveContextJsonV2Schema.safeParse(validDocument); expect(result.success).toBe(true); }); }); describe('ProgressJsonV2Schema', () => { it('should validate a correct progress document', () => { const validDocument = { schema: SCHEMA_VERSION, documentType: 'progress' as const, // Move documentType to top level metadata: { title: 'Progress', // documentType: 'progress', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'progress.json', tags: ['progress'], lastModified: '2023-10-27T15:00:00.000Z', createdAt: '2023-10-26T15:00:00.000Z', version: 1 }, content: { workingFeatures: [], // Optional, default [] pendingImplementation: [], // Optional, default [] status: 'In progress', // Optional // currentState: 'Phase 2', // This field is not in the Progress schema completionPercentage: 50, // Optional knownIssues: [] // Optional, default [] } }; const result = ProgressJsonV2Schema.safeParse(validDocument); expect(result.success).toBe(true); }); it('should accept progress document with minimum required fields', () => { // status and completionPercentage are required according to the schema const validDocument = { schema: SCHEMA_VERSION, documentType: 'progress' as const, metadata: { title: 'Progress', id: '123e4567-e89b-12d3-a456-426614174000', path: 'progress.json', tags: ['progress'], lastModified: '2023-10-27T16:00:00.000Z', createdAt: '2023-10-26T16:00:00.000Z', version: 1 }, content: { status: 'Initial', // Add required status completionPercentage: 0, // Add required completionPercentage // Optional fields with defaults can be omitted or explicitly set workingFeatures: [], pendingImplementation: [], knownIssues: [], // currentState is optional } }; const result = ProgressJsonV2Schema.safeParse(validDocument); if (!result.success) { console.error("ProgressJsonV2Schema (minimum) validation failed:", JSON.stringify(result.error.format(), null, 2)); } expect(result.success).toBe(true); }); }); describe('SystemPatternsJsonV2Schema', () => { it('should validate a correct system patterns document', () => { const validDocument = { schema: SCHEMA_VERSION, documentType: 'system_patterns' as const, // Move documentType to top level metadata: { title: 'System Patterns', // documentType: 'system_patterns', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'systemPatterns.json', tags: ['system-patterns'], lastModified: '2023-10-27T17:00:00.000Z', createdAt: '2023-10-26T17:00:00.000Z', version: 1 }, content: { technicalDecisions: [ // Optional, default [] { title: 'Use TypeScript', // Required context: 'Need type safety', // Required decision: 'We will use TypeScript', // Required consequences: ['Better code quality', 'Requires compilation'] // Must be string[] with min 1 element // status, date, alternatives are not in the schema definition } ], implementationPatterns: [] // Optional, default [] } }; const result = SystemPatternsJsonV2Schema.safeParse(validDocument); if (!result.success) { console.error("SystemPatternsJsonV2Schema validation failed:", JSON.stringify(result.error.format(), null, 2)); } expect(result.success).toBe(true); }); it('should accept system patterns with minimum fields', () => { const validDocument = { schema: SCHEMA_VERSION, documentType: 'system_patterns' as const, // Move documentType to top level metadata: { title: 'System Patterns', // documentType: 'system_patterns', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'systemPatterns.json', tags: ['system-patterns'], lastModified: '2023-10-27T18:00:00.000Z', createdAt: '2023-10-26T18:00:00.000Z', version: 1 }, content: { // technicalDecisions and implementationPatterns have defaults } }; const result = SystemPatternsJsonV2Schema.safeParse(validDocument); expect(result.success).toBe(true); }); it('should reject technical decision with missing required fields (e.g., title)', () => { // テストケース名を修正 const invalidDocument = { schema: SCHEMA_VERSION, documentType: 'system_patterns' as const, // Move documentType to top level metadata: { title: 'System Patterns', // documentType: 'system_patterns', // Removed from metadata id: '123e4567-e89b-12d3-a456-426614174000', path: 'systemPatterns.json', tags: ['system-patterns'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }, content: { technicalDecisions: [ { // title: 'Use TypeScript', // title を削除して必須フィールド欠落をテスト context: 'Need type safety', decision: 'We will use TypeScript', // consequences は TechnicalDecisionContentV2Schema では string[] なので修正 consequences: ['Consequence 1'], // date は TechnicalDecisionContentV2Schema にないので削除 // date: new Date().toISOString(), } ] } }; const result = SystemPatternsJsonV2Schema.safeParse(invalidDocument); expect(result.success).toBe(false); // title が欠落しているエラーを確認 (パスは content.technicalDecisions[0].title になるはず) expect(result.error?.errors.some((e: any) => e.path.includes('title'))).toBe(true); }); }); describe('GenericDocumentJsonV2Schema', () => { it('should validate a generic document', () => { // Generic schema expects documentType inside metadata const validDocument = { schema: SCHEMA_VERSION, documentType: 'custom_type', // トップレベルに移動 metadata: { title: 'Custom Document', // documentType: 'custom_type', // metadata から削除 id: '123e4567-e89b-12d3-a456-426614174000', path: 'custom.json', tags: ['custom'], lastModified: '2023-10-27T19:00:00.000Z', createdAt: '2023-10-26T19:00:00.000Z', version: 1 }, content: { // Content must not be empty customField: 'value', anotherField: 123 } }; const result = GenericDocumentJsonV2Schema.safeParse(validDocument); expect(result.success).toBe(true); }); it('should reject generic document with empty content', () => { const invalidDocument = { schema: SCHEMA_VERSION, metadata: { title: 'Custom Document', documentType: 'custom_type', id: '123e4567-e89b-12d3-a456-426614174000', path: 'custom.json', tags: ['custom'], lastModified: new Date().toISOString(), // Use ISO string createdAt: new Date().toISOString(), // Use ISO string version: 1 }, content: {} // Empty content }; const result = GenericDocumentJsonV2Schema.safeParse(invalidDocument); // Generic schema requires content not to be empty expect(result.success).toBe(false); }); });

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/t3ta/memory-bank-mcp-server'

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