Skip to main content
Glama

Stampchain MCP Server

Official
registry.test.ts10.2 kB
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest'; /** * Tests for ToolRegistry system */ import { ToolRegistry } from '../../tools/registry.js'; import { GetStampTool } from '../../tools/stamps.js'; import { GetCollectionTool } from '../../tools/collections.js'; import { createMockToolContext } from '../utils/test-helpers.js'; describe('ToolRegistry', () => { let registry: ToolRegistry; let mockTool1: GetStampTool; let mockTool2: GetCollectionTool; beforeEach(() => { registry = new ToolRegistry({ validateOnRegister: true, allowDuplicateNames: false, maxTools: 100, }); mockTool1 = new GetStampTool(); mockTool2 = new GetCollectionTool(); }); describe('constructor', () => { it('should create registry with default options', () => { const defaultRegistry = new ToolRegistry(); expect(defaultRegistry).toBeInstanceOf(ToolRegistry); }); it('should create registry with custom options', () => { const customRegistry = new ToolRegistry({ validateOnRegister: false, allowDuplicateNames: true, maxTools: 50, }); expect(customRegistry).toBeInstanceOf(ToolRegistry); }); }); describe('register', () => { it('should register a tool successfully', () => { registry.register(mockTool1, { category: 'stamps', version: '1.0.0', }); expect(registry.has('get_stamp')).toBe(true); expect(registry.get('get_stamp')).toBe(mockTool1); }); it('should register tool with minimal metadata', () => { registry.register(mockTool1); expect(registry.has('get_stamp')).toBe(true); expect(registry.get('get_stamp')).toBe(mockTool1); }); it('should reject duplicate tool names when not allowed', () => { registry.register(mockTool1); expect(() => { registry.register(mockTool1, { category: 'duplicate' }); }).toThrow("Tool with name 'get_stamp' already registered"); }); it('should allow duplicate tool names when configured', () => { const duplicateRegistry = new ToolRegistry({ allowDuplicateNames: true, }); duplicateRegistry.register(mockTool1); expect(() => { duplicateRegistry.register(mockTool1, { category: 'duplicate' }); }).not.toThrow(); }); it('should enforce maximum tool limit', () => { const limitedRegistry = new ToolRegistry({ maxTools: 1, }); limitedRegistry.register(mockTool1); expect(() => { limitedRegistry.register(mockTool2); }).toThrow('Maximum number of tools (1) reached'); }); it('should validate tool when enabled', () => { // Mock a tool with invalid structure const invalidTool = {} as any; expect(() => { registry.register(invalidTool); }).toThrow(); }); it('should skip validation when disabled', () => { const nonValidatingRegistry = new ToolRegistry({ validateOnRegister: false, }); const invalidTool = { name: 'test', description: 'test' } as any; expect(() => { nonValidatingRegistry.register(invalidTool); }).not.toThrow(); }); }); describe('get', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps' }); registry.register(mockTool2, { category: 'collections' }); }); it('should retrieve registered tool', () => { const tool = registry.get('get_stamp'); expect(tool).toBe(mockTool1); }); it('should throw error for non-existent tool', () => { expect(() => { registry.get('non_existent_tool'); }).toThrow('Tool not found: non_existent_tool'); }); }); describe('has', () => { beforeEach(() => { registry.register(mockTool1); }); it('should return true for registered tool', () => { expect(registry.has('get_stamp')).toBe(true); }); it('should return false for non-existent tool', () => { expect(registry.has('non_existent_tool')).toBe(false); }); }); describe('list', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps' }); registry.register(mockTool2, { category: 'collections' }); }); it('should list all registered tool names', () => { const tools = registry.list(); const toolNames = tools.map((tool) => tool.name); expect(toolNames).toContain('get_stamp'); expect(toolNames).toContain('get_collection'); expect(tools).toHaveLength(2); }); }); describe('remove', () => { beforeEach(() => { registry.register(mockTool1); registry.register(mockTool2); }); it('should remove registered tool', () => { expect(registry.has('get_stamp')).toBe(true); registry.remove('get_stamp'); expect(registry.has('get_stamp')).toBe(false); }); it('should return false for non-existent tool', () => { const result = registry.remove('non_existent_tool'); expect(result).toBe(false); }); }); describe('clear', () => { beforeEach(() => { registry.register(mockTool1); registry.register(mockTool2); }); it('should remove all tools', () => { expect(registry.list()).toHaveLength(2); registry.clear(); expect(registry.list()).toHaveLength(0); }); }); describe('getByCategory', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps' }); registry.register(mockTool2, { category: 'collections' }); }); it('should return tools in specified category', () => { const stampsTools = registry.getByCategory('stamps'); expect(stampsTools).toContain('get_stamp'); expect(stampsTools).toHaveLength(1); }); it('should return empty array for non-existent category', () => { const nonExistentTools = registry.getByCategory('non_existent'); expect(nonExistentTools).toEqual([]); }); }); describe('getCategories', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps' }); registry.register(mockTool2, { category: 'collections' }); }); it('should return all categories', () => { const categories = registry.getCategories(); expect(categories).toContain('stamps'); expect(categories).toContain('collections'); expect(categories).toHaveLength(2); }); }); describe('enable/disable', () => { beforeEach(() => { registry.register(mockTool1); }); it('should disable tool', () => { expect(registry.isEnabled('get_stamp')).toBe(true); registry.disable('get_stamp'); expect(registry.isEnabled('get_stamp')).toBe(false); }); it('should enable tool', () => { registry.disable('get_stamp'); expect(registry.isEnabled('get_stamp')).toBe(false); registry.enable('get_stamp'); expect(registry.isEnabled('get_stamp')).toBe(true); }); it('should handle non-existent tools gracefully', () => { expect(() => { registry.disable('non_existent_tool'); }).not.toThrow(); expect(() => { registry.enable('non_existent_tool'); }).not.toThrow(); }); }); describe('getStats', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps' }); registry.register(mockTool2, { category: 'collections' }); registry.disable('get_stamp'); }); it('should return accurate statistics', () => { const stats = registry.getStats(); expect(stats.totalTools).toBe(2); expect(stats.enabledTools).toBe(1); expect(stats.disabledTools).toBe(1); expect(stats.categories).toBe(2); }); }); describe('getMCPTools', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps' }); registry.register(mockTool2, { category: 'collections' }); registry.disable('get_stamp'); }); it('should return only enabled tools in MCP format', () => { const mcpTools = registry.getMCPTools(); expect(mcpTools).toHaveLength(1); expect(mcpTools[0].name).toBe('get_collection'); expect(mcpTools[0].description).toBeDefined(); expect(mcpTools[0].inputSchema).toBeDefined(); }); it('should return all tools when includeDisabled is true', () => { const mcpTools = registry.getMCPTools(true); expect(mcpTools).toHaveLength(2); expect(mcpTools.map((t) => t.name)).toContain('get_stamp'); expect(mcpTools.map((t) => t.name)).toContain('get_collection'); }); }); describe('export/import', () => { beforeEach(() => { registry.register(mockTool1, { category: 'stamps', version: '1.0.0', description: 'Custom description', }); registry.register(mockTool2, { category: 'collections' }); }); it('should export registry configuration', () => { const exported = registry.export(); expect(exported.tools).toHaveLength(2); expect(exported.tools[0].name).toBe('get_stamp'); expect(exported.tools[0].category).toBe('stamps'); expect(exported.options).toBeDefined(); }); it('should import registry configuration', () => { const exported = registry.export(); const newRegistry = new ToolRegistry(); // Note: Import would need to be implemented to recreate tool instances // This test validates the export structure expect(exported.tools).toBeDefined(); expect(exported.options).toBeDefined(); }); }); describe('error handling', () => { it('should handle tool execution errors gracefully', async () => { const context = createMockToolContext(); registry.register(mockTool1); // Mock tool execution to throw error const originalExecute = mockTool1.execute; mockTool1.execute = vi.fn().mockRejectedValueOnce(new Error('Tool execution failed')); const tool = registry.get('get_stamp'); await expect(tool.execute({}, context)).rejects.toThrow('Tool execution failed'); // Restore original method mockTool1.execute = originalExecute; }); }); });

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/stampchain-io/stampchain-mcp'

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