Skip to main content
Glama
jagan-shanmugam

OpenStreetMap MCP Server

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

TableJSON Schema
NameRequiredDescriptionDefault
latitudeYes
longitudeYes
radiusNo
education_levelsNo

Implementation Reference

  • 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)
        }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jagan-shanmugam/open-streetmap-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server