mirror of
https://github.com/sstent/AICycling_mcp.git
synced 2026-01-25 16:42:24 +00:00
204 lines
6.6 KiB
Python
Executable File
204 lines
6.6 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Debug script to identify MCP tools hanging issue
|
|
"""
|
|
import asyncio
|
|
import yaml
|
|
import logging
|
|
import signal
|
|
from main import GarthMCPConnector, Config
|
|
|
|
# Set up more detailed logging
|
|
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class TimeoutError(Exception):
|
|
pass
|
|
|
|
def timeout_handler(signum, frame):
|
|
raise TimeoutError("Operation timed out")
|
|
|
|
async def debug_mcp_connection():
|
|
"""Debug the MCP connection step by step"""
|
|
# Load config
|
|
with open("config.yaml") as f:
|
|
config_data = yaml.safe_load(f)
|
|
|
|
config = Config(**config_data)
|
|
garmin = GarthMCPConnector(config.garth_token, config.garth_mcp_server_path)
|
|
|
|
print("=== MCP CONNECTION DEBUG ===")
|
|
|
|
# Step 1: Test connection
|
|
print("\n1. Testing MCP connection...")
|
|
try:
|
|
success = await garmin.connect()
|
|
if success:
|
|
print("✓ MCP connection successful")
|
|
else:
|
|
print("✗ MCP connection failed")
|
|
return
|
|
except Exception as e:
|
|
print(f"✗ MCP connection error: {e}")
|
|
return
|
|
|
|
# Step 2: Test session availability
|
|
print("\n2. Testing session availability...")
|
|
if garmin._session:
|
|
print("✓ Session is available")
|
|
else:
|
|
print("✗ No session available")
|
|
return
|
|
|
|
# Step 3: Test tools listing with timeout
|
|
print("\n3. Testing tools listing (with 10s timeout)...")
|
|
try:
|
|
# Set up timeout
|
|
signal.signal(signal.SIGALRM, timeout_handler)
|
|
signal.alarm(10) # 10 second timeout
|
|
|
|
tools_result = await garmin._session.list_tools()
|
|
signal.alarm(0) # Cancel timeout
|
|
|
|
if tools_result:
|
|
print(f"✓ Tools result received: {type(tools_result)}")
|
|
if hasattr(tools_result, 'tools'):
|
|
tools = tools_result.tools
|
|
print(f"✓ Found {len(tools)} tools")
|
|
|
|
# Show first few tools
|
|
for i, tool in enumerate(tools[:3]):
|
|
print(f" Tool {i+1}: {tool.name} - {getattr(tool, 'description', 'No desc')}")
|
|
|
|
if len(tools) > 3:
|
|
print(f" ... and {len(tools) - 3} more tools")
|
|
else:
|
|
print(f"✗ tools_result has no 'tools' attribute: {dir(tools_result)}")
|
|
else:
|
|
print("✗ No tools result received")
|
|
|
|
except TimeoutError:
|
|
print("✗ Tools listing timed out after 10 seconds")
|
|
print("This suggests the MCP server is hanging on list_tools()")
|
|
except Exception as e:
|
|
print(f"✗ Tools listing error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
finally:
|
|
signal.alarm(0) # Make sure to cancel any pending alarm
|
|
|
|
# Step 4: Test our wrapper method
|
|
print("\n4. Testing our get_available_tools_info() method...")
|
|
try:
|
|
# Clear cache first
|
|
garmin.cached_tools = []
|
|
|
|
signal.signal(signal.SIGALRM, timeout_handler)
|
|
signal.alarm(15) # 15 second timeout
|
|
|
|
tools = await garmin.get_available_tools_info()
|
|
signal.alarm(0)
|
|
|
|
print(f"✓ get_available_tools_info() returned {len(tools)} tools")
|
|
for tool in tools[:3]:
|
|
print(f" - {tool['name']}: {tool['description']}")
|
|
|
|
except TimeoutError:
|
|
print("✗ get_available_tools_info() timed out")
|
|
except Exception as e:
|
|
print(f"✗ get_available_tools_info() error: {e}")
|
|
finally:
|
|
signal.alarm(0)
|
|
|
|
# Cleanup
|
|
print("\n5. Cleaning up...")
|
|
await garmin.disconnect()
|
|
print("✓ Cleanup complete")
|
|
|
|
async def test_alternative_approach():
|
|
"""Test an alternative approach to getting tools info"""
|
|
print("\n=== TESTING ALTERNATIVE APPROACH ===")
|
|
|
|
# Load config
|
|
with open("config.yaml") as f:
|
|
config_data = yaml.safe_load(f)
|
|
|
|
config = Config(**config_data)
|
|
|
|
# Create a simpler MCP connector for testing
|
|
from mcp import ClientSession, StdioServerParameters
|
|
from mcp.client.stdio import stdio_client
|
|
import os
|
|
import shutil
|
|
|
|
try:
|
|
# Set up environment
|
|
env = os.environ.copy()
|
|
env['GARTH_TOKEN'] = config.garth_token
|
|
|
|
# Find server command
|
|
server_command = shutil.which("garth-mcp-server")
|
|
if not server_command:
|
|
print("✗ garth-mcp-server not found")
|
|
return
|
|
|
|
print(f"✓ Found server at: {server_command}")
|
|
|
|
# Create server parameters
|
|
server_params = StdioServerParameters(
|
|
command="/bin/bash",
|
|
args=["-c", f"exec {server_command} \"$@\" 1>&2"],
|
|
env=env,
|
|
)
|
|
|
|
print("Starting direct MCP test...")
|
|
async with stdio_client(server_params) as streams:
|
|
if len(streams) == 3:
|
|
read_stream, write_stream, stderr_stream = streams
|
|
else:
|
|
read_stream, write_stream = streams
|
|
|
|
session = ClientSession(read_stream, write_stream)
|
|
await session.initialize()
|
|
print("✓ Direct session initialized")
|
|
|
|
# Try to list tools with timeout
|
|
try:
|
|
signal.signal(signal.SIGALRM, timeout_handler)
|
|
signal.alarm(10)
|
|
|
|
print("Calling list_tools()...")
|
|
tools_result = await session.list_tools()
|
|
signal.alarm(0)
|
|
|
|
print(f"✓ Direct list_tools() successful: {len(tools_result.tools) if tools_result and hasattr(tools_result, 'tools') else 0} tools")
|
|
|
|
if tools_result and hasattr(tools_result, 'tools'):
|
|
for tool in tools_result.tools[:3]:
|
|
print(f" - {tool.name}")
|
|
|
|
except TimeoutError:
|
|
print("✗ Direct list_tools() timed out")
|
|
except Exception as e:
|
|
print(f"✗ Direct list_tools() error: {e}")
|
|
finally:
|
|
signal.alarm(0)
|
|
|
|
except Exception as e:
|
|
print(f"✗ Alternative approach failed: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
if __name__ == "__main__":
|
|
async def main():
|
|
await debug_mcp_connection()
|
|
await test_alternative_approach()
|
|
|
|
try:
|
|
asyncio.run(main())
|
|
except KeyboardInterrupt:
|
|
print("\n\n✗ Interrupted by user")
|
|
except Exception as e:
|
|
print(f"\n\n✗ Debug script failed: {e}")
|
|
import traceback
|
|
traceback.print_exc() |