File size: 5,208 Bytes
b2ff92e
7d1cee1
b2ff92e
038aba5
b2ff92e
7d1cee1
 
 
 
 
 
 
 
b2ff92e
 
4cab5dd
 
 
 
 
 
 
 
7d1cee1
 
038aba5
 
7d1cee1
038aba5
7d1cee1
b2ff92e
7d1cee1
 
 
b2ff92e
7d1cee1
 
038aba5
 
7d1cee1
 
 
 
 
 
b2ff92e
96d425d
7d1cee1
b2ff92e
 
038aba5
7d1cee1
038aba5
 
7d1cee1
 
 
 
 
 
b2ff92e
038aba5
7d1cee1
038aba5
 
7d1cee1
038aba5
 
 
 
 
 
 
 
7d1cee1
038aba5
7d1cee1
038aba5
 
 
 
 
4cab5dd
038aba5
 
 
 
 
 
 
 
4cab5dd
038aba5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b2ff92e
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import gradio as gr
import logging
from camptocamp_api import CamptocampAPI
from typing import Optional

# Configure logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s"
)
logger = logging.getLogger("CamptocampApp")

# Instantiate API client
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]
    }

# Gradio UI
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()