search_locations
Find Australian locations by name or state code. Returns location IDs and details for the 21 curated cities, including capitals and major regional centres.
Instructions
Fuzzy-search the 21 curated Australian locations.
The curated set covers all 8 state/territory capitals plus 13 major regional centres (Newcastle, Wollongong, Gold Coast, Sunshine Coast, Cairns, Townsville, Mackay, Geelong, Ballarat, Bendigo, Launceston, Alice Springs, Broome).
Examples: results = await search_locations("sydney") # → [{id: 'sydney', name: 'Sydney', state: 'NSW', ...}]
results = await search_locations("nsw")
# → Newcastle, Wollongong, Sydney (all NSW locations)When to use: - Discover the location ID for a city you know by name - Find all supported locations in a state - Verify whether a place is in the curated set before calling get_weather
Returns: List of LocationSummary (id, name, state, description), ranked by relevance.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Free-text search query. Matches against location IDs, names, and state codes. Case-insensitive. | |
| limit | No | Maximum number of results to return, ranked by relevance. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/au_weather_mcp/server.py:109-179 (handler)Main tool handler for search_locations. Validates query (must be non-empty string) and limit (must be positive int), then delegates to curated_mod.search() for fuzzy matching. Returns list of LocationSummary objects.
@mcp.tool async def search_locations( query: Annotated[ str, Field( description=( "Free-text search query. Matches against location IDs, names, " "and state codes. Case-insensitive." ), examples=["sydney", "nsw", "tropical north", "gold coast", "tasmania"], ), ], limit: Annotated[ int, Field( description="Maximum number of results to return, ranked by relevance.", examples=[5, 10, 21], ge=1, le=100, ), ] = 10, ) -> list[LocationSummary]: """Fuzzy-search the 21 curated Australian locations. The curated set covers all 8 state/territory capitals plus 13 major regional centres (Newcastle, Wollongong, Gold Coast, Sunshine Coast, Cairns, Townsville, Mackay, Geelong, Ballarat, Bendigo, Launceston, Alice Springs, Broome). Examples: results = await search_locations("sydney") # → [{id: 'sydney', name: 'Sydney', state: 'NSW', ...}] results = await search_locations("nsw") # → Newcastle, Wollongong, Sydney (all NSW locations) When to use: - Discover the location ID for a city you know by name - Find all supported locations in a state - Verify whether a place is in the curated set before calling get_weather Returns: List of LocationSummary (id, name, state, description), ranked by relevance. """ if not isinstance(query, str): raise ValueError( f"query must be a string, got {type(query).__name__}. " "Try 'sydney', 'nsw', 'tropical', or another place name." ) if not query.strip(): raise ValueError( "query is required. Try 'sydney', 'nsw', 'tropical', " "or any Australian place name." ) if isinstance(limit, bool) or not isinstance(limit, int): raise ValueError( f"limit must be a positive integer, got {limit!r} ({type(limit).__name__})." ) if limit < 1: raise ValueError(f"limit must be >= 1, got {limit}.") matches = curated_mod.search(query, limit=limit) return [ LocationSummary( id=m.id, name=m.name, state=m.state, description=m.description, ) for m in matches ] - src/au_weather_mcp/models.py:30-35 (schema)Return type schema for search_locations. Contains id, name, state, and optional description.
class LocationSummary(BaseModel): """A curated AU location — surface for search_locations and list_curated.""" id: str name: str state: str # NSW, VIC, etc. description: str | None = None - Core fuzzy-search logic using rapidfuzz. Builds a haystack from id+name+state+description, applies WRatio scorer, deduplicates results, and returns up to limit matches.
def search(query: str, limit: int = 10) -> list[CuratedLocation]: """Fuzzy-search the curated location set. Matches against id + name + state so 'syd', 'Sydney', 'NSW' all work. Returns up to `limit` rows ranked by score. """ locs = all_locations() # Each haystack entry is "id name state description" — wide enough for # broad queries like 'tropical north qld' to hit Cairns/Townsville. haystack = { i: f"{loc.id} {loc.name} {loc.state} {loc.description or ''}".lower() for i, loc in enumerate(locs) } matches = process.extract( query.lower(), haystack, scorer=fuzz.WRatio, limit=max(limit * 2, 20) ) seen: set[int] = set() out: list[CuratedLocation] = [] for _hay, _score, idx in matches: if idx in seen: continue seen.add(idx) out.append(locs[idx]) if len(out) >= limit: break return out - src/au_weather_mcp/server.py:109-109 (registration)Tool registration via the @mcp.tool decorator (FastMCP) on the search_locations handler function.
@mcp.tool