Skip to main content
Glama

mcp-graphql-forge

by toolprint
integration.test.ts8.55 kB
import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { introspectGraphQLSchema } from '../introspect.js'; import { generateMCPToolsFromSchema } from '../tool-generator.js'; import { createMockGraphQLServer } from './fixtures/mock-server.js'; describe('Integration Tests', () => { const mockServer = createMockGraphQLServer(4002); beforeAll(async () => { await mockServer.start(); }); afterAll(async () => { await mockServer.stop(); }); describe('End-to-End Schema Processing', () => { it('should complete full workflow: introspect -> generate tools', async () => { // Step 1: Introspect the schema const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql' }); expect(introspectionResult).toBeDefined(); expect(introspectionResult.__schema).toBeDefined(); // Step 2: Generate MCP tools from the introspection result const tools = generateMCPToolsFromSchema(introspectionResult); expect(tools).toBeInstanceOf(Array); expect(tools.length).toBeGreaterThan(0); // Verify we have both query and mutation tools const queryTools = tools.filter(tool => tool.name.startsWith('query_')); const mutationTools = tools.filter(tool => tool.name.startsWith('mutation_')); expect(queryTools.length).toBeGreaterThan(0); expect(mutationTools.length).toBeGreaterThan(0); // Verify tools have correct structure tools.forEach(tool => { expect(tool).toHaveProperty('name'); expect(tool).toHaveProperty('description'); expect(tool).toHaveProperty('inputSchema'); expect(tool.inputSchema).toHaveProperty('type'); expect(tool.inputSchema).toHaveProperty('properties'); expect(typeof tool.name).toBe('string'); expect(typeof tool.description).toBe('string'); expect(tool.inputSchema.type).toBe('object'); }); }); it('should generate tools that match GraphQL schema structure', async () => { const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql' }); const tools = generateMCPToolsFromSchema(introspectionResult); // Find specific tools and verify their properties const userTool = tools.find(tool => tool.name === 'query_user'); expect(userTool).toBeDefined(); expect(userTool?.inputSchema.properties.id).toBeDefined(); expect(userTool?.inputSchema.required).toContain('id'); const createUserTool = tools.find(tool => tool.name === 'mutation_createUser'); expect(createUserTool).toBeDefined(); expect(createUserTool?.inputSchema.properties.input).toBeDefined(); expect(createUserTool?.inputSchema.required).toContain('input'); const usersTool = tools.find(tool => tool.name === 'query_users'); expect(usersTool).toBeDefined(); expect(usersTool?.inputSchema.properties.filters).toBeDefined(); expect(usersTool?.inputSchema.properties.limit).toBeDefined(); expect(usersTool?.inputSchema.properties.offset).toBeDefined(); }); it('should handle authentication headers in introspection', async () => { const headers = { 'Authorization': 'Bearer test-token', 'X-API-Key': 'test-api-key' }; const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql', headers }); expect(introspectionResult).toBeDefined(); expect(introspectionResult.__schema).toBeDefined(); const tools = generateMCPToolsFromSchema(introspectionResult); expect(tools.length).toBeGreaterThan(0); }); }); describe('Tool Schema Validation', () => { it('should generate valid JSON schemas for all tools', async () => { const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql' }); const tools = generateMCPToolsFromSchema(introspectionResult); tools.forEach(tool => { const schema = tool.inputSchema; // Validate basic JSON schema structure expect(schema.type).toBe('object'); expect(typeof schema.properties).toBe('object'); // Validate property types Object.values(schema.properties).forEach((property: Record<string, unknown>) => { expect(property).toHaveProperty('type'); expect(typeof property.type).toBe('string'); if (property.type === 'array') { expect(property).toHaveProperty('items'); expect(property.items).toHaveProperty('type'); } if (property.type === 'object') { expect(property).toHaveProperty('properties'); } if (property.enum) { expect(property.enum).toBeInstanceOf(Array); expect(property.enum.length).toBeGreaterThan(0); } }); // Validate required fields exist in properties if (schema.required) { schema.required.forEach((requiredField: string) => { expect(schema.properties).toHaveProperty(requiredField); }); } }); }); it('should correctly map GraphQL types to JSON schema types', async () => { const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql' }); const tools = generateMCPToolsFromSchema(introspectionResult); // Test String -> string const userTool = tools.find(tool => tool.name === 'query_user'); expect(userTool?.inputSchema.properties.id.type).toBe('string'); // Test Int -> integer const usersTool = tools.find(tool => tool.name === 'query_users'); expect(usersTool?.inputSchema.properties.limit?.type).toBe('integer'); expect(usersTool?.inputSchema.properties.offset?.type).toBe('integer'); // Test Enum -> string with enum values const filtersProperty = usersTool?.inputSchema.properties.filters; if (filtersProperty?.properties?.role) { expect(filtersProperty.properties.role.type).toBe('string'); expect(filtersProperty.properties.role.enum).toBeInstanceOf(Array); expect(filtersProperty.properties.role.enum).toContain('ADMIN'); } // Test Array -> array with items const createPostTool = tools.find(tool => tool.name === 'mutation_createPost'); expect(createPostTool?.inputSchema.properties.tags?.type).toBe('array'); expect(createPostTool?.inputSchema.properties.tags?.items?.type).toBe('string'); }); }); describe('Performance and Efficiency', () => { it('should complete introspection and tool generation within reasonable time', async () => { const startTime = Date.now(); const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql' }); const introspectionTime = Date.now(); const tools = generateMCPToolsFromSchema(introspectionResult); const endTime = Date.now(); const totalTime = endTime - startTime; const introspectionDuration = introspectionTime - startTime; const generationDuration = endTime - introspectionTime; // These are reasonable performance expectations expect(totalTime).toBeLessThan(5000); // Less than 5 seconds total expect(introspectionDuration).toBeLessThan(3000); // Less than 3 seconds for introspection expect(generationDuration).toBeLessThan(1000); // Less than 1 second for generation expect(tools.length).toBeGreaterThan(0); }); it('should handle large schemas efficiently', async () => { // This test uses our mock schema which is reasonably complex const introspectionResult = await introspectGraphQLSchema({ endpoint: 'http://localhost:4002/graphql' }); const tools = generateMCPToolsFromSchema(introspectionResult); // Verify all expected tools are generated expect(tools.length).toBeGreaterThanOrEqual(11); // 5 queries + 6 mutations from our schema // Verify performance: should generate tools quickly even for complex schemas const startTime = Date.now(); const toolsAgain = generateMCPToolsFromSchema(introspectionResult); const endTime = Date.now(); expect(endTime - startTime).toBeLessThan(100); // Should be very fast on second run expect(toolsAgain.length).toBe(tools.length); }); }); });

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/toolprint/mcp-graphql-forge'

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