|
import gradio as gr |
|
import logging |
|
from camptocamp_api import CamptocampAPI |
|
from typing import Optional |
|
|
|
|
|
logging.basicConfig( |
|
level=logging.INFO, |
|
format="%(asctime)s [%(levelname)s] %(message)s" |
|
) |
|
logger = logging.getLogger("CamptocampApp") |
|
|
|
|
|
c2c = CamptocampAPI(language="en") |
|
|
|
ACTIVITIES = [ |
|
"hiking", "snowshoeing", "skitouring", "snow_ice_mixed", |
|
"rock_climbing", "ice_climbing", "mountaineering", "via_ferrata", |
|
"paragliding", "bouldering", "multi_pitch", |
|
"bike", "mountain_bike", "trail_running", "alpine_climbing" |
|
] |
|
|
|
|
|
def get_recent_outings_by_location(location: str, start_date: Optional[str] = None, end_date: Optional[str] = None, activity: Optional[str] = None, limit: int = 10) -> dict: |
|
logger.info(f"[Outings] Resolving location: {location}") |
|
bbox = c2c.get_bbox_from_location(location) |
|
if not bbox: |
|
logger.warning(f"No bounding box found for: {location}") |
|
return {"error": f"Could not resolve bounding box for location: {location}"} |
|
logger.info(f"BBox for '{location}': {bbox}") |
|
date_range = (start_date, end_date) if start_date and end_date else None |
|
result = c2c.get_recent_outings(bbox, date_range, activity, limit) |
|
logger.info(f"Returned {len(result.get('documents', []))} outings.") |
|
return result |
|
|
|
def search_routes_by_location(location: str, activity: str, limit: int = 10) -> dict: |
|
logger.info(f"[Routes] Resolving location: {location}") |
|
bbox = c2c.get_bbox_from_location(location) |
|
if not bbox: |
|
logger.warning(f"No bounding box found for: {location}") |
|
return {"error": f"Could not resolve bounding box for location: {location}"} |
|
logger.info(f"BBox for '{location}': {bbox}") |
|
result = c2c.search_routes_by_activity(bbox, activity, limit) |
|
logger.info(f"Returned {len(result.get('documents', []))} routes.") |
|
return result |
|
|
|
def get_route_details(route_id: int) -> dict: |
|
logger.info(f"[Details] Fetching route ID: {route_id}") |
|
return c2c.get_route_details(route_id) |
|
|
|
def search_waypoints_by_location(location: str, limit: int = 10) -> dict: |
|
logger.info(f"[Waypoints] Resolving location: {location}") |
|
bbox = c2c.get_bbox_from_location(location) |
|
if not bbox: |
|
logger.warning(f"No bounding box found for: {location}") |
|
return {"error": f"Could not resolve bounding box for location: {location}"} |
|
logger.info(f"BBox for '{location}': {bbox}") |
|
result = c2c.search_waypoints(bbox, limit) |
|
logger.info(f"Returned {len(result.get('documents', []))} waypoints.") |
|
return result |
|
|
|
def lookup_bbox_from_location(location_name: str) -> Optional[dict]: |
|
logger.info(f"[Lookup] Resolving location: {location_name}") |
|
bbox = c2c.get_bbox_from_location(location_name) |
|
if not bbox: |
|
logger.warning(f"No bounding box found for: {location_name}") |
|
return {"error": f"No bounding box found for: {location_name}"} |
|
return { |
|
"west": bbox[0], |
|
"south": bbox[1], |
|
"east": bbox[2], |
|
"north": bbox[3] |
|
} |
|
|
|
|
|
with gr.Blocks(title="Camptocamp MCP Server") as demo: |
|
gr.Markdown("# ποΈ Camptocamp API MCP") |
|
|
|
with gr.Tab("π Recent Outings"): |
|
loc = gr.Textbox(label="Location (e.g. Chamonix, La Grave)") |
|
start = gr.Textbox(label="Start Date (YYYY-MM-DD)") |
|
end = gr.Textbox(label="End Date (YYYY-MM-DD)") |
|
act = gr.Dropdown(label="Activity", choices=ACTIVITIES, allow_none=True, value="alpine_climbing") |
|
limit = gr.Number(label="Result Limit", value=5) |
|
out = gr.JSON() |
|
gr.Button("Get Outings").click(get_recent_outings_by_location, |
|
inputs=[loc, start, end, act, limit], |
|
outputs=out) |
|
|
|
with gr.Tab("π§ Search Routes"): |
|
rloc = gr.Textbox(label="Location (e.g. Alps)") |
|
ract = gr.Dropdown(label="Activity", choices=ACTIVITIES, value="alpine_climbing") |
|
rlim = gr.Number(label="Result Limit", value=5) |
|
rout = gr.JSON() |
|
gr.Button("Search Routes").click(search_routes_by_location, |
|
inputs=[rloc, ract, rlim], |
|
outputs=rout) |
|
|
|
with gr.Tab("π Route Details"): |
|
rid = gr.Number(label="Route ID") |
|
rdet = gr.JSON() |
|
gr.Button("Get Route Details").click(get_route_details, |
|
inputs=[rid], |
|
outputs=rdet) |
|
|
|
with gr.Tab("β° Waypoints"): |
|
wloc = gr.Textbox(label="Location (e.g. Mont Blanc)") |
|
wlim = gr.Number(label="Result Limit", value=5) |
|
wout = gr.JSON() |
|
gr.Button("Get Waypoints").click(search_waypoints_by_location, |
|
inputs=[wloc, wlim], |
|
outputs=wout) |
|
|
|
with gr.Tab("π Location β BBox"): |
|
lstr = gr.Textbox(label="Location Name") |
|
lout = gr.JSON() |
|
gr.Button("Lookup BBox").click(lookup_bbox_from_location, |
|
inputs=[lstr], |
|
outputs=lout) |
|
|
|
demo.launch() |
|
|