Skip to main content
Glama

Letta MCP Server

by oculairmedia
create-agent.test.js12.5 kB
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { handleCreateAgent, createAgentToolDefinition, } from '../../../tools/agents/create-agent.js'; import { createMockLettaServer } from '../../utils/mock-server.js'; import { fixtures } from '../../utils/test-fixtures.js'; import { expectValidToolResponse } from '../../utils/test-helpers.js'; describe('Create Agent', () => { let mockServer; beforeEach(() => { mockServer = createMockLettaServer(); }); afterEach(() => { vi.restoreAllMocks(); }); describe('Tool Definition', () => { it('should have correct tool definition', () => { expect(createAgentToolDefinition.name).toBe('create_agent'); expect(createAgentToolDefinition.description).toContain('Create a new Letta agent'); expect(createAgentToolDefinition.inputSchema.required).toEqual(['name', 'description']); expect(createAgentToolDefinition.inputSchema.properties).toHaveProperty('name'); expect(createAgentToolDefinition.inputSchema.properties).toHaveProperty('description'); expect(createAgentToolDefinition.inputSchema.properties).toHaveProperty('model'); expect(createAgentToolDefinition.inputSchema.properties).toHaveProperty('embedding'); }); it('should have correct default values', () => { expect(createAgentToolDefinition.inputSchema.properties.model.default).toBe( 'openai/gpt-4', ); expect(createAgentToolDefinition.inputSchema.properties.embedding.default).toBe( 'openai/text-embedding-ada-002', ); }); }); describe('Functionality Tests', () => { it('should create agent successfully with minimal args', async () => { const createdAgent = { ...fixtures.agent.basic, id: 'new-agent-123' }; const agentWithTools = { ...createdAgent, tools: [{ name: 'tool1' }, { name: 'tool2' }], }; // Mock successful agent creation mockServer.api.post.mockResolvedValueOnce({ data: createdAgent }); mockServer.api.get.mockResolvedValueOnce({ data: agentWithTools }); const result = await handleCreateAgent(mockServer, { name: 'Test Agent', description: 'A test agent for unit tests', }); // Verify API calls expect(mockServer.api.post).toHaveBeenCalledWith( '/agents/', expect.objectContaining({ name: 'Test Agent', description: 'A test agent for unit tests', agent_type: 'memgpt_agent', model: 'openai/gpt-4', embedding: 'openai/text-embedding-ada-002', }), expect.objectContaining({ headers: expect.any(Object) }), ); expect(mockServer.api.get).toHaveBeenCalledWith( '/agents/new-agent-123', expect.objectContaining({ headers: expect.any(Object) }), ); // Verify response const data = expectValidToolResponse(result); expect(data.agent_id).toBe('new-agent-123'); expect(data.capabilities).toEqual(['tool1', 'tool2']); }); it('should create agent with custom model and embedding', async () => { const createdAgent = { ...fixtures.agent.basic, id: 'custom-agent-123' }; mockServer.api.post.mockResolvedValueOnce({ data: createdAgent }); mockServer.api.get.mockResolvedValueOnce({ data: createdAgent }); const result = await handleCreateAgent(mockServer, { name: 'Custom Model Agent', description: 'An agent with custom models', model: 'anthropic/claude-3', embedding: 'openai/text-embedding-3-large', }); // Verify custom model configuration expect(mockServer.api.post).toHaveBeenCalledWith( '/agents/', expect.objectContaining({ model: 'anthropic/claude-3', embedding: 'openai/text-embedding-3-large', llm_config: expect.objectContaining({ model: 'claude-3', model_endpoint_type: 'anthropic', }), }), expect.any(Object), ); const data = expectValidToolResponse(result); expect(data.agent_id).toBe('custom-agent-123'); }); it('should handle agent without tools', async () => { const agentWithoutTools = { ...fixtures.agent.basic, id: 'no-tools-agent', tools: undefined, }; mockServer.api.post.mockResolvedValueOnce({ data: agentWithoutTools }); mockServer.api.get.mockResolvedValueOnce({ data: agentWithoutTools }); const result = await handleCreateAgent(mockServer, { name: 'No Tools Agent', description: 'An agent without tools', }); const data = expectValidToolResponse(result); expect(data.agent_id).toBe('no-tools-agent'); expect(data.capabilities).toEqual([]); }); it('should include user_id header when retrieving agent info', async () => { const createdAgent = { ...fixtures.agent.basic, id: 'header-test-agent' }; mockServer.api.post.mockResolvedValueOnce({ data: createdAgent }); mockServer.api.get.mockResolvedValueOnce({ data: createdAgent }); await handleCreateAgent(mockServer, { name: 'Header Test Agent', description: 'Testing headers', }); // Verify that get request includes user_id header expect(mockServer.api.get).toHaveBeenCalledWith( '/agents/header-test-agent', expect.objectContaining({ headers: expect.objectContaining({ user_id: 'header-test-agent', }), }), ); }); }); describe('Error Handling', () => { it('should throw error for missing name', async () => { await expect( handleCreateAgent(mockServer, { description: 'Missing name', }), ).rejects.toThrow('Invalid arguments: name and description must be strings'); }); it('should throw error for missing description', async () => { await expect( handleCreateAgent(mockServer, { name: 'Missing Description', }), ).rejects.toThrow('Invalid arguments: name and description must be strings'); }); it('should throw error for non-string name', async () => { await expect( handleCreateAgent(mockServer, { name: 123, description: 'Valid description', }), ).rejects.toThrow('Invalid arguments: name and description must be strings'); }); it('should throw error for non-string description', async () => { await expect( handleCreateAgent(mockServer, { name: 'Valid name', description: { invalid: 'description' }, }), ).rejects.toThrow('Invalid arguments: name and description must be strings'); }); it('should handle API error during agent creation', async () => { const error = new Error('Server error'); error.response = { status: 500, data: { error: 'Internal server error' } }; mockServer.api.post.mockRejectedValueOnce(error); await expect( handleCreateAgent(mockServer, { name: 'Failed Agent', description: 'This will fail', }), ).rejects.toThrow('Server error'); }); it('should handle API error when retrieving agent info', async () => { const createdAgent = { ...fixtures.agent.basic, id: 'error-agent' }; mockServer.api.post.mockResolvedValueOnce({ data: createdAgent }); const error = new Error('Failed to retrieve agent'); error.response = { status: 404 }; mockServer.api.get.mockRejectedValueOnce(error); await expect( handleCreateAgent(mockServer, { name: 'Retrieve Error Agent', description: 'Will fail on retrieval', }), ).rejects.toThrow('Failed to retrieve agent'); }); }); describe('Agent Configuration', () => { it('should create agent with correct llm_config structure', async () => { const createdAgent = { ...fixtures.agent.basic, id: 'config-test-agent' }; mockServer.api.post.mockResolvedValueOnce({ data: createdAgent }); mockServer.api.get.mockResolvedValueOnce({ data: createdAgent }); await handleCreateAgent(mockServer, { name: 'Config Test Agent', description: 'Testing configuration', model: 'openai/gpt-4-turbo', }); expect(mockServer.api.post).toHaveBeenCalledWith( '/agents/', expect.objectContaining({ llm_config: { model: 'gpt-4-turbo', model_endpoint_type: 'openai', model_endpoint: 'https://api.openai.com/v1', context_window: 16000, max_tokens: 1000, temperature: 0.7, frequency_penalty: 0.5, presence_penalty: 0.5, functions_config: { allow: true, functions: [], }, }, parameters: { context_window: 16000, max_tokens: 1000, temperature: 0.7, presence_penalty: 0.5, frequency_penalty: 0.5, }, }), expect.any(Object), ); }); it('should handle letta-free model correctly', async () => { const createdAgent = { ...fixtures.agent.basic, id: 'letta-free-agent' }; const agentWithTools = { ...createdAgent, tools: [{ name: 'tool1' }, { name: 'tool2' }], }; // Mock successful agent creation mockServer.api.post.mockResolvedValueOnce({ data: createdAgent }); mockServer.api.get.mockResolvedValueOnce({ data: agentWithTools }); const result = await handleCreateAgent(mockServer, { name: 'Letta Free Agent', description: 'Testing letta free model', model: 'letta/letta-free', embedding: 'letta/letta-free', }); expect(mockServer.api.post).toHaveBeenCalledWith( '/agents/', expect.objectContaining({ model: 'letta/letta-free', llm_config: expect.objectContaining({ model: 'letta-free', model_endpoint_type: 'openai', model_endpoint: 'https://inference.letta.com', }), }), expect.any(Object), ); expect(result).toEqual({ content: [ { type: 'text', text: JSON.stringify({ agent_id: 'letta-free-agent', capabilities: ['tool1', 'tool2'], }), }, ], structuredContent: { agent_id: 'letta-free-agent', capabilities: ['tool1', 'tool2'], }, }); }); }); });

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