search_kanun
Search Turkish laws by title and content using Boolean operators, date filters, and exact phrase matching to find relevant legislation with publication details and links.
Instructions
Search for Turkish laws (Kanun) in both titles and content.
This tool searches in law titles and full text content. Use 'search_within_kanun' to search within a specific law's articles and get article-level results.
Query Syntax:
Simple keyword: yatırımcı
Boolean AND: yatırımcı AND tazmin (both terms)
Boolean OR: yatırımcı OR müşteri (at least one term)
Boolean NOT: yatırımcı NOT kurum (first yes, second no)
Required term: +yatırımcı +tazmin (similar to AND)
Grouping: (yatırımcı OR müşteri) AND tazmin
Exact phrase: "mali sıkıntı" (or use tam_cumle=true)
Returns:
Law number, title, and acceptance date
Official Gazette publication date and issue number
URLs for viewing online and downloading PDF
Example queries:
"sermaye piyasası" - Find Capital Markets Law
"vergi OR gelir" - Laws with tax or income in title/content
"ceza muhakemesi" - Find Criminal Procedure Law
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| aranacak_ifade | Yes | Search query with optional Boolean operators: simple word (yatırımcı), AND (yatırımcı AND tazmin), OR (vergi OR ücret), NOT (yatırımcı NOT kurum), + for required (+term), grouping with (), exact phrase with quotes ("mali sıkıntı") | |
| tam_cumle | No | Exact phrase match (true) or any word match (false, default). Set to true when searching for exact phrases like 'mali sıkıntı'. | |
| baslangic_tarihi | No | Start date for filtering results (format: DD.MM.YYYY, e.g., '01.01.2020') | |
| bitis_tarihi | No | End date for filtering results (format: DD.MM.YYYY, e.g., '31.12.2024') | |
| page_number | No | Page number for pagination (starts at 1) | |
| page_size | No | Number of results per page (1-100) |
Implementation Reference
- mevzuat_mcp_server.py:39-128 (handler)Main handler function for 'search_kanun' tool. Decorated with @app.tool() for registration in FastMCP server. Validates input params, creates MevzuatSearchRequestNew with type 'Kanun', calls MevzuatApiClientNew.search_documents(), handles errors, and returns MevzuatSearchResultNew.@app.tool() async def search_kanun( aranacak_ifade: str = Field( ..., description='Search query with optional Boolean operators: simple word (yatırımcı), AND (yatırımcı AND tazmin), OR (vergi OR ücret), NOT (yatırımcı NOT kurum), + for required (+term), grouping with (), exact phrase with quotes ("mali sıkıntı")' ), tam_cumle: bool = Field( False, description="Exact phrase match (true) or any word match (false, default). Set to true when searching for exact phrases like 'mali sıkıntı'." ), baslangic_tarihi: Optional[str] = Field( None, description="Start date for filtering results (format: DD.MM.YYYY, e.g., '01.01.2020')" ), bitis_tarihi: Optional[str] = Field( None, description="End date for filtering results (format: DD.MM.YYYY, e.g., '31.12.2024')" ), page_number: int = Field( 1, ge=1, description="Page number for pagination (starts at 1)" ), page_size: int = Field( 25, ge=1, le=100, description="Number of results per page (1-100)" ) ) -> MevzuatSearchResultNew: """ Search for Turkish laws (Kanun) in both titles and content. This tool searches in law titles and full text content. Use 'search_within_kanun' to search within a specific law's articles and get article-level results. Query Syntax: - Simple keyword: yatırımcı - Boolean AND: yatırımcı AND tazmin (both terms) - Boolean OR: yatırımcı OR müşteri (at least one term) - Boolean NOT: yatırımcı NOT kurum (first yes, second no) - Required term: +yatırımcı +tazmin (similar to AND) - Grouping: (yatırımcı OR müşteri) AND tazmin - Exact phrase: "mali sıkıntı" (or use tam_cumle=true) Returns: - Law number, title, and acceptance date - Official Gazette publication date and issue number - URLs for viewing online and downloading PDF Example queries: - "sermaye piyasası" - Find Capital Markets Law - "vergi OR gelir" - Laws with tax or income in title/content - "ceza muhakemesi" - Find Criminal Procedure Law """ search_req = MevzuatSearchRequestNew( mevzuat_tur="Kanun", aranacak_ifade=aranacak_ifade, aranacak_yer=1, # 1=Title only tam_cumle=tam_cumle, mevzuat_no=None, baslangic_tarihi=baslangic_tarihi, bitis_tarihi=bitis_tarihi, page_number=page_number, page_size=page_size ) log_params = search_req.model_dump(exclude_defaults=True) logger.info(f"Tool 'search_kanun' called with parameters: {log_params}") try: result = await mevzuat_client.search_documents(search_req) if not result.documents and not result.error_message: result.error_message = "No legislation found matching the specified criteria." return result except Exception as e: logger.exception("Error in tool 'search_mevzuat'") return MevzuatSearchResultNew( documents=[], total_results=0, current_page=page_number, page_size=page_size, total_pages=0, query_used=log_params, error_message=f"An unexpected error occurred: {str(e)}" )
- mevzuat_models.py:107-117 (schema)Output schema for the tool: MevzuatSearchResultNew pydantic model defining the structure of search results including list of documents, pagination info, used query, and optional error.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 model used internally: MevzuatSearchRequestNew defines parameters for API search requests, including legislation type (set to 'Kanun'), search expression, search location, exact match flag, dates, and pagination.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_client.py:451-556 (helper)Core helper method in MevzuatApiClientNew that performs the actual API search on mevzuat.gov.tr using DataTables endpoint. Handles session, payload construction (including 'YonetmelikMevzuatTur': 'OsmanliKanunu'), response parsing, and returns structured results.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}" )
- mevzuat_models.py:86-106 (schema)Schema for individual search result documents: MevzuatDocumentNew includes metadata like number, title, dates, URLs, and utility methods for PDF/web links.class MevzuatDocumentNew(BaseModel): """Model for a single legislation document from mevzuat.gov.tr""" mevzuat_no: str = Field(..., description="Legislation number") mev_adi: str = Field(..., description="Legislation title/name") kabul_tarih: Optional[str] = Field(None, description="Acceptance date") resmi_gazete_tarihi: Optional[str] = Field(None, description="Official Gazette publication date") resmi_gazete_sayisi: Optional[str] = Field(None, description="Official Gazette issue number") mevzuat_tertip: str = Field(..., description="Legislation series/order") mevzuat_tur: int = Field(..., description="Legislation type code") url: str = Field(..., description="Relative URL to view the legislation") def get_pdf_url(self) -> str: """Generate PDF download URL for this legislation (only works for Kanun).""" return f"https://www.mevzuat.gov.tr/MevzuatMetin/{self.mevzuat_tur}.{self.mevzuat_tertip}.{self.mevzuat_no}.pdf" def get_web_url(self) -> str: """Generate web page URL for this legislation.""" return f"https://www.mevzuat.gov.tr/{self.url}"