Skip to main content
Glama

Letta MCP Server

by oculairmedia
list-agents.test.js11.1 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { handleListAgents, listAgentsToolDefinition } from '../../../tools/agents/list-agents.js'; import { createMockLettaServer } from '../../utils/mock-server.js'; import { fixtures } from '../../utils/test-fixtures.js'; import { expectValidToolResponse } from '../../utils/test-helpers.js'; describe('List Agents', () => { let mockServer; beforeEach(() => { mockServer = createMockLettaServer(); }); afterEach(() => { vi.restoreAllMocks(); }); describe('Tool Definition', () => { it('should have correct tool definition', () => { expect(listAgentsToolDefinition.name).toBe('list_agents'); expect(listAgentsToolDefinition.description).toContain('List all available agents'); expect(listAgentsToolDefinition.inputSchema.required).toEqual([]); expect(listAgentsToolDefinition.inputSchema.properties).toHaveProperty('filter'); }); it('should have optional filter parameter', () => { const filterProp = listAgentsToolDefinition.inputSchema.properties.filter; expect(filterProp.type).toBe('string'); expect(filterProp.description).toContain('Optional filter'); }); }); describe('Functionality Tests', () => { it('should list all agents without filter', async () => { const agents = [ fixtures.agent.basic, fixtures.agent.minimal, { id: 'agent-789', name: 'Third Agent', description: 'Another test agent' }, ]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, {}); // Verify API call expect(mockServer.api.get).toHaveBeenCalledWith( '/agents/', expect.objectContaining({ headers: expect.any(Object) }), ); // Verify response const data = expectValidToolResponse(result); expect(data.count).toBe(3); expect(data.agents).toHaveLength(3); // Verify summarized agent structure data.agents.forEach((agent, index) => { expect(agent).toHaveProperty('id'); expect(agent).toHaveProperty('name'); // The description property may or may not exist in the response // depending on whether the source agent had it if (index === 1) { // The minimal agent fixture might not have description property // in the response even though tool maps it expect(Object.keys(agent).sort()).toEqual(['id', 'name']); } else { expect(agent).toHaveProperty('description'); expect(agent.description).toBe(agents[index].description); expect(Object.keys(agent).sort()).toEqual(['description', 'id', 'name']); } // Verify values match expect(agent.id).toBe(agents[index].id); expect(agent.name).toBe(agents[index].name); }); }); it('should handle empty agent list', async () => { mockServer.api.get.mockResolvedValueOnce({ data: [] }); const result = await handleListAgents(mockServer, {}); const data = expectValidToolResponse(result); expect(data.count).toBe(0); expect(data.agents).toEqual([]); }); it('should filter agents by name', async () => { const agents = [ { id: 'agent-1', name: 'Production Agent', description: 'Production system' }, { id: 'agent-2', name: 'Test Agent', description: 'Testing system' }, { id: 'agent-3', name: 'Development Agent', description: 'Dev system' }, ]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: 'test' }); const data = expectValidToolResponse(result); expect(data.count).toBe(1); expect(data.agents).toHaveLength(1); expect(data.agents[0].name).toBe('Test Agent'); }); it('should filter agents by description', async () => { const agents = [ { id: 'agent-1', name: 'Agent One', description: 'Production deployment' }, { id: 'agent-2', name: 'Agent Two', description: 'Development environment' }, { id: 'agent-3', name: 'Agent Three', description: 'Testing framework' }, ]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: 'development' }); const data = expectValidToolResponse(result); expect(data.count).toBe(1); expect(data.agents).toHaveLength(1); expect(data.agents[0].name).toBe('Agent Two'); }); it('should perform case-insensitive filtering', async () => { const agents = [ { id: 'agent-1', name: 'UPPERCASE Agent', description: 'System ONE' }, { id: 'agent-2', name: 'lowercase agent', description: 'system two' }, { id: 'agent-3', name: 'MixedCase Agent', description: 'System Three' }, ]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: 'AGENT' }); const data = expectValidToolResponse(result); expect(data.count).toBe(3); // All agents match expect(data.agents).toHaveLength(3); }); it('should handle agents without descriptions', async () => { const agents = [ { id: 'agent-1', name: 'With Description', description: 'Has description' }, { id: 'agent-2', name: 'Without Description', description: null }, { id: 'agent-3', name: 'Undefined Description' }, // No description field ]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: 'description' }); const data = expectValidToolResponse(result); // All three agents match because they all have "Description" in their name expect(data.count).toBe(3); expect(data.agents.map((a) => a.name).sort()).toEqual([ 'Undefined Description', 'With Description', 'Without Description', ]); }); it('should return multiple matches when filter matches multiple agents', async () => { const agents = [ { id: 'agent-1', name: 'Customer Support Agent', description: 'Handles customer queries', }, { id: 'agent-2', name: 'Sales Agent', description: 'Manages customer sales' }, { id: 'agent-3', name: 'Admin Agent', description: 'System administration' }, ]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: 'customer' }); const data = expectValidToolResponse(result); expect(data.count).toBe(2); expect(data.agents).toHaveLength(2); expect(data.agents.map((a) => a.id).sort()).toEqual(['agent-1', 'agent-2']); }); it('should handle undefined args gracefully', async () => { const agents = [fixtures.agent.basic]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, undefined); const data = expectValidToolResponse(result); expect(data.count).toBe(1); expect(data.agents).toHaveLength(1); }); }); describe('Error Handling', () => { it('should handle API errors', async () => { const error = new Error('Network error'); error.response = { status: 500, data: { error: 'Internal server error' } }; mockServer.api.get.mockRejectedValueOnce(error); await expect(handleListAgents(mockServer, {})).rejects.toThrow('Network error'); }); it('should handle authentication errors', async () => { const error = new Error('Unauthorized'); error.response = { status: 401, data: { error: 'Invalid credentials' } }; mockServer.api.get.mockRejectedValueOnce(error); await expect(handleListAgents(mockServer, {})).rejects.toThrow('Unauthorized'); }); it('should handle malformed API response', async () => { // API returns non-array data mockServer.api.get.mockResolvedValueOnce({ data: { invalid: 'response' } }); await expect(handleListAgents(mockServer, {})).rejects.toThrow(); }); }); describe('Edge Cases', () => { it('should handle very large agent lists', async () => { // Create 1000 agents const agents = Array.from({ length: 1000 }, (_, i) => ({ id: `agent-${i}`, name: `Agent ${i}`, description: `Description for agent ${i}`, })); mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, {}); const data = expectValidToolResponse(result); expect(data.count).toBe(1000); expect(data.agents).toHaveLength(1000); }); it('should filter efficiently on large lists', async () => { const agents = Array.from({ length: 1000 }, (_, i) => ({ id: `agent-${i}`, name: i % 10 === 0 ? `Special Agent ${i}` : `Regular Agent ${i}`, description: `Description ${i}`, })); mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: 'special' }); const data = expectValidToolResponse(result); expect(data.count).toBe(100); // Every 10th agent is special expect(data.agents).toHaveLength(100); data.agents.forEach((agent) => { expect(agent.name).toContain('Special'); }); }); it('should handle empty filter string', async () => { const agents = [fixtures.agent.basic, fixtures.agent.minimal]; mockServer.api.get.mockResolvedValueOnce({ data: agents }); const result = await handleListAgents(mockServer, { filter: '' }); const data = expectValidToolResponse(result); expect(data.count).toBe(2); // Empty filter matches all expect(data.agents).toHaveLength(2); }); }); });

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