cwadayi commited on
Commit
92d48d5
·
verified ·
1 Parent(s): 29725a6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +138 -0
app.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import sqlite3
3
+ import pandas as pd
4
+ import gradio as gr
5
+ from mcp.server import MCPServer
6
+ from mcp.common.tool import Tool, ToolResult
7
+
8
+ class EarthquakeDataTool(Tool):
9
+ """
10
+ A tool to retrieve earthquake data from the database with filtering capabilities.
11
+ """
12
+ def __init__(self, db_path):
13
+ super().__init__(
14
+ name="get_earthquake_data",
15
+ description="Fetches earthquake catalog data with optional filters.",
16
+ parameters={
17
+ "date": {"type": "string", "description": "Filter by date (YYYY-MM-DD)"},
18
+ "lat_min": {"type": "number", "description": "Minimum latitude"},
19
+ "lat_max": {"type": "number", "description": "Maximum latitude"},
20
+ "lon_min": {"type": "number", "description": "Minimum longitude"},
21
+ "lon_max": {"type": "number", "description": "Maximum longitude"},
22
+ "depth_min": {"type": "number", "description": "Minimum depth"},
23
+ "depth_max": {"type": "number", "description": "Maximum depth"},
24
+ "ML_min": {"type": "number", "description": "Minimum magnitude (ML)"},
25
+ "ML_max": {"type": "number", "description": "Maximum magnitude (ML)"},
26
+ },
27
+ )
28
+ self.db_path = db_path
29
+
30
+ async def __call__(self, **kwargs) -> ToolResult:
31
+ try:
32
+ conn = sqlite3.connect(self.db_path)
33
+
34
+ query = "SELECT * FROM earthquakes WHERE 1=1"
35
+ params = []
36
+
37
+ # Handle filters
38
+ if kwargs.get("date"):
39
+ query += " AND date = ?"
40
+ params.append(kwargs["date"])
41
+ if kwargs.get("lat_min"):
42
+ query += " AND lat >= ?"
43
+ params.append(kwargs["lat_min"])
44
+ if kwargs.get("lat_max"):
45
+ query += " AND lat <= ?"
46
+ params.append(kwargs["lat_max"])
47
+ if kwargs.get("lon_min"):
48
+ query += " AND lon >= ?"
49
+ params.append(kwargs["lon_min"])
50
+ if kwargs.get("lon_max"):
51
+ query += " AND lon <= ?"
52
+ params.append(kwargs["lon_max"])
53
+ if kwargs.get("depth_min"):
54
+ query += " AND depth >= ?"
55
+ params.append(kwargs["depth_min"])
56
+ if kwargs.get("depth_max"):
57
+ query += " AND depth <= ?"
58
+ params.append(kwargs["depth_max"])
59
+ if kwargs.get("ML_min"):
60
+ query += " AND ML >= ?"
61
+ params.append(kwargs["ML_min"])
62
+ if kwargs.get("ML_max"):
63
+ query += " AND ML <= ?"
64
+ params.append(kwargs["ML_max"])
65
+
66
+ df = pd.read_sql_query(query, conn, params=tuple(params))
67
+ conn.close()
68
+
69
+ return ToolResult.success(df)
70
+ except Exception as e:
71
+ return ToolResult.error(str(e))
72
+
73
+ class EarthquakeMCPServer(MCPServer):
74
+ def __init__(self, db_path):
75
+ super().__init__()
76
+ self.tool = EarthquakeDataTool(db_path)
77
+ self.add_tool(self.tool)
78
+
79
+ # --- Gradio Interface ---
80
+ def create_gradio_interface(server_tool):
81
+ async def fetch_data(date, lat_min, lat_max, lon_min, lon_max, depth_min, depth_max, ML_min, ML_max):
82
+ # Create a dictionary of filters, excluding empty values
83
+ filters = {
84
+ "date": date,
85
+ "lat_min": lat_min,
86
+ "lat_max": lat_max,
87
+ "lon_min": lon_min,
88
+ "lon_max": lon_max,
89
+ "depth_min": depth_min,
90
+ "depth_max": depth_max,
91
+ "ML_min": ML_min,
92
+ "ML_max": ML_max,
93
+ }
94
+ active_filters = {k: v for k, v in filters.items() if v is not None and v != ''}
95
+
96
+ result = await server_tool(**active_filters)
97
+ if result.is_success:
98
+ return result.content
99
+ else:
100
+ return pd.DataFrame({"error": [result.content]})
101
+
102
+ with gr.Blocks() as iface:
103
+ gr.Markdown("# Earthquake Data Explorer")
104
+ gr.Markdown("Use the filters below to search the earthquake catalog.")
105
+
106
+ with gr.Row():
107
+ date = gr.Textbox(label="Date (YYYY-MM-DD)")
108
+ with gr.Row():
109
+ lat_min = gr.Number(label="Min Latitude")
110
+ lat_max = gr.Number(label="Max Latitude")
111
+ with gr.Row():
112
+ lon_min = gr.Number(label="Min Longitude")
113
+ lon_max = gr.Number(label="Max Longitude")
114
+ with gr.Row():
115
+ depth_min = gr.Number(label="Min Depth")
116
+ depth_max = gr.Number(label="Max Depth")
117
+ with gr.Row():
118
+ ML_min = gr.Number(label="Min Magnitude (ML)")
119
+ ML_max = gr.Number(label="Max Magnitude (ML)")
120
+
121
+ filter_button = gr.Button("Filter Data")
122
+
123
+ output_df = gr.DataFrame(label="Filtered Results")
124
+
125
+ filter_button.click(
126
+ fn=fetch_data,
127
+ inputs=[date, lat_min, lat_max, lon_min, lon_max, depth_min, depth_max, ML_min, ML_max],
128
+ outputs=output_df
129
+ )
130
+ return iface
131
+
132
+ # --- Main execution ---
133
+ if __name__ == "__main__":
134
+ # In a real-world scenario, the server might run as a separate process.
135
+ # For this Gradio app, we'll instantiate the tool directly.
136
+ server = EarthquakeMCPServer('earthquake_data.db')
137
+ gradio_app = create_gradio_interface(server.tool)
138
+ gradio_app.launch(server_name="0.0.0.0")