Skip to main content
Glama
test_smithery_fix.py14.6 kB
#!/usr/bin/env python3 """ Test script to verify the Smithery deployment fix Simulates Smithery's MCP scanning process with proper JSON-RPC protocol """ import os import sys import json import time import requests import subprocess from typing import Dict, Any, Optional def test_mcp_json_rpc_endpoints(base_url: str = "http://localhost:8080") -> Dict[str, Any]: """Test MCP JSON-RPC endpoints that Smithery uses for scanning""" results = { "base_url": base_url, "tests": {}, "overall_success": True, "smithery_compatible": True } mcp_endpoint = f"{base_url}/mcp" print(f"🔍 Testing MCP JSON-RPC Protocol for Smithery compatibility...") print(f"🌐 MCP Endpoint: {mcp_endpoint}") print() # Standard MCP headers required by the protocol headers = { "Content-Type": "application/json", "Accept": "application/json, text/event-stream", "MCP-Protocol-Version": "2025-06-18" } # Critical MCP JSON-RPC requests that Smithery uses mcp_requests = { "initialize": { "description": "MCP initialization - CRITICAL for Smithery", "payload": { "jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": { "name": "smithery-test-client", "version": "1.0.0" } } }, "critical": True }, "tools_list": { "description": "Tool discovery - CRITICAL for Smithery", "payload": { "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }, "critical": True }, "resources_list": { "description": "Resource discovery - Optional", "payload": { "jsonrpc": "2.0", "id": 3, "method": "resources/list", "params": {} }, "critical": False }, "prompts_list": { "description": "Prompt discovery - Optional", "payload": { "jsonrpc": "2.0", "id": 4, "method": "prompts/list", "params": {} }, "critical": False } } for test_name, test_info in mcp_requests.items(): try: print(f"📡 Testing {test_name} - {test_info['description']}") # Make JSON-RPC request without authentication (as Smithery would during discovery) response = requests.post( mcp_endpoint, headers=headers, json=test_info["payload"], timeout=10 ) test_result = { "endpoint": mcp_endpoint, "description": test_info["description"], "request": test_info["payload"], "status_code": response.status_code, "success": False, "response_data": None, "error": None, "smithery_critical": test_info["critical"] } # Check if response is successful (200-299 range) if 200 <= response.status_code < 300: test_result["success"] = True try: response_data = response.json() test_result["response_data"] = response_data # Validate JSON-RPC response if "jsonrpc" in response_data and "id" in response_data: if "result" in response_data: print(f" ✅ SUCCESS (HTTP {response.status_code}) - Valid JSON-RPC response") elif "error" in response_data: print(f" ⚠️ JSON-RPC ERROR: {response_data['error']}") if test_info["critical"]: results["smithery_compatible"] = False else: print(f" ⚠️ Invalid JSON-RPC response format") else: print(f" ⚠️ Non-JSON-RPC response: {str(response_data)[:100]}") except: test_result["response_data"] = response.text[:200] + "..." if len(response.text) > 200 else response.text print(f" ✅ SUCCESS (HTTP {response.status_code}) - Non-JSON response") elif response.status_code == 401: print(f" ❌ AUTHENTICATION REQUIRED (HTTP 401) - Discovery should be open!") test_result["error"] = f"HTTP 401 - Authentication required for discovery" results["smithery_compatible"] = False if test_info["critical"]: results["overall_success"] = False elif response.status_code == 403: print(f" ❌ FORBIDDEN (HTTP 403) - Discovery should be accessible!") test_result["error"] = f"HTTP 403 - Forbidden" results["smithery_compatible"] = False if test_info["critical"]: results["overall_success"] = False elif response.status_code == 404: print(f" ❌ NOT FOUND (HTTP 404) - MCP endpoint not available") test_result["error"] = f"HTTP 404 - MCP endpoint not found" results["smithery_compatible"] = False if test_info["critical"]: results["overall_success"] = False elif response.status_code == 405: print(f" ❌ METHOD NOT ALLOWED (HTTP 405) - POST should be supported") test_result["error"] = f"HTTP 405 - Method not allowed" results["smithery_compatible"] = False if test_info["critical"]: results["overall_success"] = False elif response.status_code == 406: print(f" ❌ NOT ACCEPTABLE (HTTP 406) - Headers issue") test_result["error"] = f"HTTP 406 - Not acceptable" results["smithery_compatible"] = False if test_info["critical"]: results["overall_success"] = False else: print(f" ❌ FAILED (HTTP {response.status_code})") test_result["error"] = f"HTTP {response.status_code}" if test_info["critical"]: results["smithery_compatible"] = False results["overall_success"] = False results["tests"][test_name] = test_result except requests.exceptions.RequestException as e: print(f" ❌ CONNECTION ERROR: {str(e)}") results["tests"][test_name] = { "endpoint": mcp_endpoint, "description": test_info["description"], "status_code": None, "success": False, "error": str(e), "smithery_critical": test_info["critical"] } results["overall_success"] = False if test_info["critical"]: results["smithery_compatible"] = False print() return results def test_http_endpoints(base_url: str = "http://localhost:8080") -> Dict[str, Any]: """Test basic HTTP endpoints for server health""" results = { "base_url": base_url, "tests": {}, "overall_success": True } print(f"🔍 Testing Basic HTTP Endpoints...") print(f"🌐 Base URL: {base_url}") print() # Basic HTTP endpoints endpoints = { "/health": "Server health check" } for endpoint, description in endpoints.items(): test_name = endpoint.replace("/", "_").strip("_") or "root" url = f"{base_url}{endpoint}" try: print(f"📡 Testing {endpoint} - {description}") response = requests.get(url, timeout=10) test_result = { "url": url, "description": description, "status_code": response.status_code, "success": False, "response_data": None, "error": None } if 200 <= response.status_code < 300: test_result["success"] = True try: test_result["response_data"] = response.json() except: test_result["response_data"] = response.text[:200] + "..." if len(response.text) > 200 else response.text print(f" ✅ SUCCESS (HTTP {response.status_code})") else: print(f" ❌ FAILED (HTTP {response.status_code})") test_result["error"] = f"HTTP {response.status_code}" results["overall_success"] = False results["tests"][test_name] = test_result except requests.exceptions.RequestException as e: print(f" ❌ CONNECTION ERROR: {str(e)}") results["tests"][test_name] = { "url": url, "description": description, "status_code": None, "success": False, "error": str(e) } results["overall_success"] = False print() return results def test_production_simulation(): """Test with simulated production environment variables (as Smithery would set them)""" print("🧪 TESTING PRODUCTION SIMULATION") print("=" * 50) # Backup original environment original_env = { "DESCOPE_PROJECT_ID": os.environ.get("DESCOPE_PROJECT_ID"), "DESCOPE_MANAGEMENT_KEY": os.environ.get("DESCOPE_MANAGEMENT_KEY") } try: # Set simulated Smithery production credentials os.environ["DESCOPE_PROJECT_ID"] = "P2l8xGh4KQf3wXr9mN5yZ1vB" # Fake production-like project ID os.environ["DESCOPE_MANAGEMENT_KEY"] = "K1:fake_management_key_for_testing_purposes_only" # Fake management key print(f"🔧 Set simulated production credentials:") print(f" DESCOPE_PROJECT_ID: P2l8xGh4KQf3wXr9mN5yZ1vB") print(f" DESCOPE_MANAGEMENT_KEY: K1:fake_management_key...") print() # Test server startup with production credentials print("🚀 Testing server startup with production credentials...") # Start server as subprocess server_process = subprocess.Popen([ sys.executable, "mcp_server.py" ], cwd=os.getcwd(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) # Wait for server to start time.sleep(3) if server_process.poll() is None: print("✅ Server started successfully with production credentials") # Test basic endpoints first http_results = test_http_endpoints() # Test MCP protocol endpoints mcp_results = test_mcp_json_rpc_endpoints() # Stop server server_process.terminate() server_process.wait(timeout=5) return { "server_startup": True, "http_tests": http_results, "mcp_tests": mcp_results, "smithery_compatible": mcp_results.get("smithery_compatible", False) } else: print("❌ Server failed to start with production credentials") output, _ = server_process.communicate() print(f"Server output: {output}") return { "server_startup": False, "error": "Server startup failed", "output": output, "smithery_compatible": False } finally: # Restore original environment for key, value in original_env.items(): if value is None: os.environ.pop(key, None) else: os.environ[key] = value def main(): """Main test function""" print("🔥 SMITHERY DEPLOYMENT FIX VERIFICATION") print("=" * 60) print() # Test 1: Current demo mode print("📋 TEST 1: Demo Mode (Current Configuration)") print("-" * 40) try: http_results = test_http_endpoints() mcp_results = test_mcp_json_rpc_endpoints() demo_compatible = mcp_results.get("smithery_compatible", False) except Exception as e: print(f"❌ Demo mode test failed: {e}") demo_compatible = False print("\n📋 TEST 2: Production Mode Simulation") print("-" * 40) prod_results = test_production_simulation() prod_compatible = prod_results.get("smithery_compatible", False) if isinstance(prod_results, dict) else False # Summary print("\n📊 FINAL RESULTS") print("=" * 30) print(f"Demo Mode Smithery Compatible: {'✅ YES' if demo_compatible else '❌ NO'}") print(f"Production Mode Smithery Compatible: {'✅ YES' if prod_compatible else '❌ NO'}") overall_fix_success = demo_compatible and prod_compatible print(f"\n🎯 OVERALL FIX STATUS: {'✅ SUCCESS' if overall_fix_success else '❌ NEEDS MORE WORK'}") if overall_fix_success: print("\n🎉 Smithery deployment should now work successfully!") print(" • MCP JSON-RPC discovery endpoints are accessible without authentication") print(" • Server starts reliably with any credential configuration") print(" • Graceful degradation prevents startup failures") print(" • Proper MCP protocol support for tool discovery") else: print("\n⚠️ Issues still need to be resolved:") if not demo_compatible: print(" • Demo mode MCP discovery endpoints are not working") if not prod_compatible: print(" • Production mode has issues with credential handling") return overall_fix_success if __name__ == "__main__": success = main() sys.exit(0 if success else 1)

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/yoriichi-07/Multi_Orchestrator_MCP'

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