find_schools_nearby
Locate schools and educational institutions near a specific location, filtered by education level such as elementary, secondary, or university. Useful for families evaluating neighborhoods or real estate purchases with education considerations.
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 |
|---|---|---|---|
| latitude | Yes | ||
| longitude | Yes | ||
| radius | No | ||
| education_levels | No |
Implementation Reference
- src/osm_mcp_server/server.py:801-948 (handler)The primary handler function for the 'find_schools_nearby' MCP tool. It uses Overpass API to query for schools, universities, kindergartens, and colleges within a bounding box derived from the input coordinates and radius. Filters results by education_levels if provided, calculates distances using the haversine formula, and returns a sorted list of schools with detailed information including name, type, coordinates, distance, and address.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) }