Skip to main content
Glama
mcp-protocol.spec.ts9.82 kB
/** * End-to-end tests for MCP protocol implementation */ import { test, expect } from '@playwright/test'; test.describe('MCP Protocol Integration', () => { test.beforeEach(async ({ page }) => { // Set up authenticated state await page.addInitScript(() => { const validToken = { access_token: 'valid_test_token', token_type: 'Bearer', expires_in: 3600, obtained_at: Date.now(), refresh_token: 'valid_refresh_token', }; (globalThis as any).localStorage.setItem('wp_oauth_tokens', JSON.stringify(validToken)); }); }); test('should handle MCP initialization', async ({ page }) => { // Navigate to MCP endpoint await page.goto('/mcp/initialize'); // Should return proper MCP initialization response const response = await page.locator('pre').textContent(); const mcpResponse = JSON.parse(response || '{}'); expect(mcpResponse).toHaveProperty('serverInfo'); expect(mcpResponse).toHaveProperty('capabilities'); expect(mcpResponse.serverInfo).toHaveProperty('name'); expect(mcpResponse.serverInfo).toHaveProperty('version'); }); test('should list available tools via MCP', async ({ page }) => { await page.goto('/mcp/tools/list'); const response = await page.locator('pre').textContent(); const mcpResponse = JSON.parse(response || '{}'); expect(mcpResponse).toHaveProperty('tools'); expect(Array.isArray(mcpResponse.tools)).toBe(true); // Should include WordPress-specific tools const toolNames = mcpResponse.tools.map((tool: any) => tool.name); expect(toolNames).toContain('wordpress_get_posts'); expect(toolNames).toContain('wordpress_create_post'); }); test('should execute WordPress tools via MCP', async ({ page }) => { // Test tool execution await page.goto('/mcp/tools/call', { waitUntil: 'networkidle', }); // Fill in tool call form await page.fill('#tool-name', 'wordpress_get_posts'); await page.fill('#tool-arguments', JSON.stringify({ limit: 5 })); await page.click('#execute-tool'); // Should show tool execution result await expect(page.locator('.tool-result')).toBeVisible(); const result = await page.locator('.tool-result pre').textContent(); const toolResponse = JSON.parse(result || '{}'); expect(toolResponse).toHaveProperty('content'); expect(Array.isArray(toolResponse.content)).toBe(true); }); test('should list available resources via MCP', async ({ page }) => { await page.goto('/mcp/resources/list'); const response = await page.locator('pre').textContent(); const mcpResponse = JSON.parse(response || '{}'); expect(mcpResponse).toHaveProperty('resources'); expect(Array.isArray(mcpResponse.resources)).toBe(true); // Should include WordPress resources const resourceUris = mcpResponse.resources.map((resource: any) => resource.uri); expect(resourceUris.some((uri: string) => uri.includes('wordpress://posts'))).toBe(true); }); test('should read WordPress resources via MCP', async ({ page }) => { await page.goto('/mcp/resources/read'); // Fill in resource URI await page.fill('#resource-uri', 'wordpress://posts'); await page.click('#read-resource'); // Should show resource content await expect(page.locator('.resource-content')).toBeVisible(); const content = await page.locator('.resource-content pre').textContent(); const resourceData = JSON.parse(content || '{}'); expect(resourceData).toHaveProperty('contents'); expect(Array.isArray(resourceData.contents)).toBe(true); }); test('should handle MCP prompts', async ({ page }) => { await page.goto('/mcp/prompts/list'); const response = await page.locator('pre').textContent(); const mcpResponse = JSON.parse(response || '{}'); expect(mcpResponse).toHaveProperty('prompts'); expect(Array.isArray(mcpResponse.prompts)).toBe(true); }); test('should execute MCP prompts with arguments', async ({ page }) => { await page.goto('/mcp/prompts/get'); // Fill in prompt details await page.fill('#prompt-name', 'wordpress_content_summary'); await page.fill('#prompt-arguments', JSON.stringify({ post_type: 'post', limit: 10 })); await page.click('#get-prompt'); // Should show prompt result await expect(page.locator('.prompt-result')).toBeVisible(); const result = await page.locator('.prompt-result pre').textContent(); const promptResponse = JSON.parse(result || '{}'); expect(promptResponse).toHaveProperty('messages'); expect(Array.isArray(promptResponse.messages)).toBe(true); }); test('should handle MCP error responses', async ({ page }) => { // Test invalid tool call await page.goto('/mcp/tools/call'); await page.fill('#tool-name', 'nonexistent_tool'); await page.fill('#tool-arguments', '{}'); await page.click('#execute-tool'); // Should show error response await expect(page.locator('.error-message')).toBeVisible(); const errorText = await page.locator('.error-message').textContent(); expect(errorText).toContain('Tool not found'); }); test('should maintain MCP session state', async ({ page }) => { // Make multiple MCP requests to verify session consistency await page.goto('/mcp/tools/list'); const tools1 = await page.locator('pre').textContent(); await page.goto('/mcp/resources/list'); const resources = await page.locator('pre').textContent(); await page.goto('/mcp/tools/list'); const tools2 = await page.locator('pre').textContent(); // Tools list should be consistent across requests expect(tools1).toBe(tools2); // Both should be valid JSON responses expect(() => JSON.parse(tools1 || '{}')).not.toThrow(); expect(() => JSON.parse(resources || '{}')).not.toThrow(); }); test('should handle concurrent MCP requests', async ({ page }) => { // Open multiple tabs for concurrent testing const promises = [ page.goto('/mcp/tools/list'), page.goto('/mcp/resources/list'), page.goto('/mcp/prompts/list'), ]; await Promise.all(promises); // All requests should complete successfully // The last navigation (prompts/list) should be visible const response = await page.locator('pre').textContent(); const mcpResponse = JSON.parse(response || '{}'); expect(mcpResponse).toHaveProperty('prompts'); }); test('should validate MCP request/response format', async ({ page }) => { await page.goto('/mcp/tools/list'); const response = await page.locator('pre').textContent(); const mcpResponse = JSON.parse(response || '{}'); // Should follow MCP JSON-RPC format expect(mcpResponse).toHaveProperty('jsonrpc'); expect(mcpResponse.jsonrpc).toBe('2.0'); expect(mcpResponse).toHaveProperty('id'); expect(mcpResponse).toHaveProperty('result'); }); test('should handle MCP logging and debugging', async ({ page }) => { // Test logging level changes await page.goto('/mcp/logging/setLevel'); await page.fill('#log-level', 'debug'); await page.click('#set-level'); // Should acknowledge log level change await expect(page.locator('.success-message')).toBeVisible(); // Subsequent requests should have more verbose logging await page.goto('/mcp/tools/list'); // Check for debug information (implementation specific) const hasDebugInfo = await page.locator('.debug-info').isVisible(); // Debug info might not be visible in UI, but logging should be affected }); test('should handle MCP completion requests', async ({ page }) => { await page.goto('/mcp/completion/complete'); // Fill in completion request await page.fill('#completion-ref', 'wordpress_post_'); await page.fill('#completion-argument', 'title'); await page.click('#get-completion'); // Should provide completions await expect(page.locator('.completion-results')).toBeVisible(); const results = await page.locator('.completion-results pre').textContent(); const completionResponse = JSON.parse(results || '{}'); expect(completionResponse).toHaveProperty('completion'); expect(completionResponse.completion).toHaveProperty('values'); }); test('should handle large MCP responses', async ({ page }) => { // Test with a request that returns large amounts of data await page.goto('/mcp/tools/call'); await page.fill('#tool-name', 'wordpress_get_posts'); await page.fill('#tool-arguments', JSON.stringify({ limit: 100 })); await page.click('#execute-tool'); // Should handle large response without timeout await expect(page.locator('.tool-result')).toBeVisible({ timeout: 10000 }); const result = await page.locator('.tool-result pre').textContent(); expect(result).toBeTruthy(); expect(result!.length).toBeGreaterThan(1000); // Should be substantial data }); test('should work with different WordPress site types', async ({ page }) => { // Test with hosted WordPress site await page.addInitScript(() => { (globalThis as any).localStorage.setItem('wp_site_type', 'hosted_wordpress'); }); await page.goto('/mcp/tools/list'); const hostedTools = await page.locator('pre').textContent(); // Test with self-hosted site await page.addInitScript(() => { (globalThis as any).localStorage.setItem('wp_site_type', 'self_hosted'); }); await page.goto('/mcp/tools/list'); const selfHostedTools = await page.locator('pre').textContent(); // Both should return valid tool lists, but may differ expect(() => JSON.parse(hostedTools || '{}')).not.toThrow(); expect(() => JSON.parse(selfHostedTools || '{}')).not.toThrow(); }); });

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/Automattic/mcp-wordpress-remote'

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