search_tuzuk
Search Turkish regulatory statutes (Tüzük) by keywords, phrases, or date ranges to find implementation details for laws. Supports Boolean operators and wildcards for precise queries.
Instructions
Search for Turkish Statutes/Regulations (Tüzük) by title.
Tüzük are regulatory statutes that implement and detail the provisions of laws. They are issued by government agencies and regulatory bodies.
Query Syntax:
Simple keyword: tapu
Exact phrase: "sicil kayıt" (use quotes or set tam_cumle=True)
AND operator: tapu AND sicil (both terms must be present)
OR operator: tescil OR ilan (at least one term must be present)
NOT operator: vakıf NOT kurul (first term present, second must not be)
Wildcard: tescil* (matches tescil, tescile, tescili, etc.)
Combinations: (tapu OR kadastro) AND sicil NOT iptal
Returns:
List of matching statutes with numbers, titles, dates, and metadata
Pagination info and total result count
Each statute includes: mevzuat_no, mev_adi, kabul_tarih, resmi_gazete_tarihi, etc.
Example usage:
search_tuzuk(aranacak_ifade="tapu") → Find land registry related statutes
search_tuzuk(baslangic_tarihi="2008", bitis_tarihi="2013") → List all statutes from 2008-2013
search_tuzuk(aranacak_ifade="vakıf AND tescil") → Find foundation registration statutes
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| aranacak_ifade | No | Search query with Boolean operators and wildcards. Examples: "tapu" (simple), "sicil AND kayıt" (AND), "tescil OR ilan" (OR), "vakıf NOT kurul" (NOT), "tescil*" (wildcard), "medeni kanun" (exact phrase with quotes). Leave empty to list all statutes 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., '2008'). Use with bitis_tarihi to define a date range. | |
| bitis_tarihi | No | End year for filtering results (format: YYYY, e.g., '2013'). 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:1199-1284 (handler)The primary handler for the 'search_tuzuk' tool. Decorated with @app.tool() for MCP registration. Constructs a MevzuatSearchRequestNew with mevzuat_tur='Tuzuk' and invokes the API client to perform the search on mevzuat.gov.tr.@app.tool() async def search_tuzuk( aranacak_ifade: Optional[str] = Field( None, description='Search query with Boolean operators and wildcards. Examples: "tapu" (simple), "sicil AND kayıt" (AND), "tescil OR ilan" (OR), "vakıf NOT kurul" (NOT), "tescil*" (wildcard), "medeni kanun" (exact phrase with quotes). Leave empty to list all statutes 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., '2008'). 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., '2013'). 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 Statutes/Regulations (Tüzük) by title. Tüzük are regulatory statutes that implement and detail the provisions of laws. They are issued by government agencies and regulatory bodies. Query Syntax: - Simple keyword: tapu - Exact phrase: "sicil kayıt" (use quotes or set tam_cumle=True) - AND operator: tapu AND sicil (both terms must be present) - OR operator: tescil OR ilan (at least one term must be present) - NOT operator: vakıf NOT kurul (first term present, second must not be) - Wildcard: tescil* (matches tescil, tescile, tescili, etc.) - Combinations: (tapu OR kadastro) AND sicil NOT iptal Returns: - List of matching statutes with numbers, titles, dates, and metadata - Pagination info and total result count - Each statute includes: mevzuat_no, mev_adi, kabul_tarih, resmi_gazete_tarihi, etc. Example usage: - search_tuzuk(aranacak_ifade="tapu") → Find land registry related statutes - search_tuzuk(baslangic_tarihi="2008", bitis_tarihi="2013") → List all statutes from 2008-2013 - search_tuzuk(aranacak_ifade="vakıf AND tescil") → Find foundation registration statutes """ logger.info(f"Tool 'search_tuzuk' called: '{aranacak_ifade}', dates: {baslangic_tarihi}-{bitis_tarihi}") try: search_req = MevzuatSearchRequestNew( mevzuat_tur="Tuzuk", 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} statutes") return result except Exception as e: logger.exception("Error in tool 'search_tuzuk'") 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:32-85 (schema)Pydantic input schema (MevzuatSearchRequestNew) used by the search_tuzuk handler, including MevzuatTurLiteral which lists 'Tuzuk' as a valid legislation type.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:107-117 (schema)Pydantic output schema (MevzuatSearchResultNew) returned by the search_tuzuk 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_client.py:451-556 (helper)Core helper method MevzuatApiClientNew.search_documents() invoked by the tool handler. Performs HTTP POST to mevzuat.gov.tr DataTables API endpoint, handles authentication via Playwright-obtained antiforgery token/cookies, and parses results into structured models.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}" )