search_tenders
Access and filter Israeli Land Authority public tender data by tender number, type, location, status, and date ranges for targeted land tender searches.
Instructions
Search for land tenders from the Israeli Land Authority
Enhanced search with comprehensive filtering options including tender types, locations, statuses, date ranges, and priority populations. Supports Hebrew text and backward compatibility.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| args | Yes |
Implementation Reference
- MCP tool handler for 'search_tenders'. Validates input with SearchTendersArgs, processes date ranges, converts settlement names to kod_yeshuv, calls the underlying IsraeliLandAPI.search_tenders method, processes results, and returns structured response with summary.def search_tenders(args: SearchTendersArgs) -> Dict[str, Any]: """ Search for land tenders from the Israeli Land Authority Enhanced search with comprehensive filtering options including tender types, locations, statuses, date ranges, and priority populations. Supports Hebrew text and backward compatibility. """ try: # Handle date range conversion submission_date_from = None submission_date_to = None publication_date_from = None publication_date_to = None # New date range format if args.submission_deadline: if args.submission_deadline.from_date: submission_date_from = datetime.strptime( args.submission_deadline.from_date, "%d/%m/%y" ) if args.submission_deadline.to_date: submission_date_to = datetime.strptime( args.submission_deadline.to_date, "%d/%m/%y" ) if args.publication_date: if args.publication_date.from_date: publication_date_from = datetime.strptime( args.publication_date.from_date, "%d/%m/%y" ) if args.publication_date.to_date: publication_date_to = datetime.strptime( args.publication_date.to_date, "%d/%m/%y" ) # Legacy compatibility for days_back if args.days_back and not submission_date_from: submission_date_from = datetime.now() - timedelta(days=args.days_back) # Handle legacy parameters legacy_purpose = args.purpose legacy_region = args.region # Handle settlement name to kod_yeshuv conversion final_kod_yeshuv = args.kod_yeshuv if args.settlement and not args.kod_yeshuv: # Try to convert settlement name to kod_yeshuv for settlement in KOD_YESHUV_SETTLEMENTS: if settlement.name_hebrew == args.settlement.strip(): final_kod_yeshuv = settlement.kod_yeshuv break # Handle committee date ranges committee_date_from = None committee_date_to = None if args.committee_date: if args.committee_date.from_date: committee_date_from = datetime.strptime( args.committee_date.from_date, "%d/%m/%y" ) if args.committee_date.to_date: committee_date_to = datetime.strptime( args.committee_date.to_date, "%d/%m/%y" ) # Call API with enhanced parameters results = api_client.search_tenders( tender_number=args.tender_number, tender_types=args.tender_types, settlement=( args.settlement if not final_kod_yeshuv else None ), # Only pass if no kod_yeshuv kod_yeshuv=final_kod_yeshuv, neighborhood=args.neighborhood, purpose=legacy_purpose, # Legacy support region=legacy_region, # Legacy support submission_date_from=submission_date_from, submission_date_to=submission_date_to, publication_date_from=publication_date_from, publication_date_to=publication_date_to, committee_date_from=committee_date_from, committee_date_to=committee_date_to, tender_purposes=args.tender_purposes, regions=args.regions, tender_statuses=args.tender_statuses, priority_populations=args.priority_populations, active_only=args.active_only, quick_search=args.quick_search, page_size=min(args.max_results, 1000), ) # Process results if isinstance(results, list): tender_list = results[: args.max_results] else: tender_list = results.get("results", results)[: args.max_results] # Prepare search summary search_summary = { "parameters_used": args.model_dump(exclude_unset=True), "new_features": { "enhanced_date_ranges": bool( args.submission_deadline or args.publication_date ), "priority_populations": bool(args.priority_populations), "multiple_statuses": bool(args.tender_statuses), "multiple_purposes": bool(args.tender_purposes), "multiple_regions": bool(args.regions), }, "settlement_conversion": { "settlement_name_provided": bool(args.settlement), "kod_yeshuv_resolved": ( final_kod_yeshuv if args.settlement and not args.kod_yeshuv else None ), "conversion_successful": bool( args.settlement and not args.kod_yeshuv and final_kod_yeshuv ), }, } return { "success": True, "count": len(tender_list), "tenders": tender_list, "search_summary": search_summary, } except Exception as e: return { "success": False, "error": str(e), "search_parameters": args.model_dump(exclude_unset=True), }
- Pydantic BaseModel defining the input schema/arguments for the search_tenders MCP tool, including filters for tenders, locations, dates, and search controls.class SearchTendersArgs(BaseModel): """Arguments for search_tenders tool""" # Basic search parameters tender_number: Optional[str] = Field( None, description="Specific tender number to search for (מספר מכרז)" ) tender_types: Optional[List[int]] = Field( None, description="List of tender type IDs (סוג המכרז)" ) settlement: Optional[str] = Field( None, description="Settlement name in Hebrew (יישוב)" ) kod_yeshuv: Optional[int] = Field(None, description="Settlement code (Kod Yeshuv)") neighborhood: Optional[str] = Field( None, description="Neighborhood name in Hebrew (שכונה)" ) tender_purposes: Optional[List[int]] = Field( None, description="List of tender purpose/designation IDs (ייעוד מכרז)" ) regions: Optional[List[int]] = Field( None, description='List of Rami region IDs (מרחב ברמ"י)' ) tender_statuses: Optional[List[int]] = Field( None, description="List of tender status IDs (סטטוס המכרז)" ) # Date range filters submission_deadline: Optional[DateRange] = Field( None, description="Submission deadline date range (מועד אחרון להגשת הצעות)" ) committee_date: Optional[DateRange] = Field( None, description="Committee date range (ועדת מכרזים)" ) publication_date: Optional[DateRange] = Field( None, description="Publication date range (פרסום מכרז)" ) # Priority populations priority_populations: Optional[List[int]] = Field( None, description="Priority population codes (אוכלוסיות עדיפות)" ) # Search mode and result controls active_only: bool = Field(False, description="Only return active tenders") quick_search: bool = Field(False, description="Use quick search mode") max_results: int = Field(100, description="Maximum number of results to return") # Legacy compatibility (deprecated) purpose: Optional[str] = Field( None, description="Legacy: Land use purpose (use tender_purposes instead)", deprecated=True, ) region: Optional[str] = Field( None, description="Legacy: Region name (use regions instead)", deprecated=True ) days_back: Optional[int] = Field( None, description="Legacy: Search tenders from last N days (use date ranges instead)", deprecated=True, )
- Underlying API client method called by the MCP handler. Performs HTTP POST to Israeli Land Authority API with constructed payload and implements client-side pagination.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)}")
- src/remy_mcp/server.py:20-21 (registration)Registration of all tools (including search_tenders) via register_tools call in the MCP server creation.register_tools(mcp, api_client) register_resources(mcp)