Skip to main content
Glama

explore_area

Analyze and profile specific geographic areas by identifying amenities, points of interest, and features. Organizes results by category for neighborhood research, area comparisons, and location-based decisions.

Instructions

Generate a comprehensive profile of an area including all amenities and features.

This powerful analysis tool creates a detailed overview of a neighborhood or area by identifying and categorizing all geographic features, amenities, and points of interest. Results are organized by category for easy analysis. Excellent for neighborhood research, area comparisons, and location-based decision making.

Args: latitude: Center point latitude (decimal degrees) longitude: Center point longitude (decimal degrees) radius: Search radius in meters (defaults to 500m)

Returns: In-depth area profile including: - Address and location context - Total feature count - Features organized by category and subcategory - Each feature includes name, coordinates, and detailed metadata

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
latitudeYes
longitudeYes
radiusNo

Implementation Reference

  • The primary handler implementation for the 'explore_area' MCP tool. This async function queries OpenStreetMap via the OSMClient for multiple feature categories within a radius, groups results by subcategory, fetches address info, and returns a detailed area profile dictionary.
    async def explore_area( latitude: float, longitude: float, ctx: Context, radius: float = 500 ) -> Dict[str, Any]: """ Generate a comprehensive profile of an area including all amenities and features. This powerful analysis tool creates a detailed overview of a neighborhood or area by identifying and categorizing all geographic features, amenities, and points of interest. Results are organized by category for easy analysis. Excellent for neighborhood research, area comparisons, and location-based decision making. Args: latitude: Center point latitude (decimal degrees) longitude: Center point longitude (decimal degrees) radius: Search radius in meters (defaults to 500m) Returns: In-depth area profile including: - Address and location context - Total feature count - Features organized by category and subcategory - Each feature includes name, coordinates, and detailed metadata """ osm_client = ctx.request_context.lifespan_context.osm_client # Categories to search for categories = [ "amenity", "shop", "tourism", "leisure", "natural", "historic", "public_transport" ] results = {} for i, category in enumerate(categories): await ctx.report_progress(i, len(categories)) ctx.info(f"Exploring {category} features...") try: # Convert radius to bounding box 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 ) features = await osm_client.search_features_by_category(bbox, category) # Group by subcategory subcategories = {} for feature in features: tags = feature.get("tags", {}) subcategory = tags.get(category) if subcategory: if subcategory not in subcategories: subcategories[subcategory] = [] # Get coordinates based on feature type coords = {} if feature.get("type") == "node": coords = { "latitude": feature.get("lat"), "longitude": feature.get("lon") } elif "center" in feature: coords = { "latitude": feature.get("center", {}).get("lat"), "longitude": feature.get("center", {}).get("lon") } subcategories[subcategory].append({ "id": feature.get("id"), "name": tags.get("name", "Unnamed"), "coordinates": coords, "type": feature.get("type"), "tags": tags }) results[category] = subcategories except Exception as e: ctx.warning(f"Error fetching {category} features: {str(e)}") results[category] = {} # Get address information for the center point try: address_info = await osm_client.reverse_geocode(latitude, longitude) except Exception: address_info = {"error": "Could not retrieve address information"} # Report completion await ctx.report_progress(len(categories), len(categories)) # Count total features total_features = sum( len(places) for category_data in results.values() for places in category_data.values() ) return { "query": { "latitude": latitude, "longitude": longitude, "radius": radius }, "address": address_info, "categories": results, "total_features": total_features, "timestamp": datetime.now().isoformat() }
  • Helper method in OSMClient class used by explore_area to fetch OSM features by category within a bounding box via Overpass API.
    async def search_features_by_category(self, bbox: Tuple[float, float, float, float], category: str, subcategories: List[str] = None) -> List[Dict]: """Search for OSM features by category and subcategories""" if not self.session: raise RuntimeError("OSM client not connected") overpass_url = "https://overpass-api.de/api/interpreter" # Build query for specified category and subcategories if subcategories: subcategory_filters = " or ".join([f'"{category}"="{sub}"' for sub in subcategories]) query_filter = f'({subcategory_filters})' else: query_filter = f'"{category}"' query = f""" [out:json]; ( node[{query_filter}]({bbox[1]},{bbox[0]},{bbox[3]},{bbox[2]}); way[{query_filter}]({bbox[1]},{bbox[0]},{bbox[3]},{bbox[2]}); relation[{query_filter}]({bbox[1]},{bbox[0]},{bbox[3]},{bbox[2]}); ); out body; """ async with self.session.post(overpass_url, data={"data": query}) as response: if response.status == 200: data = await response.json() return data.get("elements", []) else: raise Exception(f"Failed to search features by category: {response.status}")
  • OSMClient helper method called by explore_area to get address information for the center point.
    async def reverse_geocode(self, lat: float, lon: float) -> Dict: """Reverse geocode coordinates to address""" if not self.session: raise RuntimeError("OSM client not connected") nominatim_url = "https://nominatim.openstreetmap.org/reverse" async with self.session.get( nominatim_url, params={ "lat": lat, "lon": lon, "format": "json" }, headers={"User-Agent": "OSM-MCP-Server/1.0"} ) as response: if response.status == 200: return await response.json() else: raise Exception(f"Failed to reverse geocode ({lat}, {lon}): {response.status}")
  • The @mcp.tool() decorator registers the explore_area function as an MCP tool.
    async def explore_area(

Other Tools

Related Tools

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