UNPKG

@toolprint/mcp-graphql-forge

Version:

MCP server that exposes GraphQL APIs to AI tools through automatic schema introspection and tool generation

152 lines 9.09 kB
import { describe, it, expect } from 'vitest'; import { generateMCPToolsFromSchema } from '../tool-generator.js'; import { mockIntrospectionResult } from './fixtures/introspection-result.js'; describe('MCP Tool Generator', () => { describe('generateMCPToolsFromSchema', () => { it('should generate tools from introspection result', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); expect(tools).toBeInstanceOf(Array); expect(tools.length).toBeGreaterThan(0); }); it('should generate query tools with correct naming', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const queryTools = tools.filter(tool => tool.name.startsWith('query_')); expect(queryTools.length).toBeGreaterThan(0); const toolNames = queryTools.map(tool => tool.name); expect(toolNames).toContain('query_user'); expect(toolNames).toContain('query_users'); expect(toolNames).toContain('query_userCount'); expect(toolNames).toContain('query_post'); expect(toolNames).toContain('query_posts'); }); it('should generate mutation tools with correct naming', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const mutationTools = tools.filter(tool => tool.name.startsWith('mutation_')); expect(mutationTools.length).toBeGreaterThan(0); const toolNames = mutationTools.map(tool => tool.name); expect(toolNames).toContain('mutation_createUser'); expect(toolNames).toContain('mutation_updateUser'); expect(toolNames).toContain('mutation_deleteUser'); expect(toolNames).toContain('mutation_createPost'); expect(toolNames).toContain('mutation_publishPost'); expect(toolNames).toContain('mutation_deletePost'); }); it('should include proper descriptions for tools', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const userTool = tools.find(tool => tool.name === 'query_user'); expect(userTool).toBeDefined(); expect(userTool?.description).toMatch(/user/i); const createUserTool = tools.find(tool => tool.name === 'mutation_createUser'); expect(createUserTool).toBeDefined(); expect(createUserTool?.description).toMatch(/create.*user/i); }); }); describe('Input Schema Generation', () => { it('should generate correct input schema for required arguments', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const userTool = tools.find(tool => tool.name === 'query_user'); expect(userTool).toBeDefined(); expect(userTool?.inputSchema.type).toBe('object'); expect(userTool?.inputSchema.properties.id).toBeDefined(); expect(userTool?.inputSchema.properties.id.type).toBe('string'); expect(userTool?.inputSchema.required).toContain('id'); }); it('should generate correct input schema for optional arguments', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const usersTool = tools.find(tool => tool.name === 'query_users'); expect(usersTool).toBeDefined(); expect(usersTool?.inputSchema.properties.limit).toBeDefined(); expect(usersTool?.inputSchema.properties.limit.type).toBe('integer'); expect(usersTool?.inputSchema.properties.offset).toBeDefined(); expect(usersTool?.inputSchema.properties.offset.type).toBe('integer'); expect(usersTool?.inputSchema.required || []).not.toContain('limit'); expect(usersTool?.inputSchema.required || []).not.toContain('offset'); }); it('should handle complex input objects', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const createUserTool = tools.find(tool => tool.name === 'mutation_createUser'); expect(createUserTool).toBeDefined(); expect(createUserTool?.inputSchema.properties.input).toBeDefined(); expect(createUserTool?.inputSchema.properties.input.type).toBe('object'); expect(createUserTool?.inputSchema.required).toContain('input'); const inputProps = createUserTool?.inputSchema.properties.input.properties; expect(inputProps?.name).toBeDefined(); expect(inputProps?.name.type).toBe('string'); expect(inputProps?.email).toBeDefined(); expect(inputProps?.email.type).toBe('string'); expect(inputProps?.role).toBeDefined(); expect(inputProps?.role.type).toBe('string'); expect(inputProps?.role.enum).toContain('ADMIN'); expect(inputProps?.role.enum).toContain('USER'); expect(inputProps?.role.enum).toContain('MODERATOR'); }); it('should handle array types correctly', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const createPostTool = tools.find(tool => tool.name === 'mutation_createPost'); expect(createPostTool).toBeDefined(); expect(createPostTool?.inputSchema.properties.tags).toBeDefined(); expect(createPostTool?.inputSchema.properties.tags.type).toBe('array'); expect(createPostTool?.inputSchema.properties.tags.items).toBeDefined(); expect(createPostTool?.inputSchema.properties.tags.items.type).toBe('string'); }); it('should handle enum types correctly', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const usersTool = tools.find(tool => tool.name === 'query_users'); expect(usersTool).toBeDefined(); const filtersInput = usersTool?.inputSchema.properties.filters; expect(filtersInput).toBeDefined(); expect(filtersInput.type).toBe('object'); const roleProperty = filtersInput.properties?.role; expect(roleProperty).toBeDefined(); expect(roleProperty.type).toBe('string'); expect(roleProperty.enum).toBeInstanceOf(Array); expect(roleProperty.enum).toContain('ADMIN'); expect(roleProperty.enum).toContain('USER'); expect(roleProperty.enum).toContain('MODERATOR'); }); it('should handle scalar types correctly', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const usersTool = tools.find(tool => tool.name === 'query_users'); expect(usersTool).toBeDefined(); const filtersInput = usersTool?.inputSchema.properties.filters; const filtersProps = filtersInput?.properties; expect(filtersProps?.minAge?.type).toBe('integer'); expect(filtersProps?.maxAge?.type).toBe('integer'); expect(filtersProps?.searchTerm?.type).toBe('string'); }); it('should handle tools with no arguments', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const allTools = tools.filter(tool => Object.keys(tool.inputSchema.properties).length === 0); allTools.forEach(tool => { expect(tool.inputSchema.type).toBe('object'); expect(tool.inputSchema.properties).toEqual({}); expect(tool.inputSchema.required || []).toHaveLength(0); }); }); }); describe('Edge Cases', () => { it('should handle fields with descriptions', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const userTool = tools.find(tool => tool.name === 'query_user'); expect(userTool).toBeDefined(); expect(typeof userTool?.description).toBe('string'); expect(userTool?.description.length).toBeGreaterThan(0); }); it('should generate unique tool names', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const toolNames = tools.map(tool => tool.name); const uniqueNames = new Set(toolNames); expect(toolNames.length).toBe(uniqueNames.size); }); it('should handle nested input object requirements correctly', () => { const tools = generateMCPToolsFromSchema(mockIntrospectionResult); const createUserTool = tools.find(tool => tool.name === 'mutation_createUser'); const inputSchema = createUserTool?.inputSchema.properties.input; expect(inputSchema?.required).toContain('name'); expect(inputSchema?.required).toContain('email'); expect(inputSchema?.required).not.toContain('age'); expect(inputSchema?.required).not.toContain('role'); }); }); }); //# sourceMappingURL=tool-generator.test.js.map