basic_demo.pyā¢7.38 kB
"""
Basic MCP OAuth Demo
This demo shows the complete OAuth authentication flow between
an MCP client and server.
"""
import asyncio
import logging
import sys
import subprocess
import time
from pathlib import Path
# Add parent directory to path to import modules
sys.path.insert(0, str(Path(__file__).parent.parent))
from client.client import MCPOAuthClient
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
async def wait_for_server(url: str, timeout: int = 30) -> bool:
"""Wait for the MCP server to be ready."""
import httpx
start_time = time.time()
while time.time() - start_time < timeout:
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"{url}/health")
if response.status_code == 200:
return True
except:
pass
await asyncio.sleep(1)
return False
async def demo_oauth_flow():
"""Demonstrate the complete OAuth flow."""
print("š MCP OAuth Basic Demo")
print("=" * 50)
server_url = "http://localhost:8000"
# Wait for server to be ready
print("ā³ Waiting for MCP server to be ready...")
if not await wait_for_server(server_url):
print("ā MCP server is not running!")
print("š” Please start the server first with: uv run python server/app.py")
return False
print("ā
MCP server is ready!")
# Create client
print("\nš§ Creating MCP OAuth client...")
client = MCPOAuthClient(server_url)
try:
# Step 1: Authentication
print("\n" + "="*30)
print("STEP 1: OAuth Authentication")
print("="*30)
print("š Starting OAuth authentication flow...")
print("š± This will open your browser for authentication")
if not await client.authenticate():
print("ā Authentication failed!")
return False
print("ā
Authentication successful!")
# Step 2: Connection
print("\n" + "="*30)
print("STEP 2: MCP Server Connection")
print("="*30)
if not await client.connect():
print("ā Connection failed!")
return False
print("ā
Connected to MCP server!")
# Step 3: List Tools
print("\n" + "="*30)
print("STEP 3: List Available Tools")
print("="*30)
tools = await client.list_tools()
print(f"š Found {len(tools.get('tools', []))} available tools:")
for i, tool in enumerate(tools.get('tools', []), 1):
print(f" {i}. {tool['name']}")
print(f" Description: {tool['description']}")
# Step 4: Call Tools
print("\n" + "="*30)
print("STEP 4: Call MCP Tools")
print("="*30)
# Call get_user_info
print("š§ Calling get_user_info tool...")
result = await client.call_tool("get_user_info", {})
print(f"ā
Result: {result['result']}")
# Call get_weather
print("\nš§ Calling get_weather tool...")
result = await client.call_tool("get_weather", {"city": "London"})
print(f"ā
Weather result: {result['result']}")
# Call protected_action
print("\nš§ Calling protected_action tool...")
result = await client.call_tool("protected_action", {"action": "demo_action"})
print(f"ā
Action result: {result['result']}")
# Step 5: Cleanup
print("\n" + "="*30)
print("STEP 5: Cleanup")
print("="*30)
await client.disconnect()
print("ā
Disconnected from server")
print("\nš Demo completed successfully!")
print("š” The OAuth flow worked end-to-end!")
return True
except Exception as e:
print(f"\nā Demo failed: {e}")
await client.disconnect()
return False
async def interactive_demo():
"""Run an interactive demo where user can try different tools."""
print("š® Interactive MCP OAuth Demo")
print("=" * 50)
server_url = input("Enter MCP server URL (default: http://localhost:8000): ").strip()
if not server_url:
server_url = "http://localhost:8000"
# Check if server is running
if not await wait_for_server(server_url):
print("ā MCP server is not running!")
print("š” Please start the server first with: uv run python server/app.py")
return False
client = MCPOAuthClient(server_url)
try:
# Authenticate
print("\nš Authenticating...")
if not await client.authenticate():
print("ā Authentication failed!")
return False
# Connect
if not await client.connect():
print("ā Connection failed!")
return False
print("ā
Connected! You can now interact with the MCP server.")
# Interactive loop
while True:
print("\n" + "="*40)
print("What would you like to do?")
print("1. List available tools")
print("2. Get weather for a city")
print("3. Get user information")
print("4. Perform a protected action")
print("5. Exit")
choice = input("\nEnter choice (1-5): ").strip()
if choice == "1":
tools = await client.list_tools()
print("\nš Available tools:")
for tool in tools.get('tools', []):
print(f" ⢠{tool['name']} - {tool['description']}")
elif choice == "2":
city = input("Enter city name: ").strip()
if city:
result = await client.call_tool("get_weather", {"city": city})
print(f"š¤ļø {result['result']}")
elif choice == "3":
result = await client.call_tool("get_user_info", {})
print(f"š¤ {result['result']}")
elif choice == "4":
action = input("Enter action to perform: ").strip()
if action:
result = await client.call_tool("protected_action", {"action": action})
print(f"š§ {result['result']}")
elif choice == "5":
break
else:
print("ā Invalid choice. Please enter 1-5.")
await client.disconnect()
print("\nš Thanks for trying the demo!")
return True
except KeyboardInterrupt:
print("\n\nš Demo interrupted by user")
await client.disconnect()
return True
except Exception as e:
print(f"\nā Demo error: {e}")
await client.disconnect()
return False
def main():
"""Main demo entry point."""
print("Choose demo mode:")
print("1. Automated demo (shows complete flow)")
print("2. Interactive demo (you control the actions)")
choice = input("\nEnter choice (1-2): ").strip()
if choice == "1":
success = asyncio.run(demo_oauth_flow())
elif choice == "2":
success = asyncio.run(interactive_demo())
else:
print("ā Invalid choice")
return 1
return 0 if success else 1
if __name__ == "__main__":
exit_code = main()
sys.exit(exit_code)