search_category
Find specific types of places like restaurants, schools, or parks within a defined geographic area using category-based filtering. Returns detailed location and metadata for each result.
Instructions
Search for specific types of places within a defined geographic area.
This tool allows targeted searches for places matching specific categories within a rectangular geographic region. It's particularly useful for filtering places by type (restaurants, schools, parks, etc.) within a neighborhood or city district. Results include complete location details and metadata about each matching place.
Args: category: Main OSM category to search for (e.g., "amenity", "shop", "tourism", "building") min_latitude: Southern boundary of search area (decimal degrees) min_longitude: Western boundary of search area (decimal degrees) max_latitude: Northern boundary of search area (decimal degrees) max_longitude: Eastern boundary of search area (decimal degrees) subcategories: Optional list of specific subcategories to filter by (e.g., ["restaurant", "cafe"])
Returns: Structured results including: - Query parameters - Count of matching places - List of matching places with coordinates, names, and metadata
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | ||
| max_latitude | Yes | ||
| max_longitude | Yes | ||
| min_latitude | Yes | ||
| min_longitude | Yes | ||
| subcategories | No |
Implementation Reference
- src/osm_mcp_server/server.py:442-524 (handler)The primary handler function for the 'search_category' MCP tool. It processes input parameters to form a bounding box, calls the OSMClient helper to query Overpass API, processes the OSM features (extracting coordinates and tags), and returns structured results grouped by category.async def search_category( category: str, min_latitude: float, min_longitude: float, max_latitude: float, max_longitude: float, ctx: Context, subcategories: List[str] = None ) -> Dict[str, Any]: """ Search for specific types of places within a defined geographic area. This tool allows targeted searches for places matching specific categories within a rectangular geographic region. It's particularly useful for filtering places by type (restaurants, schools, parks, etc.) within a neighborhood or city district. Results include complete location details and metadata about each matching place. Args: category: Main OSM category to search for (e.g., "amenity", "shop", "tourism", "building") min_latitude: Southern boundary of search area (decimal degrees) min_longitude: Western boundary of search area (decimal degrees) max_latitude: Northern boundary of search area (decimal degrees) max_longitude: Eastern boundary of search area (decimal degrees) subcategories: Optional list of specific subcategories to filter by (e.g., ["restaurant", "cafe"]) Returns: Structured results including: - Query parameters - Count of matching places - List of matching places with coordinates, names, and metadata """ osm_client = ctx.request_context.lifespan_context.osm_client bbox = (min_longitude, min_latitude, max_longitude, max_latitude) ctx.info(f"Searching for {category} in bounding box") features = await osm_client.search_features_by_category(bbox, category, subcategories) # Process results results = [] for feature in features: tags = feature.get("tags", {}) # Get coordinates based on feature type coords = {} if feature.get("type") == "node": coords = { "latitude": feature.get("lat"), "longitude": feature.get("lon") } # For ways and relations, use center coordinates if available elif "center" in feature: coords = { "latitude": feature.get("center", {}).get("lat"), "longitude": feature.get("center", {}).get("lon") } # Only include features with valid coordinates if coords: results.append({ "id": feature.get("id"), "type": feature.get("type"), "name": tags.get("name", "Unnamed"), "coordinates": coords, "category": category, "subcategory": tags.get(category), "tags": tags }) return { "query": { "category": category, "subcategories": subcategories, "bbox": { "min_latitude": min_latitude, "min_longitude": min_longitude, "max_latitude": max_latitude, "max_longitude": max_longitude } }, "results": results, "count": len(results) }
- src/osm_mcp_server/server.py:144-177 (helper)Supporting method in OSMClient class that constructs and executes an Overpass API query to fetch OSM nodes, ways, and relations matching the given category (and optional subcategories) within the specified bounding box.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}")