find_schools_nearby
Identify nearby schools, colleges, and educational institutions based on location and education level. Filter results by type (elementary, high school, university) and distance for informed decisions on relocating or real estate investments.
Instructions
Locate educational institutions near a specific location, filtered by education level.
This specialized search tool identifies schools, colleges, and other educational institutions within a specified distance from a location. Results can be filtered by education level (elementary, middle, high school, university, etc.). Essential for families evaluating neighborhoods or real estate purchases with education considerations.
Args: latitude: Center point latitude (decimal degrees) longitude: Center point longitude (decimal degrees) radius: Search radius in meters (defaults to 2000m/2km) education_levels: Optional list of specific education levels to filter by (e.g., ["elementary", "secondary", "university"])
Returns: List of educational institutions with: - Name and type - Distance from search point - Education levels offered - Contact information if available - Other relevant metadata
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| education_levels | No | ||
| latitude | Yes | ||
| longitude | Yes | ||
| radius | No |
Implementation Reference
- src/osm_mcp_server/server.py:801-947 (handler)The core handler function for the 'find_schools_nearby' MCP tool. It queries the Overpass API for OSM features tagged as schools, universities, kindergartens, and colleges within a bounding box approximating the given radius. Filters by education_levels if specified, computes distances using Haversine formula, sorts results by proximity, and returns a structured JSON response with school details including names, types, coordinates, distances, and addresses.async def find_schools_nearby( latitude: float, longitude: float, ctx: Context, radius: float = 2000, education_levels: List[str] = None ) -> Dict[str, Any]: """ Locate educational institutions near a specific location, filtered by education level. This specialized search tool identifies schools, colleges, and other educational institutions within a specified distance from a location. Results can be filtered by education level (elementary, middle, high school, university, etc.). Essential for families evaluating neighborhoods or real estate purchases with education considerations. Args: latitude: Center point latitude (decimal degrees) longitude: Center point longitude (decimal degrees) radius: Search radius in meters (defaults to 2000m/2km) education_levels: Optional list of specific education levels to filter by (e.g., ["elementary", "secondary", "university"]) Returns: List of educational institutions with: - Name and type - Distance from search point - Education levels offered - Contact information if available - Other relevant metadata """ osm_client = ctx.request_context.lifespan_context.osm_client # Convert radius to bounding box (approximate) lat_delta = radius / 111000 lon_delta = radius / (111000 * math.cos(math.radians(latitude))) bbox = ( longitude - lon_delta, latitude - lat_delta, longitude + lon_delta, latitude + lat_delta ) # Build Overpass query for educational institutions overpass_url = "https://overpass-api.de/api/interpreter" # Create query for amenity=school and other education-related tags education_filters = [ 'node["amenity"="school"]({{bbox}});', 'way["amenity"="school"]({{bbox}});', 'node["amenity"="university"]({{bbox}});', 'way["amenity"="university"]({{bbox}});', 'node["amenity"="kindergarten"]({{bbox}});', 'way["amenity"="kindergarten"]({{bbox}});', 'node["amenity"="college"]({{bbox}});', 'way["amenity"="college"]({{bbox}});' ] query = f""" [out:json]; ( {" ".join(education_filters)} ); out body; """ query = query.replace("{bbox}", f"{bbox[1]},{bbox[0]},{bbox[3]},{bbox[2]}") async with aiohttp.ClientSession() as session: async with session.post(overpass_url, data={"data": query}) as response: if response.status == 200: data = await response.json() schools = data.get("elements", []) else: raise Exception(f"Failed to find schools: {response.status}") # Process and filter results results = [] for school in schools: tags = school.get("tags", {}) school_type = tags.get("school", "") # Filter by education level if specified if education_levels and school_type and school_type not in education_levels: continue # Get coordinates based on feature type coords = {} if school.get("type") == "node": coords = { "latitude": school.get("lat"), "longitude": school.get("lon") } elif "center" in school: coords = { "latitude": school.get("center", {}).get("lat"), "longitude": school.get("center", {}).get("lon") } # Skip if no valid coordinates if not coords: continue # Calculate distance from search point # Using Haversine formula for quick distance calculation from math import radians, sin, cos, sqrt, asin def haversine(lat1, lon1, lat2, lon2): R = 6371000 # Earth radius in meters dLat = radians(lat2 - lat1) dLon = radians(lon2 - lon1) a = sin(dLat/2)**2 + cos(radians(lat1)) * cos(radians(lat2)) * sin(dLon/2)**2 c = 2 * asin(sqrt(a)) return R * c distance = haversine(latitude, longitude, coords["latitude"], coords["longitude"]) results.append({ "id": school.get("id"), "name": tags.get("name", "Unnamed School"), "amenity_type": tags.get("amenity", ""), "school_type": school_type, "education_level": tags.get("isced", ""), "coordinates": coords, "distance": round(distance, 1), "address": { "street": tags.get("addr:street", ""), "housenumber": tags.get("addr:housenumber", ""), "city": tags.get("addr:city", ""), "postcode": tags.get("addr:postcode", "") }, "tags": tags }) # Sort by distance results.sort(key=lambda x: x["distance"]) return { "query": { "latitude": latitude, "longitude": longitude, "radius": radius, "education_levels": education_levels }, "schools": results, "count": len(results) }