Skip to main content
Glama
barvhaim

Israeli Land Authority MCP Server

by barvhaim
israeli_land_api.py12.8 kB
""" Israeli Land Authority API Client Provides access to רמ״י (Israeli Land Authority) public tender data """ import time from typing import Dict, List, Optional, Any from datetime import datetime, timedelta import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry class IsraeliLandAPI: """Client for accessing Israeli Land Authority public tender data""" BASE_URL = "https://apps.land.gov.il/MichrazimSite/api" REQUIRED_HEADERS = { "User-Agent": "datagov-external-client", "Content-Type": "application/json", "Origin": "https://apps.land.gov.il", "Referer": "https://apps.land.gov.il/MichrazimSite/", } def __init__(self, rate_limit_delay: float = 1.0): """ Initialize the API client Args: rate_limit_delay: Delay between requests in seconds """ self.rate_limit_delay = rate_limit_delay self._last_request_time = 0.0 # Configure session with retries self.session = requests.Session() retry_strategy = Retry( total=3, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504], ) adapter = HTTPAdapter(max_retries=retry_strategy) self.session.mount("http://", adapter) self.session.mount("https://", adapter) self.session.headers.update(self.REQUIRED_HEADERS) def _rate_limit(self): """Implement rate limiting between requests""" current_time = time.time() time_since_last = current_time - self._last_request_time if time_since_last < self.rate_limit_delay: time.sleep(self.rate_limit_delay - time_since_last) self._last_request_time = time.time() def search_tenders( self, tender_number: Optional[str] = None, tender_types: Optional[List[int]] = None, settlement: Optional[str] = None, kod_yeshuv: Optional[int] = None, neighborhood: Optional[str] = None, purpose: Optional[str] = None, region: Optional[str] = None, submission_date_from: Optional[datetime] = None, submission_date_to: Optional[datetime] = None, publication_date_from: Optional[datetime] = None, publication_date_to: Optional[datetime] = None, committee_date_from: Optional[datetime] = None, committee_date_to: Optional[datetime] = None, tender_purposes: Optional[List[int]] = None, regions: Optional[List[int]] = None, tender_statuses: Optional[List[int]] = None, priority_populations: Optional[List[int]] = None, active_only: bool = False, quick_search: bool = False, has_results: Optional[bool] = None, sort_by: Optional[str] = None, sort_order: Optional[str] = None, page_size: int = 100, page_number: int = 1, ) -> Dict[str, Any]: """ Search for land tenders with enhanced filtering capabilities Args: tender_number: Specific tender number to search for (מספר מכרז) tender_types: List of tender type IDs to filter by (סוג המכרז) settlement: Settlement name to filter by (יישוב) kod_yeshuv: Settlement code (Kod Yeshuv) to filter by neighborhood: Neighborhood name to filter by (שכונה) purpose: Land use purpose to filter by (legacy) region: Region to filter by (legacy) submission_date_from: Start date for submission deadline filter submission_date_to: End date for submission deadline filter publication_date_from: Start date for publication filter publication_date_to: End date for publication filter committee_date_from: Start date for committee date filter (ועדת מכרזים) committee_date_to: End date for committee date filter (ועדת מכרזים) tender_purposes: List of tender purpose/designation IDs (ייעוד מכרז) regions: List of Rami region IDs (מרחב ברמ"י) tender_statuses: List of tender status IDs (סטטוס המכרז) priority_populations: List of priority population codes (אוכלוסיות עדיפות) active_only: Only return active tenders quick_search: Use quick search mode has_results: Filter by whether tender has results sort_by: Field to sort by sort_order: Sort order (asc/desc) page_size: Number of results per page (client-side pagination) page_number: Page number to retrieve (client-side pagination) Returns: Dictionary containing search results Note: The Israeli Land Authority API does not support server-side pagination. Pagination is implemented client-side by retrieving all results and then slicing them according to page_size and page_number parameters. """ self._rate_limit() # Build request payload based on website form structure payload = {"ActiveQuickSearch": quick_search, "ActiveMichraz": active_only} # Basic search filters if tender_number: payload["MisMichraz"] = tender_number if tender_types: payload["SugMichraz"] = tender_types # Note: Settlement name is handled by frontend autocomplete, API expects KodYeshuv if kod_yeshuv: payload["KodYeshuv"] = kod_yeshuv elif settlement: # If settlement name provided but no kod_yeshuv, this may not work with API # Users should use kod_yeshuv or convert settlement name to code first payload["Yishuv"] = settlement if neighborhood: payload["Shchuna"] = neighborhood # Enhanced filtering options if tender_purposes: payload["YeudMichraz"] = tender_purposes if regions: payload["Merchav"] = regions if tender_statuses: payload["StatusMichraz"] = tender_statuses if priority_populations: payload["PriorityPopulations"] = priority_populations # Date range filters if submission_date_from or submission_date_to: payload["CloseDate"] = {} if submission_date_from: payload["CloseDate"]["from"] = submission_date_from.strftime("%d/%m/%y") if submission_date_to: payload["CloseDate"]["to"] = submission_date_to.strftime("%d/%m/%y") if committee_date_from or committee_date_to: payload["VaadaDate"] = {} if committee_date_from: payload["VaadaDate"]["from"] = committee_date_from.strftime("%d/%m/%y") if committee_date_to: payload["VaadaDate"]["to"] = committee_date_to.strftime("%d/%m/%y") if publication_date_from or publication_date_to: payload["PirsumDate"] = {} if publication_date_from: payload["PirsumDate"]["from"] = publication_date_from.strftime( "%d/%m/%y" ) if publication_date_to: payload["PirsumDate"]["to"] = publication_date_to.strftime("%d/%m/%y") # Legacy compatibility fallbacks if purpose and not tender_purposes: payload["purpose"] = purpose if region and not regions: payload["region"] = region # Additional search parameters if has_results is not None: payload["hasResults"] = has_results if sort_by: payload["sortBy"] = sort_by if sort_order: payload["sortOrder"] = sort_order # Note: The Israeli Land Authority API doesn't support server-side pagination # pageSize and pageNumber parameters are ignored by the API # We implement client-side pagination instead try: response = self.session.post( f"{self.BASE_URL}/SearchApi/Search", json=payload, timeout=30 ) response.raise_for_status() data = response.json() # Implement client-side pagination since API doesn't support it if isinstance(data, list): # Apply client-side pagination to the results start_idx = (page_number - 1) * page_size end_idx = start_idx + page_size return data[start_idx:end_idx] else: # If it's a dict with results key, paginate those if "results" in data: start_idx = (page_number - 1) * page_size end_idx = start_idx + page_size data["results"] = data["results"][start_idx:end_idx] return data except requests.exceptions.RequestException as e: raise Exception(f"Failed to search tenders: {str(e)}") def get_tender_details(self, michraz_id: int) -> Dict[str, Any]: """ Get detailed information for a specific tender Args: michraz_id: The tender ID to get details for Returns: Dictionary containing tender details """ self._rate_limit() try: response = self.session.get( f"{self.BASE_URL}/MichrazDetailsApi/Get", params={"michrazID": michraz_id}, timeout=30, ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: raise Exception( f"Failed to get tender details for ID {michraz_id}: {str(e)}" ) def get_tender_map_details(self, michraz_id: int) -> Dict[str, Any]: """ Get geographic/mapping data for a tender Args: michraz_id: The tender ID to get map details for Returns: Dictionary containing map details """ self._rate_limit() try: response = self.session.get( f"{self.BASE_URL}/MichrazDetailsApi/GetMichrazMapaDetails", params={"michrazID": michraz_id}, timeout=30, ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: raise Exception( f"Failed to get map details for tender ID {michraz_id}: {str(e)}" ) def get_all_tenders(self) -> List[Dict[str, Any]]: """ Get all available tenders (simplified search) Returns: List of all tenders """ return self.search_tenders(active_only=False, page_size=10000) def get_active_tenders(self) -> List[Dict[str, Any]]: """ Get only active tenders Returns: List of active tenders """ return self.search_tenders(active_only=True, page_size=10000) def get_recent_results(self, days: int = 30) -> List[Dict[str, Any]]: """ Get tenders with results from the last N days Args: days: Number of days to look back Returns: List of tenders with recent results """ date_from = datetime.now() - timedelta(days=days) return self.search_tenders( has_results=True, submission_date_from=date_from, page_size=10000 ) def search_by_location( self, settlement_code: Optional[str] = None, region: Optional[str] = None, neighborhood: Optional[str] = None, purpose: Optional[str] = None, ) -> List[Dict[str, Any]]: """ Search tenders by location Args: settlement_code: Settlement code (Kod Yeshuv) region: Region name neighborhood: Neighborhood name purpose: Purpose of the tender (e.g., "מגרש לבניית בית קרקע") Returns: List of location-specific tenders """ return self.search_tenders( kod_yeshuv=settlement_code, region=region, neighborhood=neighborhood, purpose=purpose, page_size=10000, ) def search_by_type( self, tender_types: Optional[List[int]] = None, purpose: Optional[str] = None ) -> List[Dict[str, Any]]: """ Search tenders by type or purpose Args: tender_types: List of tender type IDs purpose: Land use purpose Returns: List of type-specific tenders """ return self.search_tenders( tender_types=tender_types, purpose=purpose, page_size=10000 )

Implementation Reference

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/barvhaim/remy-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server