mcp-hf / app.py
elanuk's picture
Create app.py
524df2c verified
raw
history blame
9.9 kB
import gradio as gr
import requests
import json
from datetime import datetime
import os
# Configuration
MCP_SERVER_URL = os.getenv("MCP_SERVER_URL", "https://elanuk-mcp-hf.hf.space/")
# Bihar districts list
BIHAR_DISTRICTS = [
"Patna", "Gaya", "Bhagalpur", "Muzaffarpur", "Darbhanga", "Siwan",
"Begusarai", "Katihar", "Nalanda", "Rohtas", "Saran", "Samastipur",
"Madhubani", "Purnia", "Araria", "Kishanganj", "Supaul", "Madhepura",
"Saharsa", "Khagaria", "Munger", "Lakhisarai", "Sheikhpura", "Nawada",
"Jamui", "Jehanabad", "Aurangabad", "Arwal", "Kaimur", "Buxar",
"Bhojpur", "Saran", "Siwan", "Gopalganj", "East Champaran", "West Champaran",
"Sitamarhi", "Sheohar", "Vaishali"
]
def format_workflow_output(raw_output):
"""Format the workflow output for better display"""
if not raw_output:
return "❌ No output received"
# Split into lines and format
lines = raw_output.split('\n')
formatted_lines = []
for line in lines:
line = line.strip()
if not line:
formatted_lines.append("")
continue
# Format headers
if line.startswith('🌾') and 'Workflow' in line:
formatted_lines.append(f"## {line}")
elif line.startswith('=') or line.startswith('-'):
continue # Skip separator lines
elif line.startswith('🌀️') or line.startswith('βœ… Workflow'):
formatted_lines.append(f"### {line}")
elif line.startswith('πŸ“±') or line.startswith('πŸ“ž') or line.startswith('πŸŽ™οΈ') or line.startswith('πŸ€–'):
formatted_lines.append(f"#### {line}")
elif line.startswith('βœ…') or line.startswith('❌'):
formatted_lines.append(f"- {line}")
elif line.startswith(' '):
formatted_lines.append(f" {line.strip()}")
else:
formatted_lines.append(line)
return '\n'.join(formatted_lines)
def format_alert_summary(raw_data):
"""Create a formatted summary of the alert data"""
if not raw_data or 'alert_data' not in raw_data:
return "No alert data available"
alert_data = raw_data['alert_data']
summary = f"""
## 🚨 Alert Summary
**πŸ“ Location:** {alert_data['location']['village']}, {alert_data['location']['district']}, {alert_data['location']['state']}
**🌾 Crop Information:**
- **Crop:** {alert_data['crop']['name'].title()}
- **Growth Stage:** {alert_data['crop']['stage']}
- **Season:** {alert_data['crop']['season'].title()}
**🌀️ Weather Conditions:**
- **Temperature:** {alert_data['weather']['temperature']}
- **Expected Rainfall:** {alert_data['weather']['expected_rainfall']}
- **Wind Speed:** {alert_data['weather']['wind_speed']}
- **Rain Probability:** {alert_data['weather']['rain_probability']}%
**⚠️ Alert Details:**
- **Type:** {alert_data['alert']['type'].replace('_', ' ').title()}
- **Urgency:** {alert_data['alert']['urgency'].upper()}
- **AI Enhanced:** {'βœ… Yes' if alert_data['alert']['ai_generated'] else '❌ No'}
**πŸ“¨ Alert Message:**
{alert_data['alert']['message']}
**🎯 Action Items:**
{chr(10).join([f"- {item.replace('_', ' ').title()}" for item in alert_data['alert']['action_items']])}
"""
return summary
def test_mcp_workflow(district):
"""Test the MCP workflow for a given district"""
if not district:
return "❌ Please select a district", "", ""
try:
# Make request to MCP server
payload = {
"state": "bihar",
"district": district.lower()
}
response = requests.post(
f"{MCP_SERVER_URL}/api/run-workflow",
json=payload,
timeout=30
)
if response.status_code == 200:
result = response.json()
# Format outputs
workflow_output = format_workflow_output(result.get('message', ''))
alert_summary = format_alert_summary(result.get('raw_data', {}))
# Create CSV download content
csv_content = result.get('csv', '')
return workflow_output, alert_summary, csv_content
else:
error_msg = f"❌ Server Error ({response.status_code}): {response.text}"
return error_msg, "", ""
except requests.exceptions.Timeout:
return "⏰ Request timed out. The server might be processing...", "", ""
except requests.exceptions.ConnectionError:
return f"πŸ”Œ Connection Error: Cannot reach MCP server at {MCP_SERVER_URL}", "", ""
except Exception as e:
return f"❌ Error: {str(e)}", "", ""
def check_server_health():
"""Check if the MCP server is running"""
try:
response = requests.get(f"{MCP_SERVER_URL}/api/health", timeout=10)
if response.status_code == 200:
data = response.json()
return f"βœ… Server Online | OpenAI: {'βœ…' if data.get('openai_available') else '❌'} | Time: {data.get('timestamp', 'N/A')}"
else:
return f"⚠️ Server responded with status {response.status_code}"
except:
return f"❌ Server Offline or Unreachable ({MCP_SERVER_URL})"
# Create Gradio interface
with gr.Blocks(
title="BIHAR AgMCP - Agricultural Weather Alerts",
theme=gr.themes.Soft(),
css="""
.gradio-container {
max-width: 1200px;
margin: auto;
}
.status-box {
padding: 10px;
border-radius: 5px;
margin: 10px 0;
}
"""
) as demo:
gr.Markdown("""
# 🌾 BIHAR AgMCP - Agricultural Weather Alert System
**AI-Powered Weather Alerts for Bihar Farmers**
This interface tests the MCP (Model Context Protocol) server that generates personalized weather alerts for agricultural activities in Bihar districts.
## πŸ“‹ How to Use:
1. **Select District**: Choose a Bihar district from the dropdown
2. **Run Workflow**: Click the button to generate weather alerts
3. **View Results**: See formatted workflow output and alert summary
4. **Download Data**: Get CSV export of the alert data
The system will:
- Select a random village in the district
- Choose appropriate crops based on season and region
- Generate weather-based agricultural alerts
- Create messages for multiple communication channels (SMS, WhatsApp, etc.)
""")
# Server status
with gr.Row():
server_status = gr.Textbox(
label="πŸ”§ Server Status",
value=check_server_health(),
interactive=False,
container=True
)
refresh_btn = gr.Button("πŸ”„ Refresh Status", size="sm")
refresh_btn.click(check_server_health, outputs=server_status)
# Main interface
with gr.Row():
with gr.Column(scale=1):
district_input = gr.Dropdown(
choices=BIHAR_DISTRICTS,
label="πŸ“ Select Bihar District",
placeholder="Choose a district...",
value="Patna"
)
run_btn = gr.Button(
"πŸš€ Generate Weather Alert",
variant="primary",
size="lg"
)
gr.Markdown("""
### πŸ’‘ What happens next?
- Weather data collection
- Crop stage estimation
- AI-powered alert generation
- Multi-channel message creation
- CSV data export
""")
# Results section
with gr.Row():
with gr.Column(scale=2):
workflow_output = gr.Markdown(
label="πŸ“‹ Workflow Output",
value="Click 'Generate Weather Alert' to see results..."
)
with gr.Column(scale=1):
alert_summary = gr.Markdown(
label="πŸ“Š Alert Summary",
value="Alert details will appear here..."
)
# CSV export
with gr.Row():
csv_output = gr.File(
label="πŸ“ Download CSV Data",
visible=False
)
# Event handling
def run_workflow_with_csv(district):
workflow, summary, csv_content = test_mcp_workflow(district)
# Create temporary CSV file if content exists
if csv_content:
filename = f"bihar_alert_{district.lower()}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
with open(filename, 'w') as f:
f.write(csv_content)
return workflow, summary, gr.File(value=filename, visible=True)
else:
return workflow, summary, gr.File(visible=False)
run_btn.click(
run_workflow_with_csv,
inputs=[district_input],
outputs=[workflow_output, alert_summary, csv_output]
)
# Footer
gr.Markdown("""
---
### πŸ”— System Information:
- **State Coverage**: Bihar (38 districts)
- **Crops Supported**: Rice, Wheat, Maize, Sugarcane, Mustard, and more
- **Weather Sources**: Open-Meteo API with AI enhancement
- **Communication Channels**: SMS, WhatsApp, USSD, IVR, Telegram
### πŸ“ž Agent Outputs:
The system generates formatted messages for:
- **πŸ“± SMS**: Short text alerts for basic phones
- **πŸ“± WhatsApp**: Rich media messages with emojis
- **πŸ“ž USSD**: Interactive menu systems
- **πŸŽ™οΈ IVR**: Voice script for phone calls
- **πŸ€– Telegram**: Bot-friendly formatted messages
*Built with MCP (Model Context Protocol) for agricultural intelligence*
""")
# Launch configuration for HuggingFace Spaces
if __name__ == "__main__":
demo.launch(
share=True,
server_name="0.0.0.0",
server_port=7860,
show_error=True
)