UNPKG

mcp-server-tester-sse-http-stdio

Version:

MCP Server Tester with SSE support - Test MCP servers using HTTP, SSE, and STDIO transports

143 lines (142 loc) 4.72 kB
/** * Centralized MCP capability detection * Determines which optional MCP capabilities a server actually supports */ /** * All possible MCP capabilities for reference */ export const ALL_MCP_CAPABILITIES = [ 'tools', 'resources', 'prompts', 'logging', 'sampling', 'roots', ]; /** * Centralized capability detection for MCP servers */ export class CapabilityDetector { /** * Detect which MCP capabilities the server actually supports * First tries to read from initialization response, then falls back to probing */ static async detectCapabilities(client) { try { // First try to get capabilities from the initialization response const capabilities = await this.getCapabilitiesFromInit(client); if (capabilities.size > 0) { return capabilities; } // Fallback: probe each capability by testing if methods work return await this.probeCapabilities(client); } catch (error) { // If all else fails, return empty set console.warn('Failed to detect server capabilities:', error); return new Set(); } } /** * Get capabilities from the server's initialization response */ static async getCapabilitiesFromInit(client) { try { const clientWithInfo = client; const serverInfo = clientWithInfo.getServerInfo ? await clientWithInfo.getServerInfo() : null; if (serverInfo?.capabilities) { const detectedCapabilities = new Set(); // Check each known capability for (const capability of ALL_MCP_CAPABILITIES) { if (serverInfo.capabilities[capability]) { detectedCapabilities.add(capability); } } return detectedCapabilities; } } catch { // Expected if getServerInfo is not available - fall through to probing } return new Set(); } /** * Probe capabilities by testing if key methods work * This is a fallback when we can't get capabilities from initialization */ static async probeCapabilities(client) { const capabilities = new Set(); // Test each capability by calling its primary method const probeTests = [ { capability: 'tools', test: () => client.sdk.listTools(), }, { capability: 'resources', test: () => client.sdk.listResources(), }, { capability: 'prompts', test: () => client.sdk.listPrompts(), }, // Note: 'logging', 'sampling', and 'roots' are harder to probe // as they don't have simple list methods ]; // Test each capability in parallel for efficiency const results = await Promise.allSettled(probeTests.map(async ({ capability, test }) => { try { await test(); return capability; } catch { // Expected if capability is not supported return null; } })); // Collect successful probes results.forEach(result => { if (result.status === 'fulfilled' && result.value) { capabilities.add(result.value); } }); return capabilities; } /** * Get the list of capabilities that are not supported by the server */ static getUnsupportedCapabilities(supportedCapabilities) { return ALL_MCP_CAPABILITIES.filter(cap => !supportedCapabilities.has(cap)); } /** * Check if a server supports a specific capability */ static hasCapability(capabilities, capability) { return capabilities.has(capability); } /** * Format capabilities for display */ static formatCapabilities(capabilities) { if (capabilities.size === 0) { return 'None detected'; } return Array.from(capabilities) .sort() .map(cap => `${cap} ✅`) .join(' | '); } /** * Format unsupported capabilities for display */ static formatUnsupportedCapabilities(capabilities) { const unsupported = this.getUnsupportedCapabilities(capabilities); if (unsupported.length === 0) { return 'All capabilities supported'; } return unsupported .sort() .map(cap => `${cap} ⏭️`) .join(' | '); } }