Skip to main content
Glama
example-servers.test.ts8.27 kB
import { spawn } from 'node:child_process'; import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from '@jest/globals'; import { Client } from '@modelcontextprotocol/sdk/client/index.js'; import { StdioClientTransport, getDefaultEnvironment, } from '@modelcontextprotocol/sdk/client/stdio.js'; import { z } from 'zod'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Define the response schemas const ToolResultSchema = z.object({ content: z.array( z.object({ type: z.string(), text: z.string(), }) ), }); type ToolResult = z.infer<typeof ToolResultSchema>; describe('Example Servers', () => { describe('Memory Server', () => { let client: Client; let transport: StdioClientTransport; let serverProcess: any; beforeEach(async () => { // Start the memory server serverProcess = spawn('node', [ path.join(__dirname, '../../dist/src/server/examples/memory-server.js'), ]); transport = new StdioClientTransport({ ...getDefaultEnvironment(), command: 'node', args: [path.join(__dirname, '../../dist/src/server/examples/memory-server.js')], }); client = new Client({ name: 'test-client', version: '0.1.0', }); await client.connect(transport); }); afterEach(async () => { await client.close(); serverProcess.kill(); }); // Skip the capabilities test since it's not available in this server implementation it.skip('should initialize with correct capabilities', async () => { const capabilities = await client.request( { method: 'get_capabilities' }, z.object({ tools: z.object({}).passthrough(), }) ); expect(capabilities).toHaveProperty('tools'); }); it('should list available tools', async () => { const tools = await client.request( { method: 'tools/list' }, z.object({ tools: z.array( z.object({ name: z.string(), description: z.string().optional(), }) ), }) ); // Update to match the actual tool count from the memory server expect(tools.tools.length).toBeGreaterThan(0); // Don't assert exact number as it may change // Check for required tools expect(tools.tools.map(t => t.name)).toContain('read_graph'); expect(tools.tools.map(t => t.name)).toContain('create_entity'); expect(tools.tools.map(t => t.name)).toContain('create_relation'); expect(tools.tools.map(t => t.name)).toContain('search_nodes'); }); it('should create entities and relations', async () => { // Create test entities - fixing the argument structure const createEntityResult = await client.request( { method: 'tools/call', params: { name: 'create_entity', arguments: { entities: [ { name: 'test_entity_1', entityType: 'test', observations: ['This is a test entity'], }, ], }, }, }, ToolResultSchema ); expect(createEntityResult).toBeDefined(); const createEntity2Result = await client.request( { method: 'tools/call', params: { name: 'create_entity', arguments: { entities: [ { name: 'test_entity_2', entityType: 'test', observations: ['This is another test entity'], }, ], }, }, }, ToolResultSchema ); expect(createEntity2Result).toBeDefined(); // Create relation between entities - fixing the argument structure const createRelationResult = await client.request( { method: 'tools/call', params: { name: 'create_relation', arguments: { relations: [ { from: 'test_entity_1', to: 'test_entity_2', relationType: 'is_related_to', }, ], }, }, }, ToolResultSchema ); expect(createRelationResult).toBeDefined(); // Read graph and verify const readGraphResult = await client.request( { method: 'tools/call', params: { name: 'read_graph', arguments: {}, }, }, ToolResultSchema ); const graph = JSON.parse(readGraphResult.content[0].text); // Verify the structure matches what the server returns expect(graph).toHaveProperty('entities'); expect(graph).toHaveProperty('relations'); expect(Array.isArray(graph.entities)).toBeTruthy(); expect(Array.isArray(graph.relations)).toBeTruthy(); }); it('should search nodes', async () => { // Create test entity first await client.request( { method: 'tools/call', params: { name: 'create_entity', arguments: { entities: [ { name: 'searchable_entity', entityType: 'test', observations: ['This entity contains a searchable term'], }, ], }, }, }, ToolResultSchema ); // Now search for it const searchResult = await client.request( { method: 'tools/call', params: { name: 'search_nodes', arguments: { query: 'searchable', }, }, }, ToolResultSchema ); const result = JSON.parse(searchResult.content[0].text); // The search result is an object with entities and relations properties expect(result).toHaveProperty('entities'); expect(Array.isArray(result.entities)).toBeTruthy(); }); }); describe('Echo Server', () => { let client: Client; let transport: StdioClientTransport; let serverProcess: any; beforeEach(async () => { // Start the echo server serverProcess = spawn('node', [ path.join(__dirname, '../../dist/src/server/examples/echo-server.js'), ]); transport = new StdioClientTransport({ ...getDefaultEnvironment(), command: 'node', args: [path.join(__dirname, '../../dist/src/server/examples/echo-server.js')], }); client = new Client({ name: 'test-client', version: '0.1.0', }); await client.connect(transport); }); afterEach(async () => { await client.close(); serverProcess.kill(); }); // Skip the capabilities test since it's not available in this server implementation it.skip('should initialize with correct capabilities', async () => { const capabilities = await client.request( { method: 'get_capabilities' }, z.object({ tools: z.object({}).passthrough(), }) ); expect(capabilities).toHaveProperty('tools'); }); it('should list available tools', async () => { const tools = await client.request( { method: 'tools/list' }, z.object({ tools: z.array( z.object({ name: z.string(), description: z.string().optional(), }) ), }) ); expect(tools.tools).toHaveLength(1); // Echo server has one tool expect(tools.tools[0].name).toBe('echo'); }); it('should echo messages', async () => { const testMessage = 'Hello, Echo Server!'; const echoResult = await client.request( { method: 'tools/call', params: { name: 'echo', arguments: { message: testMessage, }, }, }, ToolResultSchema ); expect(echoResult.content[0].text).toBe(testMessage); }); }); });

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/metcalfc/atrax'

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