Download utils/api_config.py from Agents-MCP-Hackathon/test_mcp_server: direct link, hf CLI and curl.
- Browser
- Download file 8.23 kB
-
https://huggingface.co/spaces/Agents-MCP-Hackathon/test_mcp_server/resolve/main/utils/api_config.py
- Command line
-
hf download hf://spaces/Agents-MCP-Hackathon/test_mcp_server/utils/api_config.py
-
curl -L -o api_config.py https://huggingface.co/spaces/Agents-MCP-Hackathon/test_mcp_server/resolve/main/utils/api_config.py
8.23 kB
| """ | |
| Central API configuration and environment setup. | |
| """ | |
| import os | |
| import requests | |
| from typing import Dict, Tuple, Optional | |
| import json | |
| import time | |
| from urllib.parse import quote | |
| class APIConfig: | |
| """Centralized API configuration and validation.""" | |
| def __init__(self): | |
| self.foursquare_api_key = os.environ.get('FOURSQUARE_API_KEY') | |
| self.anthropic_api_key = os.environ.get('ANTHROPIC_API_KEY') | |
| # Set environment if not already set and key is available | |
| if self.foursquare_api_key and not os.environ.get('FOURSQUARE_API_KEY'): | |
| os.environ['FOURSQUARE_API_KEY'] = self.foursquare_api_key | |
| def validate_apis(self) -> Dict[str, bool]: | |
| """Validate API keys and connectivity.""" | |
| results = {} | |
| # Test Foursquare API | |
| if self.foursquare_api_key: | |
| try: | |
| url = "https://api.foursquare.com/v3/places/search" | |
| headers = { | |
| "accept": "application/json", | |
| "Authorization": self.foursquare_api_key | |
| } | |
| params = {"query": "test", "limit": 1} | |
| response = requests.get(url, headers=headers, params=params, timeout=5) | |
| results['foursquare'] = response.status_code == 200 | |
| except Exception: | |
| results['foursquare'] = False | |
| else: | |
| results['foursquare'] = False | |
| # Check Anthropic API key existence | |
| results['anthropic'] = bool(self.anthropic_api_key) | |
| return results | |
| def print_status(self): | |
| """Print API configuration status.""" | |
| print("\n🔧 API Configuration Status:") | |
| validation = self.validate_apis() | |
| if validation['foursquare']: | |
| print("✓ Foursquare API: Connected and working") | |
| else: | |
| print("⚠️ Foursquare API: Connection issues or invalid key") | |
| if validation['anthropic']: | |
| print("✓ Anthropic API Key: Configured") | |
| else: | |
| print("⚠️ Anthropic API Key: Not configured") | |
| print("ℹ️ Set environment variable: ANTHROPIC_API_KEY=your_key") | |
| class DynamicCoordinateService: | |
| """Service for dynamically fetching coordinates for locations.""" | |
| def __init__(self): | |
| self.coordinate_cache = {} # Cache for recently fetched coordinates | |
| self.cache_expiry = 3600 # Cache expires after 1 hour | |
| self.foursquare_api_key = os.environ.get('FOURSQUARE_API_KEY') | |
| def get_coordinates(self, location: str) -> Optional[str]: | |
| """ | |
| Get coordinates for a location dynamically using multiple geocoding services. | |
| Raises ValueError if coordinates cannot be found. | |
| """ | |
| location_key = location.lower().strip() | |
| # Check cache first | |
| if location_key in self.coordinate_cache: | |
| cached_data = self.coordinate_cache[location_key] | |
| if time.time() - cached_data['timestamp'] < self.cache_expiry: | |
| return cached_data['coordinates'] | |
| # Try multiple geocoding services in order of preference | |
| coordinates = None | |
| # 1. Try Foursquare API first (most accurate for places) | |
| if self.foursquare_api_key: | |
| coordinates = self._get_coordinates_foursquare(location) | |
| # 2. Fall back to Nominatim (OpenStreetMap) - free but rate limited | |
| if not coordinates: | |
| coordinates = self._get_coordinates_nominatim(location) | |
| # 3. If all services fail, raise an error | |
| if not coordinates: | |
| raise ValueError(f"Could not retrieve coordinates for '{location}'. Please try a more specific location or check the spelling.") | |
| # Cache the successful result | |
| self.coordinate_cache[location_key] = { | |
| 'coordinates': coordinates, | |
| 'timestamp': time.time() | |
| } | |
| return coordinates | |
| def _get_coordinates_foursquare(self, location: str) -> Optional[str]: | |
| """Get coordinates using Foursquare Places API.""" | |
| try: | |
| url = "https://api.foursquare.com/v3/places/search" | |
| headers = { | |
| "accept": "application/json", | |
| "Authorization": self.foursquare_api_key | |
| } | |
| params = { | |
| "query": location, | |
| "limit": 1 | |
| } | |
| response = requests.get(url, headers=headers, params=params, timeout=10) | |
| response.raise_for_status() | |
| data = response.json() | |
| if data.get('results'): | |
| geocode = data['results'][0].get('geocodes', {}).get('main', {}) | |
| if 'latitude' in geocode and 'longitude' in geocode: | |
| lat = geocode['latitude'] | |
| lon = geocode['longitude'] | |
| return f"{lat},{lon}" | |
| except Exception as e: | |
| print(f"Foursquare geocoding failed for '{location}': {e}") | |
| return None | |
| def _get_coordinates_nominatim(self, location: str) -> Optional[str]: | |
| """Get coordinates using Nominatim (OpenStreetMap) geocoding service.""" | |
| try: | |
| # Rate limit: max 1 request per second for Nominatim | |
| time.sleep(1) | |
| encoded_location = quote(location) | |
| url = f"https://nominatim.openstreetmap.org/search" | |
| params = { | |
| 'q': location, | |
| 'format': 'json', | |
| 'limit': 1, | |
| 'addressdetails': 1 | |
| } | |
| headers = { | |
| 'User-Agent': 'MCP-Server/1.0 (Dynamic Coordinate Service)' | |
| } | |
| response = requests.get(url, params=params, headers=headers, timeout=10) | |
| response.raise_for_status() | |
| data = response.json() | |
| if data: | |
| lat = data[0]['lat'] | |
| lon = data[0]['lon'] | |
| return f"{lat},{lon}" | |
| except Exception as e: | |
| print(f"Nominatim geocoding failed for '{location}': {e}") | |
| return None | |
| def get_coordinates_tuple(self, location: str) -> Optional[Tuple[float, float]]: | |
| """Get coordinates as a tuple of (latitude, longitude). Raises ValueError if not found.""" | |
| coords_str = self.get_coordinates(location) | |
| if coords_str: | |
| try: | |
| lat, lon = coords_str.split(',') | |
| return (float(lat), float(lon)) | |
| except (ValueError, IndexError): | |
| raise ValueError(f"Invalid coordinate format for '{location}'") | |
| return None | |
| def clear_cache(self): | |
| """Clear the coordinate cache.""" | |
| self.coordinate_cache.clear() | |
| # Global configuration instance | |
| api_config = APIConfig() | |
| # Dynamic coordinate service instance | |
| coordinate_service = DynamicCoordinateService() | |
| # Legacy function for backward compatibility | |
| def get_city_coordinates(location: str) -> Optional[str]: | |
| """ | |
| Get coordinates for a location dynamically. | |
| This replaces the old static CITY_COORDINATES lookup. | |
| """ | |
| return coordinate_service.get_coordinates(location) | |
| # Backward compatibility: Minimal CITY_COORDINATES for legacy code | |
| # This is deprecated - use coordinate_service.get_coordinates() instead | |
| CITY_COORDINATES = { | |
| # Common US cities for backward compatibility only | |
| 'seattle': '47.6062,-122.3321', | |
| 'portland': '45.5155,-122.6789', | |
| 'san francisco': '37.7749,-122.4194', | |
| 'los angeles': '34.0522,-118.2437', | |
| 'denver': '39.7392,-104.9903', | |
| 'chicago': '41.8781,-87.6298', | |
| 'new york': '40.7128,-74.0060', | |
| 'boston': '42.3601,-71.0589', | |
| 'miami': '25.7617,-80.1918', | |
| 'austin': '30.2672,-97.7431', | |
| 'phoenix': '33.4484,-112.0740', | |
| 'atlanta': '33.7490,-84.3880', | |
| 'nashville': '36.1627,-86.7816', | |
| 'minneapolis': '44.9778,-93.2650', | |
| 'lynnwood': '47.8209,-122.3151' | |
| } | |
| # Note: This static mapping is deprecated. | |
| # For new code, use: coordinate_service.get_coordinates(location) for dynamic lookup | |