Skip to main content
Glama
McpServer.integration.test.ts9.38 kB
/** * Integration tests for McpServer with tools and resources * * Tests the complete MCP server functionality including run_agent tool * registration, agent resources publication, and MCP client interaction. */ import { AgentManager } from 'src/agents/AgentManager' import { AgentExecutor } from 'src/execution/AgentExecutor' import { McpServer } from 'src/server/McpServer' import type { ServerConfigInterface } from 'src/types' import { afterEach, beforeEach, describe, expect, it } from 'vitest' describe('McpServer Integration', () => { let server: McpServer let mockConfig: ServerConfigInterface beforeEach(() => { mockConfig = { serverName: 'test-mcp-server', serverVersion: '1.0.0', agentsDir: './test-agents', logLevel: 'info', agentType: 'cursor', executionTimeoutMs: 300000, } }) afterEach(async () => { if (server) { await server.close() } }) describe('tool registration', () => { beforeEach(() => { server = new McpServer(mockConfig) }) it('should register run_agent tool during initialization', async () => { // This test will fail initially as run_agent tool integration is not implemented const tools = await server.listTools() expect(tools).toBeDefined() expect(Array.isArray(tools)).toBe(true) const runAgentTool = tools.find((tool) => tool.name === 'run_agent') expect(runAgentTool).toBeDefined() expect(runAgentTool?.description).toContain( 'Delegate complex, multi-step, or specialized tasks' ) }) it('should have correct run_agent tool schema', async () => { const tools = await server.listTools() const runAgentTool = tools.find((tool) => tool.name === 'run_agent') expect(runAgentTool?.inputSchema).toBeDefined() expect(runAgentTool?.inputSchema.type).toBe('object') expect(runAgentTool?.inputSchema.properties).toHaveProperty('agent') expect(runAgentTool?.inputSchema.properties).toHaveProperty('prompt') expect(runAgentTool?.inputSchema.properties).toHaveProperty('cwd') expect(runAgentTool?.inputSchema.properties).toHaveProperty('extra_args') expect(runAgentTool?.inputSchema.required).toEqual(['agent', 'prompt', 'cwd']) }) }) describe('agent resources', () => { beforeEach(() => { server = new McpServer(mockConfig) }) it('should publish agent list resource', async () => { // This test will fail initially as agent resources are not implemented const resources = await server.listResources() expect(resources).toBeDefined() expect(Array.isArray(resources)).toBe(true) const agentListResource = resources.find((resource) => resource.uri === 'agents://list') expect(agentListResource).toBeDefined() expect(agentListResource?.name).toBe('Agent List') expect(agentListResource?.description).toContain('List of available Claude Code sub-agents') }) it('should provide individual agent resources with valid URI format', async () => { const resources = await server.listResources() // Check if individual agent resources are available const agentResources = resources.filter( (resource) => resource.uri.startsWith('agents://') && resource.uri !== 'agents://list' ) // If there are agent resources, verify their structure for (const agentResource of agentResources) { expect(agentResource.name).toBeTruthy() expect(agentResource.description).toBeTruthy() expect(agentResource.uri).toMatch(/^agents:\/\/[\w-]+$/) } }) }) describe('tool execution', () => { beforeEach(() => { server = new McpServer(mockConfig) }) it('should execute run_agent tool with valid parameters', async () => { // This test will fail initially as tool execution is not fully implemented const params = { agent: 'test-agent', prompt: 'Hello, world!', cwd: process.cwd(), } const result = await server.callTool('run_agent', params) expect(result).toBeDefined() expect(result.content).toBeDefined() expect(Array.isArray(result.content)).toBe(true) expect(result.content.length).toBeGreaterThan(0) const textContent = result.content.find((c) => c.type === 'text') expect(textContent).toBeDefined() expect(textContent?.text).toBeDefined() }) it('should validate run_agent tool parameters', async () => { const invalidParams = { // Missing required 'agent' parameter prompt: 'Test prompt', } const result = (await server.callTool('run_agent', invalidParams)) as any expect(result.content).toBeDefined() const textContent = result.content.find((c: any) => c.type === 'text') expect(textContent?.text).toMatch(/agent.*required/i) }) it('should handle non-existent agent gracefully', async () => { const params = { agent: 'nonexistent-agent', prompt: 'Test prompt', cwd: process.cwd(), } const result = await server.callTool('run_agent', params) expect(result).toBeDefined() expect(result.content).toBeDefined() const textContent = result.content.find((c) => c.type === 'text') expect(textContent?.text).toMatch(/not found|Failed to load agents/i) }) }) describe('resource access', () => { beforeEach(() => { server = new McpServer(mockConfig) }) it('should provide agent list resource content', async () => { // This test will fail initially as resource access is not implemented const resource = await server.readResource('agents://list') expect(resource).toBeDefined() expect(resource.contents).toBeDefined() expect(Array.isArray(resource.contents)).toBe(true) if (resource.contents.length > 0) { const content = resource.contents[0] expect(content.type).toBe('text') expect(content.text).toBeDefined() } }) it('should provide individual agent resource content', async () => { // First get the list of available agents const listResource = await server.readResource('agents://list') if (listResource.contents.length > 0) { const agentName = 'test-agent' // Use a test agent name const agentResource = await server.readResource(`agents://${agentName}`) expect(agentResource).toBeDefined() expect(agentResource.contents).toBeDefined() expect(Array.isArray(agentResource.contents)).toBe(true) if (agentResource.contents.length > 0) { const content = agentResource.contents[0] expect(content.type).toBe('text') expect(content.text).toBeDefined() } } }) }) describe('MCP client interaction', () => { beforeEach(() => { server = new McpServer(mockConfig) }) it('should handle complete agent execution workflow', async () => { // This test simulates a complete MCP client interaction // 1. List available tools const tools = await server.listTools() expect(tools.find((t) => t.name === 'run_agent')).toBeDefined() // 2. List available resources const resources = await server.listResources() expect(resources.find((r) => r.uri === 'agents://list')).toBeDefined() // 3. Read agent list resource const agentList = await server.readResource('agents://list') expect(agentList).toBeDefined() // 4. Execute run_agent tool const executionResult = await server.callTool('run_agent', { agent: 'test-agent', prompt: 'Test execution', cwd: process.cwd(), }) expect(executionResult).toBeDefined() expect(executionResult.content).toBeDefined() }) it('should maintain consistent state across operations', async () => { // Perform multiple operations to ensure server state consistency const tools1 = await server.listTools() const resources1 = await server.listResources() // Execute a tool await server.callTool('run_agent', { agent: 'test-agent', prompt: 'State test', cwd: process.cwd(), }) // Check that tool and resource lists remain consistent const tools2 = await server.listTools() const resources2 = await server.listResources() expect(tools2).toEqual(tools1) expect(resources2).toEqual(resources1) }) }) describe('error handling', () => { beforeEach(() => { server = new McpServer(mockConfig) }) it('should handle unknown tool calls gracefully', async () => { await expect(server.callTool('unknown_tool', {})).rejects.toThrow(/unknown.*tool/i) }) it('should handle invalid resource URIs gracefully', async () => { await expect(server.readResource('invalid://resource')).rejects.toThrow( /unknown.*resource|invalid.*uri/i ) }) it('should provide meaningful error messages', async () => { const result = (await server.callTool('run_agent', { /* missing required params */ })) as any expect(result.content).toBeDefined() const textContent = result.content.find((c: any) => c.type === 'text') expect(textContent?.text).toMatch(/agent.*required|prompt.*required/i) }) }) })

Latest Blog Posts

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/shinpr/sub-agents-mcp'

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