test_mcp_server / app.py
SrikanthNagelli's picture
initial commit
b0979b9
#!/usr/bin/env python3
"""Enhanced MCP Server using Gradio's built-in MCP functionality.
This server exposes 5 specialized tools via Gradio MCP integration.
"""
import gradio as gr
import json
import os
from typing import Any, Dict, List, Optional
import argparse
# Configuration
RIDB_API_KEY = "d3e5b760-226d-4e09-99db-1f9fc514775c"
# Set environment variable for tools that need it
os.environ['RIDB_API_KEY'] = RIDB_API_KEY
# Import our enhanced tools
from tools.sentiment_tool import SentimentTool
from tools.place_tool import PlaceSearchTool
from tools.restaurant_tool import RestaurantSearchTool
from tools.hiking_tool import HikingSearchTool
from tools.web_search_tool import WebSearchTool
# Import the formatting service
from services.formatting_service import ResponseFormatter
# Initialize tools
def initialize_tools() -> Dict[str, Any]:
"""Initialize all available tools."""
tools = {}
try:
tools['sentiment_analysis'] = SentimentTool()
print("βœ… Sentiment analysis tool initialized")
except Exception as e:
print(f"❌ Failed to initialize sentiment tool: {e}")
try:
tools['place_search'] = PlaceSearchTool()
print("βœ… Place search tool initialized")
except Exception as e:
print(f"❌ Failed to initialize place search tool: {e}")
try:
tools['restaurant_search'] = RestaurantSearchTool()
print("βœ… Restaurant search tool initialized")
except Exception as e:
print(f"❌ Failed to initialize restaurant search tool: {e}")
try:
tools['hiking_search'] = HikingSearchTool()
print("βœ… Hiking search tool initialized")
except Exception as e:
print(f"❌ Failed to initialize hiking search tool: {e}")
try:
tools['web_search'] = WebSearchTool()
print("βœ… Web search tool initialized")
except Exception as e:
print(f"❌ Failed to initialize web search tool: {e}")
return tools
# Tool wrapper functions for Gradio MCP
def sentiment_analysis(text: str) -> str:
"""Analyze the sentiment of the given text using TextBlob."""
tool = tools['sentiment_analysis']
raw_result = tool.forward(text)
# Handle error cases
if 'error' in raw_result:
return ResponseFormatter.format_error(raw_result['error'])
# Extract the required arguments from results
text_analyzed = raw_result.get('text', text)
polarity = raw_result.get('polarity', 0.0)
subjectivity = raw_result.get('subjectivity', 0.5)
assessment = raw_result.get('assessment', 'neutral')
# Format the result with correct arguments
return ResponseFormatter.format_sentiment_response(text_analyzed, polarity, subjectivity, assessment)
def place_search(query: str, max_distance: int = 20) -> dict:
"""Search for hotels and accommodations in a specified location."""
tool = tools['place_search']
results = tool.forward(location=query, max_distance=max_distance)
# Handle error cases
if 'error' in results:
return ResponseFormatter.format_error(results['error'])
# Extract location and places from results
location = results.get('location', query)
places = results.get('places', [])
# Format the response with correct arguments
return ResponseFormatter.format_place_response(location, places)
def restaurant_search(query: str, cuisine: str = None) -> dict:
"""Find restaurants and dining options in a specified location."""
tool = tools['restaurant_search']
results = tool.forward(location=query, cuisine=cuisine)
# Handle error cases
if 'error' in results:
return ResponseFormatter.format_error(results['error'])
# Extract the required arguments from results
location = results.get('location', query)
# The service returns distance as a string like "1.0 miles", extract the number
distance_str = results.get('distance', '1.0 miles')
try:
distance = float(distance_str.split()[0]) # Extract number from "1.0 miles"
except (ValueError, IndexError):
distance = 1.0 # Default
# The service returns 'top_restaurants', but formatter expects 'restaurants'
restaurants = results.get('top_restaurants', [])
# Format the response with correct arguments
return ResponseFormatter.format_restaurant_response(location, distance, restaurants)
def hiking_search(location: str, difficulty: str = None, max_distance: int = 50) -> dict:
"""Discover hiking trails and outdoor activities in a specified location."""
tool = tools['hiking_search']
results = tool.forward(location, difficulty, max_distance)
# Handle error cases
if 'error' in results:
return ResponseFormatter.format_error(results['error'])
# Extract the required arguments from results
location_name = results.get('location', location)
max_dist = max_distance # We already have this from the function parameter
difficulty_filter = results.get('difficulty_filter', difficulty or 'All')
trails = results.get('trails', [])
stats = results.get('stats', {})
# Format the response with correct arguments
return ResponseFormatter.format_hiking_response(location_name, max_dist, difficulty_filter, trails, stats)
def web_search(query: str, max_results: int = 5) -> dict:
"""Search the web for information with intelligent category matching."""
tool = tools['web_search']
raw_result = tool.forward(query, max_results)
# Format the result beautifully using the formatting service
if 'error' not in raw_result:
formatted_result = ResponseFormatter.format_web_search_results(raw_result)
return {
"formatted_output": formatted_result,
"raw_data": raw_result
}
else:
# Return error with formatting
formatted_result = ResponseFormatter.format_web_search_results(raw_result)
return {
"formatted_output": formatted_result,
"raw_data": raw_result
}
def create_gradio_mcp_server():
"""Create Gradio MCP server with individual tool interfaces."""
# Create individual interfaces for each tool
# These will be automatically exposed as MCP tools
sentiment_interface = gr.Interface(
fn=sentiment_analysis,
inputs=[gr.Textbox(placeholder="Enter text to analyze", label="text")],
outputs=[gr.Markdown(label="Sentiment Analysis Result")],
title="🎭 Sentiment Analysis",
description="Analyze the sentiment of the given text using TextBlob."
)
place_interface = gr.Interface(
fn=place_search,
inputs=[
gr.Textbox(placeholder="Enter location", label="query"),
gr.Slider(minimum=1, maximum=100, value=20, label="max_distance")
],
outputs=[gr.Markdown(label="result")],
title="🏨 Place Search",
description="Search for hotels and accommodations in a specified location."
)
restaurant_interface = gr.Interface(
fn=restaurant_search,
inputs=[
gr.Textbox(placeholder="Enter location", label="query"),
gr.Textbox(placeholder="Enter cuisine type (optional)", label="cuisine", value="")
],
outputs=[gr.Markdown(label="result")],
title="🍽️ Restaurant Search",
description="Find restaurants and dining options in a specified location."
)
hiking_interface = gr.Interface(
fn=hiking_search,
inputs=[
gr.Textbox(placeholder="Enter location", label="location"),
gr.Textbox(placeholder="Enter difficulty (optional)", label="difficulty", value=""),
gr.Slider(minimum=1, maximum=200, value=50, label="max_distance")
],
outputs=[gr.Markdown(label="result")],
title="πŸ₯Ύ Hiking Search",
description="Discover hiking trails and outdoor activities in a specified location."
)
web_interface = gr.Interface(
fn=web_search,
inputs=[
gr.Textbox(placeholder="Enter search query", label="query"),
gr.Slider(minimum=1, maximum=10, value=5, label="max_results")
],
outputs=[gr.JSON(label="Search Results")],
title="🌐 Web Search",
description="Search the web for information with intelligent category matching."
)
# Create a combined tabbed interface
demo = gr.TabbedInterface(
[sentiment_interface, place_interface, restaurant_interface, hiking_interface, web_interface],
["🎭 Sentiment Analysis", "🏨 Place Search", "🍽️ Restaurant Search", "πŸ₯Ύ Hiking Search", "🌐 Web Search"],
title="πŸš€ Enhanced MCP Server with 5 Specialized Tools"
)
return demo
def main():
"""Main entry point for the Enhanced MCP Server."""
parser = argparse.ArgumentParser(description="Enhanced MCP Server with Gradio Integration")
parser.add_argument(
"--port",
type=int,
default=7860,
help="Port to run the server (default: 7861)"
)
parser.add_argument(
"--host",
default="0.0.0.0",
help="Host to bind the server (default: 0.0.0.0)"
)
args = parser.parse_args()
print("πŸš€ Starting Enhanced MCP Server with Gradio Integration")
print("✨ Using Gradio's built-in MCP functionality")
print("")
print("πŸ”§ Initializing Tools:")
# Initialize tools globally
global tools
tools = initialize_tools()
print(f"βœ… {len(tools)} tool instances initialized successfully")
print("")
print("πŸ”§ Server Features:")
for tool_name, tool_instance in tools.items():
print(f" β€’ {tool_instance.description}")
print("")
print(f"πŸ“‘ Server URL: http://{args.host}:{args.port}")
print(f"πŸ”— MCP Endpoint: http://{args.host}:{args.port}/gradio_api/mcp/sse")
print("═" * 60)
# Create and launch Gradio MCP server
demo = create_gradio_mcp_server()
print("🌟 Server ready! Tools available via MCP protocol and web interface!")
# Launch with MCP server enabled
demo.launch(
server_name=args.host,
server_port=args.port,
share=False,
show_error=True,
mcp_server=True # Enable Gradio's MCP functionality
)
if __name__ == "__main__":
main()