|
|
|
|
|
"""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 |
|
|
|
|
|
|
|
|
RIDB_API_KEY = "d3e5b760-226d-4e09-99db-1f9fc514775c" |
|
|
|
|
|
|
|
|
os.environ['RIDB_API_KEY'] = RIDB_API_KEY |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
from services.formatting_service import ResponseFormatter |
|
|
|
|
|
|
|
|
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 |
|
|
|
|
|
|
|
|
def sentiment_analysis(text: str) -> str: |
|
|
"""Analyze the sentiment of the given text using TextBlob.""" |
|
|
tool = tools['sentiment_analysis'] |
|
|
raw_result = tool.forward(text) |
|
|
|
|
|
|
|
|
if 'error' in raw_result: |
|
|
return ResponseFormatter.format_error(raw_result['error']) |
|
|
|
|
|
|
|
|
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') |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
if 'error' in results: |
|
|
return ResponseFormatter.format_error(results['error']) |
|
|
|
|
|
|
|
|
location = results.get('location', query) |
|
|
places = results.get('places', []) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
if 'error' in results: |
|
|
return ResponseFormatter.format_error(results['error']) |
|
|
|
|
|
|
|
|
location = results.get('location', query) |
|
|
|
|
|
distance_str = results.get('distance', '1.0 miles') |
|
|
try: |
|
|
distance = float(distance_str.split()[0]) |
|
|
except (ValueError, IndexError): |
|
|
distance = 1.0 |
|
|
|
|
|
|
|
|
restaurants = results.get('top_restaurants', []) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
if 'error' in results: |
|
|
return ResponseFormatter.format_error(results['error']) |
|
|
|
|
|
|
|
|
location_name = results.get('location', location) |
|
|
max_dist = max_distance |
|
|
difficulty_filter = results.get('difficulty_filter', difficulty or 'All') |
|
|
trails = results.get('trails', []) |
|
|
stats = results.get('stats', {}) |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
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: |
|
|
|
|
|
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.""" |
|
|
|
|
|
|
|
|
|
|
|
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." |
|
|
) |
|
|
|
|
|
|
|
|
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:") |
|
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
|
demo = create_gradio_mcp_server() |
|
|
|
|
|
print("π Server ready! Tools available via MCP protocol and web interface!") |
|
|
|
|
|
|
|
|
demo.launch( |
|
|
server_name=args.host, |
|
|
server_port=args.port, |
|
|
share=False, |
|
|
show_error=True, |
|
|
mcp_server=True |
|
|
) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
main() |