search_khk
Search Turkish Decree Laws (KHK) by title using keywords, Boolean operators, or date ranges to find legislation enacted between 2010-2018.
Instructions
Search for Turkish Decree Laws (Kanun Hükmünde Kararname / KHK) by title.
Note: KHKs were abolished after the 2017 constitutional referendum. The last KHKs were issued in 2018. However, previously enacted KHKs remain in force unless repealed.
Query Syntax:
Simple keyword: değişiklik
Exact phrase: "sağlık düzenleme" (use quotes or set tam_cumle=True)
AND operator: sağlık AND düzenleme (both terms must be present)
OR operator: bakanlık OR kurum (at least one term must be present)
NOT operator: kanun NOT yürürlük (first term present, second must not be)
Wildcard: değişiklik* (matches değişiklikler, değişikliği, etc.)
Combinations: (sağlık OR eğitim) AND düzenleme NOT yürürlük
Returns:
List of matching KHKs with numbers, titles, dates, and metadata
Pagination info and total result count
Each KHK includes: mevzuat_no, mev_adi, kabul_tarih, resmi_gazete_tarihi, etc.
Example usage:
search_khk(aranacak_ifade="anayasa", baslangic_tarihi="2018") → Find constitutional KHKs from 2018
search_khk(baslangic_tarihi="2010", bitis_tarihi="2018") → List all KHKs from 2010-2018
search_khk(aranacak_ifade="sağlık AND düzenleme") → Find health-related KHKs
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| aranacak_ifade | No | Search query with Boolean operators and wildcards. Examples: "değişiklik" (simple), "sağlık AND düzenleme" (AND), "bakanlık OR kurum" (OR), "kanun NOT yürürlük" (NOT), "değişiklik*" (wildcard), "güvenlik sistemi" (exact phrase with quotes). Leave empty to list all KHKs in date range. | |
| tam_cumle | No | If True, searches for exact phrase match. If False (default), searches for any word match with Boolean operators. | |
| baslangic_tarihi | No | Start year for filtering results (format: YYYY, e.g., '2010'). Use with bitis_tarihi to define a date range. | |
| bitis_tarihi | No | End year for filtering results (format: YYYY, e.g., '2018'). Use with baslangic_tarihi to define a date range. | |
| page_number | No | Page number of results to retrieve (starts from 1) | |
| page_size | No | Number of results per page (1-100, default: 25) |
Implementation Reference
- mevzuat_mcp_server.py:1017-1101 (handler)The main handler function for the 'search_khk' MCP tool. It creates a MevzuatSearchRequestNew with mevzuat_tur='KHK' and calls the client's search_documents method to query the mevzuat.gov.tr API for Decree Laws matching the criteria.async def search_khk( aranacak_ifade: Optional[str] = Field( None, description='Search query with Boolean operators and wildcards. Examples: "değişiklik" (simple), "sağlık AND düzenleme" (AND), "bakanlık OR kurum" (OR), "kanun NOT yürürlük" (NOT), "değişiklik*" (wildcard), "güvenlik sistemi" (exact phrase with quotes). Leave empty to list all KHKs in date range.' ), tam_cumle: bool = Field( False, description="If True, searches for exact phrase match. If False (default), searches for any word match with Boolean operators." ), baslangic_tarihi: Optional[str] = Field( None, description="Start year for filtering results (format: YYYY, e.g., '2010'). Use with bitis_tarihi to define a date range." ), bitis_tarihi: Optional[str] = Field( None, description="End year for filtering results (format: YYYY, e.g., '2018'). Use with baslangic_tarihi to define a date range." ), page_number: int = Field( 1, ge=1, description="Page number of results to retrieve (starts from 1)" ), page_size: int = Field( 25, ge=1, le=100, description="Number of results per page (1-100, default: 25)" ) ) -> MevzuatSearchResultNew: """ Search for Turkish Decree Laws (Kanun Hükmünde Kararname / KHK) by title. Note: KHKs were abolished after the 2017 constitutional referendum. The last KHKs were issued in 2018. However, previously enacted KHKs remain in force unless repealed. Query Syntax: - Simple keyword: değişiklik - Exact phrase: "sağlık düzenleme" (use quotes or set tam_cumle=True) - AND operator: sağlık AND düzenleme (both terms must be present) - OR operator: bakanlık OR kurum (at least one term must be present) - NOT operator: kanun NOT yürürlük (first term present, second must not be) - Wildcard: değişiklik* (matches değişiklikler, değişikliği, etc.) - Combinations: (sağlık OR eğitim) AND düzenleme NOT yürürlük Returns: - List of matching KHKs with numbers, titles, dates, and metadata - Pagination info and total result count - Each KHK includes: mevzuat_no, mev_adi, kabul_tarih, resmi_gazete_tarihi, etc. Example usage: - search_khk(aranacak_ifade="anayasa", baslangic_tarihi="2018") → Find constitutional KHKs from 2018 - search_khk(baslangic_tarihi="2010", bitis_tarihi="2018") → List all KHKs from 2010-2018 - search_khk(aranacak_ifade="sağlık AND düzenleme") → Find health-related KHKs """ logger.info(f"Tool 'search_khk' called: '{aranacak_ifade}', dates: {baslangic_tarihi}-{bitis_tarihi}") try: search_req = MevzuatSearchRequestNew( mevzuat_tur="KHK", aranacak_ifade=aranacak_ifade or "", aranacak_yer=1, # Title search tam_cumle=tam_cumle, mevzuat_no=None, baslangic_tarihi=baslangic_tarihi, bitis_tarihi=bitis_tarihi, page_number=page_number, page_size=page_size ) result = await mevzuat_client.search_documents(search_req) logger.info(f"Found {result.total_results} KHKs") return result except Exception as e: logger.exception("Error in tool 'search_khk'") return MevzuatSearchResultNew( documents=[], total_results=0, current_page=page_number, page_size=page_size, total_pages=0, query_used={"error": str(e)}, error_message=f"An unexpected error occurred: {str(e)}" )
- mevzuat_models.py:107-117 (schema)Output schema (response model) returned by the search_khk tool.class MevzuatSearchResultNew(BaseModel): """Model for search results from mevzuat.gov.tr""" documents: List[MevzuatDocumentNew] total_results: int current_page: int page_size: int total_pages: int query_used: Dict[str, Any] error_message: Optional[str] = None
- mevzuat_models.py:32-84 (schema)Input schema used by search_khk tool, including MevzuatTurLiteral which contains 'KHK'.class MevzuatSearchRequestNew(BaseModel): """Request model for searching legislation on mevzuat.gov.tr""" mevzuat_tur: MevzuatTurLiteral = Field( "Kanun", description="Type of legislation. Currently only 'Kanun' (laws) are fully supported for content extraction." ) aranacak_ifade: Optional[str] = Field( None, description="Search term or phrase to look for in legislation" ) aranacak_yer: int = Field( 3, ge=1, le=3, description="Where to search: 1=Title only, 2=Article titles, 3=Full text (default)" ) tam_cumle: bool = Field( False, description="Exact phrase match (true) or any word match (false, default)" ) mevzuat_no: Optional[str] = Field( None, description="Specific legislation number to search for" ) baslangic_tarihi: Optional[str] = Field( None, description="Start date for filtering (format: DD.MM.YYYY)" ) bitis_tarihi: Optional[str] = Field( None, description="End date for filtering (format: DD.MM.YYYY)" ) page_number: int = Field( 1, ge=1, description="Page number of results" ) page_size: int = Field( 10, ge=1, le=100, description="Number of results per page" )
- mevzuat_models.py:11-22 (schema)Literal type including 'KHK' used in search request schema.MevzuatTurLiteral = Literal[ "Kanun", "KHK", "Tuzuk", "Kurum Yönetmeliği", "Cumhurbaşkanlığı Kararnamesi", "Cumhurbaşkanı Kararı", "CB Yönetmeliği", "CB Genelgesi", "Tebliğ", "Diğer" ]
- mevzuat_client.py:451-555 (helper)Core helper method called by search_khk handler to perform the actual API search on mevzuat.gov.tr.async def search_documents(self, request: MevzuatSearchRequestNew) -> MevzuatSearchResultNew: """Search for legislation documents using httpx with Playwright cookies.""" # Get session/cookies with Playwright first await self._ensure_session() # If session establishment failed, fallback to full Playwright method if not self._antiforgery_token and not self._cookies: logger.warning("Session establishment failed, using full Playwright search method as fallback") return await self.search_documents_with_playwright(request) # Build DataTables compatible payload # Normalize mevzuat type for API mevzuat_tur_api = self._normalize_mevzuat_tur_for_api(request.mevzuat_tur) payload = { "draw": 1, "columns": [ {"data": None, "name": "", "searchable": True, "orderable": False, "search": {"value": "", "regex": False}}, {"data": None, "name": "", "searchable": True, "orderable": False, "search": {"value": "", "regex": False}}, {"data": None, "name": "", "searchable": True, "orderable": False, "search": {"value": "", "regex": False}} ], "order": [], "start": (request.page_number - 1) * request.page_size, "length": request.page_size, "search": {"value": "", "regex": False}, "parameters": { "MevzuatTur": mevzuat_tur_api, "YonetmelikMevzuatTur": "OsmanliKanunu", # Required for all searches "AranacakIfade": request.aranacak_ifade or "", "TamCumle": "true" if request.tam_cumle else "false", "AranacakYer": str(request.aranacak_yer), "MevzuatNo": request.mevzuat_no or "", "KurumId": "0", "AltKurumId": "0", "BaslangicTarihi": request.baslangic_tarihi or "", "BitisTarihi": request.bitis_tarihi or "", "antiforgerytoken": self._antiforgery_token or "" } } try: # Log payload for debugging logger.debug(f"Search payload: {payload}") # Make request with cookies properly response = await self._http_client.post( self.SEARCH_ENDPOINT, json=payload, cookies=self._cookies if self._cookies else None ) # Log response for debugging if response.status_code != 200: logger.error(f"Search API error {response.status_code}: {response.text[:500]}") response.raise_for_status() data = response.json() total_results = data.get("recordsTotal", 0) documents = [] for item in data.get("data", []): doc = MevzuatDocumentNew( mevzuat_no=item.get("mevzuatNo", ""), mev_adi=item.get("mevAdi", ""), kabul_tarih=item.get("kabulTarih", ""), resmi_gazete_tarihi=item.get("resmiGazeteTarihi", ""), resmi_gazete_sayisi=item.get("resmiGazeteSayisi", ""), mevzuat_tertip=item.get("mevzuatTertip", ""), mevzuat_tur=item.get("tur", 1), url=item.get("url", "") ) documents.append(doc) return MevzuatSearchResultNew( documents=documents, total_results=total_results, current_page=request.page_number, page_size=request.page_size, total_pages=(total_results + request.page_size - 1) // request.page_size if request.page_size > 0 else 0, query_used=request.model_dump() ) except httpx.HTTPStatusError as e: logger.error(f"Search request failed: {e.response.status_code}") return MevzuatSearchResultNew( documents=[], total_results=0, current_page=request.page_number, page_size=request.page_size, total_pages=0, query_used=request.model_dump(), error_message=f"API request failed: {e.response.status_code}" ) except Exception as e: logger.exception("Unexpected error during search") return MevzuatSearchResultNew( documents=[], total_results=0, current_page=request.page_number, page_size=request.page_size, total_pages=0, query_used=request.model_dump(), error_message=f"An unexpected error occurred: {e}" )