Skip to main content
Glama

Letta MCP Server

by oculairmedia
tool-registration.test.js4.76 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { LettaServer } from '../../core/server.js'; import { registerToolHandlers } from '../../tools/index.js'; // Mock dependencies vi.mock('@modelcontextprotocol/sdk/server/index.js'); vi.mock('axios'); vi.mock('../../core/logger.js'); describe('Tool Registration (LMP-84)', () => { let server; let registeredHandlers; beforeEach(() => { // Set required env vars process.env.LETTA_BASE_URL = 'https://test.letta.com'; process.env.LETTA_PASSWORD = 'test-password'; // Track registered handlers registeredHandlers = []; // Create server instance server = new LettaServer(); // Mock setRequestHandler to capture registrations server.server.setRequestHandler = vi.fn((schema, handler) => { registeredHandlers.push({ schema, handler }); }); }); describe('Handler Registration', () => { it('should register tool handlers', () => { registerToolHandlers(server); // Should register exactly 2 handlers expect(registeredHandlers).toHaveLength(2); expect(server.server.setRequestHandler).toHaveBeenCalledTimes(2); }); it('should register tools/list handler first', () => { registerToolHandlers(server); // First handler should be list tools const firstHandler = registeredHandlers[0]; expect(firstHandler).toBeDefined(); expect(firstHandler.handler).toBeTypeOf('function'); }); it('should register tools/call handler second', () => { registerToolHandlers(server); // Second handler should be call tool const secondHandler = registeredHandlers[1]; expect(secondHandler).toBeDefined(); expect(secondHandler.handler).toBeTypeOf('function'); }); }); describe('List Tools Handler', () => { it('should return list of available tools', async () => { registerToolHandlers(server); // Get the list tools handler (first one registered) const listToolsHandler = registeredHandlers[0].handler; const response = await listToolsHandler({}); expect(response).toHaveProperty('tools'); expect(Array.isArray(response.tools)).toBe(true); expect(response.tools.length).toBeGreaterThan(0); }); it('should return tools with correct structure', async () => { registerToolHandlers(server); const listToolsHandler = registeredHandlers[0].handler; const response = await listToolsHandler({}); // Check first tool structure const firstTool = response.tools[0]; expect(firstTool).toHaveProperty('name'); expect(firstTool).toHaveProperty('description'); expect(firstTool).toHaveProperty('inputSchema'); }); it('should include expected tool names', async () => { registerToolHandlers(server); const listToolsHandler = registeredHandlers[0].handler; const response = await listToolsHandler({}); const toolNames = response.tools.map((t) => t.name); expect(toolNames).toContain('list_agents'); expect(toolNames).toContain('prompt_agent'); expect(toolNames).toContain('list_memory_blocks'); }); }); describe('Call Tool Handler', () => { it('should be registered as second handler', () => { registerToolHandlers(server); // Get the call tool handler (second one registered) const callToolHandler = registeredHandlers[1].handler; expect(callToolHandler).toBeTypeOf('function'); }); it('should throw error for unknown tool', async () => { registerToolHandlers(server); const callToolHandler = registeredHandlers[1].handler; const request = { params: { name: 'unknown_tool', arguments: {}, }, }; await expect(callToolHandler(request)).rejects.toThrow(); }); }); describe('Error Handling', () => { it('should handle registration on server without MCP server', () => { const invalidServer = { server: null }; expect(() => { registerToolHandlers(invalidServer); }).toThrow(); }); it('should handle registration on undefined server', () => { expect(() => { registerToolHandlers(undefined); }).toThrow(); }); }); });

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/oculairmedia/Letta-MCP-server'

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