We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jana-Earth-Data/jana-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""Nearby location search tools for MCP."""
import logging
from typing import Any
import httpx
from mcp.types import TextContent, Tool
from jana_mcp.client import APIError, AuthenticationError, JanaClient
from jana_mcp.constants import DEFAULT_LIMIT
from jana_mcp.tools.response import create_error_response, serialize_response
from jana_mcp.tools.validation import validate_coordinates
logger = logging.getLogger(__name__)
NEARBY_TOOL = Tool(
name="find_nearby",
description="""Find environmental monitoring stations and emission sources near a location.
Returns air quality stations and emission facilities within the specified radius
of the given coordinates, with distance information.""",
inputSchema={
"type": "object",
"properties": {
"location_point": {
"type": "array",
"items": {"type": "number"},
"minItems": 2,
"maxItems": 2,
"description": "Point coordinates [longitude, latitude]",
},
"radius_km": {
"type": "number",
"minimum": 0.1,
"maximum": 500,
"description": "Search radius in kilometers",
},
"sources": {
"type": "array",
"items": {
"type": "string",
"enum": ["openaq", "climatetrace", "edgar"],
},
"description": "Data sources to search (default: all)",
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 1000,
"default": 100,
"description": "Maximum number of results",
},
},
"required": ["location_point", "radius_km"],
},
)
async def execute_nearby(
client: JanaClient, arguments: dict[str, Any]
) -> list[TextContent]:
"""
Execute the nearby search tool.
Args:
client: Jana API client
arguments: Tool arguments from MCP call
Returns:
List of TextContent with results or error message
"""
logger.info("Executing find_nearby")
# Validate required parameters
location_point = arguments.get("location_point")
radius_km = arguments.get("radius_km")
if not location_point:
error_response = create_error_response(
"location_point is required [longitude, latitude]", "VALIDATION_ERROR"
)
return [TextContent(type="text", text=serialize_response(error_response))]
if not radius_km:
error_response = create_error_response(
"radius_km is required", "VALIDATION_ERROR"
)
return [TextContent(type="text", text=serialize_response(error_response))]
# Validate coordinates
coord_error = validate_coordinates(location_point[0], location_point[1])
if coord_error:
error_response = create_error_response(coord_error, "VALIDATION_ERROR")
return [TextContent(type="text", text=serialize_response(error_response))]
try:
result = await client.find_nearby(
point=location_point,
radius_km=radius_km,
sources=arguments.get("sources"),
limit=arguments.get("limit", DEFAULT_LIMIT),
)
return [
TextContent(
type="text",
text=serialize_response(result),
)
]
except (APIError, AuthenticationError) as e:
logger.exception("API error in find_nearby")
error_response = create_error_response(
f"API error finding nearby data: {e}", "API_ERROR"
)
return [TextContent(type="text", text=serialize_response(error_response))]
except httpx.RequestError as e:
logger.exception("Network error in find_nearby")
error_response = create_error_response(
f"Network error finding nearby data: {e}", "NETWORK_ERROR"
)
return [TextContent(type="text", text=serialize_response(error_response))]
except (KeyError, ValueError, TypeError) as e:
logger.exception("Data parsing error in find_nearby")
error_response = create_error_response(
f"Invalid data format: {e}", "DATA_ERROR"
)
return [TextContent(type="text", text=serialize_response(error_response))]