add bedesten module
This commit is contained in:
@@ -9,9 +9,14 @@ Bu proje, çeşitli Türk hukuk kaynaklarına (Yargıtay, Danıştay, Emsal Kara
|
||||
🎯 **Temel Özellikler**
|
||||
|
||||
* Çeşitli Türk hukuk veritabanlarına programatik erişim için standart bir MCP arayüzü.
|
||||
* **Kapsamlı Mahkeme Daire/Kurul Filtreleme:** 79 farklı daire/kurul filtreleme seçeneği
|
||||
* **Dual/Triple API Desteği:** Her mahkeme için birden fazla API kaynağı ile maksimum kapsama
|
||||
* Aşağıdaki kurumların kararlarını arama ve getirme yeteneği:
|
||||
* **Yargıtay:** Detaylı kriterlerle karar arama ve karar metinlerini Markdown formatında getirme.
|
||||
* **Danıştay:** Anahtar kelime bazlı ve detaylı kriterlerle karar arama; karar metinlerini Markdown formatında getirme.
|
||||
* **Yargıtay:** Detaylı kriterlerle karar arama ve karar metinlerini Markdown formatında getirme. **Dual API** (Ana + Bedesten) + **52 Daire/Kurul Filtreleme** (Hukuk/Ceza Daireleri, Genel Kurullar)
|
||||
* **Danıştay:** Anahtar kelime bazlı ve detaylı kriterlerle karar arama; karar metinlerini Markdown formatında getirme. **Triple API** (Keyword + Detailed + Bedesten) + **27 Daire/Kurul Filtreleme** (İdari Daireler, Vergi/İdare Kurulları, Askeri Yüksek İdare Mahkemesi)
|
||||
* **Yerel Hukuk Mahkemeleri:** Bedesten API ile yerel hukuk mahkemesi kararlarına erişim
|
||||
* **İstinaf Hukuk Mahkemeleri:** Bedesten API ile istinaf mahkemesi kararlarına erişim
|
||||
* **Kanun Yararına Bozma (KYB):** Bedesten API ile olağanüstü kanun yoluna erişim
|
||||
* **Emsal (UYAP):** Detaylı kriterlerle emsal karar arama ve karar metinlerini Markdown formatında getirme.
|
||||
* **Uyuşmazlık Mahkemesi:** Form tabanlı kriterlerle karar arama ve karar metinlerini (URL ile erişilen) Markdown formatında getirme.
|
||||
* **Anayasa Mahkemesi (Norm Denetimi):** Kapsamlı kriterlerle norm denetimi kararlarını arama; uzun karar metinlerini (5.000 karakterlik) sayfalanmış Markdown formatında getirme.
|
||||
@@ -75,15 +80,33 @@ Bu bölüm, Yargı MCP aracını 5ire gibi Claude Desktop dışındaki MCP istem
|
||||
|
||||
Bu FastMCP sunucusu aşağıdaki temel araçları sunar:
|
||||
|
||||
### **Yargıtay Araçları (Dual API + 52 Daire Filtreleme)**
|
||||
* **Ana API:**
|
||||
* `search_yargitay_detailed(arananKelime, birimYrgKurulDaire, ...)`: Yargıtay kararlarını detaylı kriterlerle arar. **52 daire/kurul seçeneği** (Hukuk/Ceza Daireleri 1-23, Genel Kurullar, Başkanlar Kurulu)
|
||||
* `get_yargitay_document_markdown(id: str)`: Belirli bir Yargıtay kararının metnini Markdown formatında getirir.
|
||||
* **Bedesten API (Alternatif):**
|
||||
* `search_yargitay_bedesten(phrase, birimAdi, ...)`: Bedesten API ile Yargıtay kararlarını arar. **Aynı 52 daire filtreleme**
|
||||
* `get_yargitay_bedesten_document_markdown(documentId: str)`: Bedesten'den karar metni (HTML/PDF → Markdown)
|
||||
|
||||
* **Yargıtay Araçları:**
|
||||
* `search_yargitay_detailed(search_query: YargitayDetailedSearchRequest) -> CompactYargitaySearchResult`: Yargıtay kararlarını detaylı kriterlerle arar.
|
||||
* `get_yargitay_document_markdown(id: str) -> YargitayDocumentMarkdown`: Belirli bir Yargıtay kararının metnini Markdown formatında getirir.
|
||||
### **Danıştay Araçları (Triple API + 27 Daire Filtreleme)**
|
||||
* **Ana API'lar:**
|
||||
* `search_danistay_by_keyword(andKelimeler, orKelimeler, ...)`: Danıştay kararlarını anahtar kelimelerle arar.
|
||||
* `search_danistay_detailed(daire, esasYil, ...)`: Danıştay kararlarını detaylı kriterlerle arar.
|
||||
* `get_danistay_document_markdown(id: str)`: Belirli bir Danıştay kararının metnini Markdown formatında getirir.
|
||||
* **Bedesten API (Alternatif):**
|
||||
* `search_danistay_bedesten(phrase, birimAdi, ...)`: Bedesten API ile Danıştay kararlarını arar. **27 daire/kurul seçeneği** (1-17. Daireler, Vergi/İdare Kurulları, Askeri Mahkemeler)
|
||||
* `get_danistay_bedesten_document_markdown(documentId: str)`: Bedesten'den karar metni
|
||||
|
||||
* **Danıştay Araçları:**
|
||||
* `search_danistay_by_keyword(search_query: DanistayKeywordSearchRequest) -> CompactDanistaySearchResult`: Danıştay kararlarını anahtar kelimelerle arar.
|
||||
* `search_danistay_detailed(search_query: DanistayDetailedSearchRequest) -> CompactDanistaySearchResult`: Danıştay kararlarını detaylı kriterlerle arar.
|
||||
* `get_danistay_document_markdown(id: str) -> DanistayDocumentMarkdown`: Belirli bir Danıştay kararının metnini Markdown formatında getirir.
|
||||
### **Diğer Mahkemeler (Bedesten API)**
|
||||
* **Yerel Hukuk Mahkemeleri:**
|
||||
* `search_yerel_hukuk_bedesten(phrase, pageSize, ...)`: Yerel hukuk mahkemesi kararlarını arar
|
||||
* `get_yerel_hukuk_bedesten_document_markdown(documentId: str)`: Karar metni
|
||||
* **İstinaf Hukuk Mahkemeleri:**
|
||||
* `search_istinaf_hukuk_bedesten(phrase, pageSize, ...)`: İstinaf mahkemesi kararlarını arar
|
||||
* `get_istinaf_hukuk_bedesten_document_markdown(documentId: str)`: Karar metni
|
||||
* **Kanun Yararına Bozma (KYB):**
|
||||
* `search_kyb_bedesten(phrase, pageSize, ...)`: Olağanüstü kanun yolu kararlarını arar
|
||||
* `get_kyb_bedesten_document_markdown(documentId: str)`: Karar metni
|
||||
|
||||
* **Emsal Karar Araçları:**
|
||||
* `search_emsal_detailed_decisions(search_query: EmsalSearchRequest) -> CompactEmsalSearchResult`: Emsal (UYAP) kararlarını detaylı kriterlerle arar.
|
||||
@@ -109,6 +132,27 @@ Bu FastMCP sunucusu aşağıdaki temel araçları sunar:
|
||||
* `get_rekabet_kurumu_document(karar_id: str, page_number: Optional[int] = 1) -> RekabetDocument`: Belirli bir Rekabet Kurumu kararını `karar_id` ile alır. Kararın PDF formatındaki orijinalinden istenen sayfayı ayıklar ve Markdown formatında döndürür.
|
||||
|
||||
|
||||
---
|
||||
|
||||
### **📊 Kapsamlı İstatistikler**
|
||||
- **Toplam Mahkeme/Kurum:** 11 farklı hukuki kurum
|
||||
- **Toplam MCP Tool:** 30+ arama ve belge getirme aracı
|
||||
- **Daire/Kurul Filtreleme:** 79 farklı seçenek (52 Yargıtay + 27 Danıştay)
|
||||
- **API Kaynağı:** Dual/Triple API desteği ile maksimum kapsama
|
||||
- **Tam Türk Adalet Sistemi:** Yerel mahkemelerden en yüksek mahkemelere kadar
|
||||
|
||||
**🏛️ Desteklenen Mahkeme Hiyerarşisi:**
|
||||
```
|
||||
Yerel Mahkemeler → İstinaf → Yargıtay/Danıştay → Anayasa Mahkemesi
|
||||
↓ ↓ ↓ ↓
|
||||
Bedesten API Bedesten API Dual/Triple API Norm+Bireysel API
|
||||
```
|
||||
|
||||
**⚖️ Kapsamlı Daire Filtreleme:**
|
||||
- **Yargıtay:** 52 seçenek (1-23 Hukuk, 1-23 Ceza, Genel Kurullar, Başkanlar Kurulu)
|
||||
- **Danıştay:** 27 seçenek (1-17 Daireler, İdare/Vergi Kurulları, Askeri Mahkemeler)
|
||||
- **Toplam:** 79 farklı mahkeme dairesi/kurulu
|
||||
|
||||
📜 **Lisans**
|
||||
|
||||
Bu proje MIT Lisansı altında lisanslanmıştır. Detaylar için `LICENSE` dosyasına bakınız.
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# bedesten_mcp_module/__init__.py
|
||||
@@ -0,0 +1,183 @@
|
||||
# bedesten_mcp_module/client.py
|
||||
|
||||
import httpx
|
||||
import base64
|
||||
from typing import Optional
|
||||
import logging
|
||||
from markitdown import MarkItDown
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
from .models import (
|
||||
BedestenSearchRequest, BedestenSearchResponse,
|
||||
BedestenDocumentRequest, BedestenDocumentResponse,
|
||||
BedestenDocumentMarkdown, BedestenDocumentRequestData
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class BedestenApiClient:
|
||||
"""
|
||||
API Client for Bedesten (bedesten.adalet.gov.tr) - Alternative legal decision search system.
|
||||
Currently used for Yargıtay decisions, but can be extended for other court types.
|
||||
"""
|
||||
BASE_URL = "https://bedesten.adalet.gov.tr"
|
||||
SEARCH_ENDPOINT = "/emsal-karar/searchDocuments"
|
||||
DOCUMENT_ENDPOINT = "/emsal-karar/getDocumentContent"
|
||||
|
||||
def __init__(self, request_timeout: float = 60.0):
|
||||
self.http_client = httpx.AsyncClient(
|
||||
base_url=self.BASE_URL,
|
||||
headers={
|
||||
"Accept": "*/*",
|
||||
"Accept-Language": "tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7",
|
||||
"AdaletApplicationName": "UyapMevzuat",
|
||||
"Content-Type": "application/json; charset=utf-8",
|
||||
"Origin": "https://mevzuat.adalet.gov.tr",
|
||||
"Referer": "https://mevzuat.adalet.gov.tr/",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Site": "same-site",
|
||||
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"
|
||||
},
|
||||
timeout=request_timeout
|
||||
)
|
||||
|
||||
async def search_documents(self, search_request: BedestenSearchRequest) -> BedestenSearchResponse:
|
||||
"""
|
||||
Search for documents using Bedesten API.
|
||||
Currently supports: YARGITAYKARARI, DANISTAYKARARI, YERELHUKMAHKARARI, etc.
|
||||
"""
|
||||
logger.info(f"BedestenApiClient: Searching documents with phrase: {search_request.data.phrase}")
|
||||
|
||||
try:
|
||||
response = await self.http_client.post(
|
||||
self.SEARCH_ENDPOINT,
|
||||
json=search_request.model_dump()
|
||||
)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
|
||||
# Parse and return the response
|
||||
return BedestenSearchResponse(**response_json)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"BedestenApiClient: HTTP request error during search: {e}")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"BedestenApiClient: Error processing search response: {e}")
|
||||
raise
|
||||
|
||||
async def get_document_as_markdown(self, document_id: str) -> BedestenDocumentMarkdown:
|
||||
"""
|
||||
Get document content and convert to markdown.
|
||||
Handles both HTML (text/html) and PDF (application/pdf) content types.
|
||||
"""
|
||||
logger.info(f"BedestenApiClient: Fetching document for markdown conversion (ID: {document_id})")
|
||||
|
||||
try:
|
||||
# Prepare request
|
||||
doc_request = BedestenDocumentRequest(
|
||||
data=BedestenDocumentRequestData(documentId=document_id)
|
||||
)
|
||||
|
||||
# Get document
|
||||
response = await self.http_client.post(
|
||||
self.DOCUMENT_ENDPOINT,
|
||||
json=doc_request.model_dump()
|
||||
)
|
||||
response.raise_for_status()
|
||||
response_json = response.json()
|
||||
doc_response = BedestenDocumentResponse(**response_json)
|
||||
|
||||
# Decode base64 content
|
||||
content_bytes = base64.b64decode(doc_response.data.content)
|
||||
mime_type = doc_response.data.mimeType
|
||||
|
||||
logger.info(f"BedestenApiClient: Document mime type: {mime_type}")
|
||||
|
||||
# Convert to markdown based on mime type
|
||||
if mime_type == "text/html":
|
||||
html_content = content_bytes.decode('utf-8')
|
||||
markdown_content = self._convert_html_to_markdown(html_content)
|
||||
elif mime_type == "application/pdf":
|
||||
markdown_content = self._convert_pdf_to_markdown(content_bytes)
|
||||
else:
|
||||
logger.warning(f"Unsupported mime type: {mime_type}")
|
||||
markdown_content = f"Unsupported content type: {mime_type}. Unable to convert to markdown."
|
||||
|
||||
return BedestenDocumentMarkdown(
|
||||
documentId=document_id,
|
||||
markdown_content=markdown_content,
|
||||
source_url=f"{self.BASE_URL}/document/{document_id}",
|
||||
mime_type=mime_type
|
||||
)
|
||||
|
||||
except httpx.RequestError as e:
|
||||
logger.error(f"BedestenApiClient: HTTP error fetching document {document_id}: {e}")
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"BedestenApiClient: Error processing document {document_id}: {e}")
|
||||
raise
|
||||
|
||||
def _convert_html_to_markdown(self, html_content: str) -> Optional[str]:
|
||||
"""Convert HTML to Markdown using MarkItDown"""
|
||||
if not html_content:
|
||||
return None
|
||||
|
||||
temp_file_path = None
|
||||
try:
|
||||
md_converter = MarkItDown()
|
||||
|
||||
# Write HTML to temp file
|
||||
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".html", encoding="utf-8") as tmp:
|
||||
tmp.write(html_content)
|
||||
temp_file_path = tmp.name
|
||||
|
||||
# Convert
|
||||
result = md_converter.convert(temp_file_path)
|
||||
markdown_content = result.text_content
|
||||
|
||||
logger.info("Successfully converted HTML to Markdown")
|
||||
return markdown_content
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error converting HTML to Markdown: {e}")
|
||||
return f"Error converting HTML content: {str(e)}"
|
||||
finally:
|
||||
if temp_file_path and os.path.exists(temp_file_path):
|
||||
os.remove(temp_file_path)
|
||||
|
||||
def _convert_pdf_to_markdown(self, pdf_bytes: bytes) -> Optional[str]:
|
||||
"""Convert PDF to Markdown using MarkItDown"""
|
||||
if not pdf_bytes:
|
||||
return None
|
||||
|
||||
temp_file_path = None
|
||||
try:
|
||||
# MarkItDown supports PDF with markitdown[pdf]
|
||||
md_converter = MarkItDown()
|
||||
|
||||
# Write PDF to temp file
|
||||
with tempfile.NamedTemporaryFile(mode="wb", delete=False, suffix=".pdf") as tmp:
|
||||
tmp.write(pdf_bytes)
|
||||
temp_file_path = tmp.name
|
||||
|
||||
# Convert
|
||||
result = md_converter.convert(temp_file_path)
|
||||
markdown_content = result.text_content
|
||||
|
||||
logger.info("Successfully converted PDF to Markdown")
|
||||
return markdown_content
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error converting PDF to Markdown: {e}")
|
||||
return f"Error converting PDF content: {str(e)}. The document may be corrupted or in an unsupported format."
|
||||
finally:
|
||||
if temp_file_path and os.path.exists(temp_file_path):
|
||||
os.remove(temp_file_path)
|
||||
|
||||
async def close_client_session(self):
|
||||
"""Close HTTP client session"""
|
||||
await self.http_client.aclose()
|
||||
logger.info("BedestenApiClient: HTTP client session closed.")
|
||||
@@ -0,0 +1,115 @@
|
||||
# bedesten_mcp_module/models.py
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional, Dict, Any, Literal, Union
|
||||
|
||||
# Import YargitayBirimEnum for chamber filtering
|
||||
from yargitay_mcp_module.models import YargitayBirimEnum
|
||||
|
||||
# Danıştay Chamber/Board Options
|
||||
DanistayBirimEnum = Literal[
|
||||
"", # Empty string for "All" chambers
|
||||
# Main Councils
|
||||
"Büyük Gen.Kur.", # Grand General Assembly
|
||||
"İdare Dava Daireleri Kurulu", # Administrative Cases Chambers Council
|
||||
"Vergi Dava Daireleri Kurulu", # Tax Cases Chambers Council
|
||||
"İçtihatları Birleştirme Kurulu", # Precedents Unification Council
|
||||
"İdari İşler Kurulu", # Administrative Affairs Council
|
||||
"Başkanlar Kurulu", # Presidents Council
|
||||
# Chambers
|
||||
"1. Daire", "2. Daire", "3. Daire", "4. Daire", "5. Daire",
|
||||
"6. Daire", "7. Daire", "8. Daire", "9. Daire", "10. Daire",
|
||||
"11. Daire", "12. Daire", "13. Daire", "14. Daire", "15. Daire",
|
||||
"16. Daire", "17. Daire",
|
||||
# Military High Administrative Court
|
||||
"Askeri Yüksek İdare Mahkemesi",
|
||||
"Askeri Yüksek İdare Mahkemesi Daireler Kurulu",
|
||||
"Askeri Yüksek İdare Mahkemesi Başsavcılığı",
|
||||
"Askeri Yüksek İdare Mahkemesi 1. Daire",
|
||||
"Askeri Yüksek İdare Mahkemesi 2. Daire",
|
||||
"Askeri Yüksek İdare Mahkemesi 3. Daire"
|
||||
]
|
||||
|
||||
# Search Request Models
|
||||
class BedestenSearchData(BaseModel):
|
||||
pageSize: int
|
||||
pageNumber: int
|
||||
itemTypeList: List[str]
|
||||
phrase: str
|
||||
birimAdi: Optional[Union[YargitayBirimEnum, DanistayBirimEnum]] = Field(None, description="""
|
||||
Chamber/Board filter (optional). Available options depend on itemTypeList:
|
||||
|
||||
For YARGITAYKARARI (52 options):
|
||||
- None/null for ALL chambers
|
||||
- 'Hukuk Genel Kurulu', '1. Hukuk Dairesi' through '23. Hukuk Dairesi'
|
||||
- 'Ceza Genel Kurulu', '1. Ceza Dairesi' through '23. Ceza Dairesi'
|
||||
- 'Hukuk Daireleri Başkanlar Kurulu', 'Ceza Daireleri Başkanlar Kurulu'
|
||||
- 'Büyük Genel Kurulu'
|
||||
|
||||
For DANISTAYKARAR (27 options):
|
||||
- None/null for ALL chambers
|
||||
- 'Büyük Gen.Kur.', 'İdare Dava Daireleri Kurulu', 'Vergi Dava Daireleri Kurulu'
|
||||
- '1. Daire' through '17. Daire'
|
||||
- 'İçtihatları Birleştirme Kurulu', 'İdari İşler Kurulu', 'Başkanlar Kurulu'
|
||||
- Military courts: 'Askeri Yüksek İdare Mahkemesi' variants
|
||||
""")
|
||||
sortFields: List[str] = ["KARAR_TARIHI"]
|
||||
sortDirection: str = "desc"
|
||||
|
||||
class BedestenSearchRequest(BaseModel):
|
||||
data: BedestenSearchData
|
||||
applicationName: str = "UyapMevzuat"
|
||||
paging: bool = True
|
||||
|
||||
# Search Response Models
|
||||
class BedestenItemType(BaseModel):
|
||||
name: str
|
||||
description: str
|
||||
|
||||
class BedestenDecisionEntry(BaseModel):
|
||||
documentId: str
|
||||
itemType: BedestenItemType
|
||||
birimId: Optional[str] = None
|
||||
birimAdi: Optional[str]
|
||||
esasNoYil: int
|
||||
esasNoSira: int
|
||||
kararNoYil: int
|
||||
kararNoSira: int
|
||||
kararTuru: Optional[str] = None
|
||||
kararTarihi: str
|
||||
kararTarihiStr: str
|
||||
kesinlesmeDurumu: Optional[str] = None
|
||||
kararNo: str
|
||||
esasNo: str
|
||||
|
||||
class BedestenSearchDataResponse(BaseModel):
|
||||
emsalKararList: List[BedestenDecisionEntry]
|
||||
total: int
|
||||
start: int
|
||||
|
||||
class BedestenSearchResponse(BaseModel):
|
||||
data: BedestenSearchDataResponse
|
||||
metadata: Dict[str, Any]
|
||||
|
||||
# Document Request/Response Models
|
||||
class BedestenDocumentRequestData(BaseModel):
|
||||
documentId: str
|
||||
|
||||
class BedestenDocumentRequest(BaseModel):
|
||||
data: BedestenDocumentRequestData
|
||||
applicationName: str = "UyapMevzuat"
|
||||
|
||||
class BedestenDocumentData(BaseModel):
|
||||
content: str # Base64 encoded HTML or PDF
|
||||
mimeType: str
|
||||
version: int
|
||||
|
||||
class BedestenDocumentResponse(BaseModel):
|
||||
data: BedestenDocumentData
|
||||
metadata: Dict[str, Any]
|
||||
|
||||
class BedestenDocumentMarkdown(BaseModel):
|
||||
documentId: str = Field(..., description="The document ID from Bedesten")
|
||||
markdown_content: Optional[str] = Field(None, description="The decision content converted to Markdown")
|
||||
source_url: str = Field(..., description="The source URL of the document")
|
||||
mime_type: Optional[str] = Field(None, description="Original content type (text/html or application/pdf)")
|
||||
+349
-5
@@ -36,7 +36,13 @@ from fastmcp import FastMCP
|
||||
# --- Module Imports ---
|
||||
from yargitay_mcp_module.client import YargitayOfficialApiClient
|
||||
from yargitay_mcp_module.models import (
|
||||
YargitayDetailedSearchRequest, YargitayDocumentMarkdown, CompactYargitaySearchResult
|
||||
YargitayDetailedSearchRequest, YargitayDocumentMarkdown, CompactYargitaySearchResult,
|
||||
YargitayBirimEnum
|
||||
)
|
||||
from bedesten_mcp_module.client import BedestenApiClient
|
||||
from bedesten_mcp_module.models import (
|
||||
BedestenSearchRequest, BedestenSearchData,
|
||||
BedestenDocumentMarkdown, DanistayBirimEnum
|
||||
)
|
||||
from danistay_mcp_module.client import DanistayApiClient
|
||||
from danistay_mcp_module.models import (
|
||||
@@ -97,6 +103,7 @@ anayasa_norm_client_instance = AnayasaMahkemesiApiClient()
|
||||
anayasa_bireysel_client_instance = AnayasaBireyselBasvuruApiClient()
|
||||
kik_client_instance = KikApiClient()
|
||||
rekabet_client_instance = RekabetKurumuApiClient()
|
||||
bedesten_client_instance = BedestenApiClient()
|
||||
|
||||
|
||||
KARAR_TURU_ADI_TO_GUID_ENUM_MAP = {
|
||||
@@ -120,9 +127,20 @@ async def search_yargitay_detailed(
|
||||
• +"phrase1" +"phrase2" = Multiple required phrases
|
||||
• +"required" -"excluded" = Include and exclude
|
||||
Examples: arsa payı | "arsa payı" | +"arsa payı" +"bozma sebebi" | bozma*"""),
|
||||
birimYrgKurulDaire: str = Field("", description="Yargitay Board Unit (e.g., 'Hukuk Genel Kurulu')."),
|
||||
birimYrgHukukDaire: str = Field("", description="Yargitay Civil Chamber (e.g., '1. Hukuk Dairesi')."),
|
||||
birimYrgCezaDaire: str = Field("", description="Yargitay Criminal Chamber."),
|
||||
birimYrgKurulDaire: YargitayBirimEnum = Field("", description="""
|
||||
Yargıtay chamber/board selection. Available options:
|
||||
• Empty string ('') for ALL chambers
|
||||
• Hukuk Genel Kurulu (Civil General Assembly)
|
||||
• 1. Hukuk Dairesi through 23. Hukuk Dairesi (Civil Chambers 1-23)
|
||||
• Hukuk Daireleri Başkanlar Kurulu (Civil Chambers Presidents Board)
|
||||
• Ceza Genel Kurulu (Criminal General Assembly)
|
||||
• 1. Ceza Dairesi through 23. Ceza Dairesi (Criminal Chambers 1-23)
|
||||
• Ceza Daireleri Başkanlar Kurulu (Criminal Chambers Presidents Board)
|
||||
• Büyük Genel Kurulu (Grand General Assembly)
|
||||
Total: 49 possible values
|
||||
"""),
|
||||
birimYrgHukukDaire: str = Field("", description="Legacy field - use birimYrgKurulDaire instead"),
|
||||
birimYrgCezaDaire: str = Field("", description="Legacy field - use birimYrgKurulDaire instead"),
|
||||
esasYil: str = Field("", description="Case year for 'Esas No'."),
|
||||
esasIlkSiraNo: str = Field("", description="Starting sequence number for 'Esas No'."),
|
||||
esasSonSiraNo: str = Field("", description="Ending sequence number for 'Esas No'."),
|
||||
@@ -756,6 +774,331 @@ async def get_rekabet_kurumu_document(
|
||||
logger.exception(f"Error in tool 'get_rekabet_kurumu_document'. Karar ID: {karar_id}")
|
||||
raise
|
||||
|
||||
# --- MCP Tools for Bedesten (Alternative Yargitay Search) ---
|
||||
@app.tool()
|
||||
async def search_yargitay_bedesten(
|
||||
phrase: str = Field(..., description="Aranacak kavram/kelime"),
|
||||
pageSize: int = Field(10, ge=1, le=100, description="Sayfa başına sonuç sayısı"),
|
||||
pageNumber: int = Field(1, ge=1, description="Sayfa numarası"),
|
||||
birimAdi: Optional[YargitayBirimEnum] = Field(None, description="""
|
||||
Yargıtay chamber/board filter (optional). Available options:
|
||||
• None for ALL chambers
|
||||
• 'Hukuk Genel Kurulu' (Civil General Assembly)
|
||||
• '1. Hukuk Dairesi' through '23. Hukuk Dairesi' (Civil Chambers 1-23)
|
||||
• 'Hukuk Daireleri Başkanlar Kurulu' (Civil Chambers Presidents Board)
|
||||
• 'Ceza Genel Kurulu' (Criminal General Assembly)
|
||||
• '1. Ceza Dairesi' through '23. Ceza Dairesi' (Criminal Chambers 1-23)
|
||||
• 'Ceza Daireleri Başkanlar Kurulu' (Criminal Chambers Presidents Board)
|
||||
• 'Büyük Genel Kurulu' (Grand General Assembly)
|
||||
Total: 49 chamber options
|
||||
""")
|
||||
) -> dict:
|
||||
"""
|
||||
Searches Yargıtay decisions using Bedesten API (alternative source).
|
||||
This complements search_yargitay_detailed for comprehensive coverage.
|
||||
Always use BOTH Yargıtay search tools for complete results.
|
||||
|
||||
Returns a simplified response with decision list and metadata.
|
||||
"""
|
||||
search_data = BedestenSearchData(
|
||||
pageSize=pageSize,
|
||||
pageNumber=pageNumber,
|
||||
itemTypeList=["YARGITAYKARARI"], # Only Yargıtay decisions
|
||||
phrase=phrase,
|
||||
birimAdi=birimAdi
|
||||
)
|
||||
|
||||
search_request = BedestenSearchRequest(data=search_data)
|
||||
|
||||
logger.info(f"Tool 'search_yargitay_bedesten' called: phrase='{phrase}', birimAdi='{birimAdi}', page={pageNumber}")
|
||||
|
||||
try:
|
||||
response = await bedesten_client_instance.search_documents(search_request)
|
||||
|
||||
# Return simplified response format
|
||||
return {
|
||||
"decisions": [d.model_dump() for d in response.data.emsalKararList],
|
||||
"total_records": response.data.total,
|
||||
"requested_page": pageNumber,
|
||||
"page_size": pageSize
|
||||
}
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'search_yargitay_bedesten'")
|
||||
raise
|
||||
|
||||
@app.tool()
|
||||
async def get_yargitay_bedesten_document_markdown(
|
||||
documentId: str = Field(..., description="Document ID from Bedesten search results")
|
||||
) -> BedestenDocumentMarkdown:
|
||||
"""
|
||||
Retrieves a Yargıtay decision document from Bedesten API and converts to Markdown.
|
||||
Supports both HTML and PDF content types.
|
||||
Use documentId from search_yargitay_bedesten results.
|
||||
"""
|
||||
logger.info(f"Tool 'get_yargitay_bedesten_document_markdown' called for ID: {documentId}")
|
||||
|
||||
if not documentId or not documentId.strip():
|
||||
raise ValueError("Document ID must be a non-empty string.")
|
||||
|
||||
try:
|
||||
return await bedesten_client_instance.get_document_as_markdown(documentId)
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'get_yargitay_bedesten_document_markdown'")
|
||||
raise
|
||||
|
||||
# --- MCP Tools for Bedesten (Alternative Danıştay Search) ---
|
||||
@app.tool()
|
||||
async def search_danistay_bedesten(
|
||||
phrase: str = Field(..., description="Aranacak kavram/kelime"),
|
||||
pageSize: int = Field(10, ge=1, le=100, description="Sayfa başına sonuç sayısı"),
|
||||
pageNumber: int = Field(1, ge=1, description="Sayfa numarası"),
|
||||
birimAdi: Optional[DanistayBirimEnum] = Field(None, description="""
|
||||
Danıştay chamber/board filter (optional). Available options:
|
||||
• None for ALL chambers
|
||||
• Main Councils: 'Büyük Gen.Kur.', 'İdare Dava Daireleri Kurulu', 'Vergi Dava Daireleri Kurulu'
|
||||
• Chambers: '1. Daire' through '17. Daire' (17 administrative chambers)
|
||||
• Special Councils: 'İçtihatları Birleştirme Kurulu', 'İdari İşler Kurulu', 'Başkanlar Kurulu'
|
||||
• Military: 'Askeri Yüksek İdare Mahkemesi' and its chambers/councils
|
||||
Total: 27 chamber options
|
||||
""")
|
||||
) -> dict:
|
||||
"""
|
||||
Searches Danıştay decisions using Bedesten API (alternative source).
|
||||
This complements existing Danıştay search tools (search_danistay_by_keyword, search_danistay_detailed)
|
||||
for comprehensive coverage. Always use ALL Danıştay search tools for complete results.
|
||||
|
||||
Returns a simplified response with decision list and metadata.
|
||||
"""
|
||||
search_data = BedestenSearchData(
|
||||
pageSize=pageSize,
|
||||
pageNumber=pageNumber,
|
||||
itemTypeList=["DANISTAYKARAR"], # Only Danıştay decisions
|
||||
phrase=phrase,
|
||||
birimAdi=birimAdi
|
||||
)
|
||||
|
||||
search_request = BedestenSearchRequest(data=search_data)
|
||||
|
||||
logger.info(f"Tool 'search_danistay_bedesten' called: phrase='{phrase}', birimAdi='{birimAdi}', page={pageNumber}")
|
||||
|
||||
try:
|
||||
response = await bedesten_client_instance.search_documents(search_request)
|
||||
|
||||
# Return simplified response format
|
||||
return {
|
||||
"decisions": [d.model_dump() for d in response.data.emsalKararList],
|
||||
"total_records": response.data.total,
|
||||
"requested_page": pageNumber,
|
||||
"page_size": pageSize
|
||||
}
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'search_danistay_bedesten'")
|
||||
raise
|
||||
|
||||
@app.tool()
|
||||
async def get_danistay_bedesten_document_markdown(
|
||||
documentId: str = Field(..., description="Document ID from Bedesten search results")
|
||||
) -> BedestenDocumentMarkdown:
|
||||
"""
|
||||
Retrieves a Danıştay decision document from Bedesten API and converts to Markdown.
|
||||
Supports both HTML and PDF content types.
|
||||
Use documentId from search_danistay_bedesten results.
|
||||
"""
|
||||
logger.info(f"Tool 'get_danistay_bedesten_document_markdown' called for ID: {documentId}")
|
||||
|
||||
if not documentId or not documentId.strip():
|
||||
raise ValueError("Document ID must be a non-empty string.")
|
||||
|
||||
try:
|
||||
return await bedesten_client_instance.get_document_as_markdown(documentId)
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'get_danistay_bedesten_document_markdown'")
|
||||
raise
|
||||
|
||||
# --- MCP Tools for Bedesten (Yerel Hukuk Mahkemesi Search) ---
|
||||
@app.tool()
|
||||
async def search_yerel_hukuk_bedesten(
|
||||
phrase: str = Field(..., description="Aranacak kavram/kelime"),
|
||||
pageSize: int = Field(10, ge=1, le=100, description="Sayfa başına sonuç sayısı"),
|
||||
pageNumber: int = Field(1, ge=1, description="Sayfa numarası")
|
||||
) -> dict:
|
||||
"""
|
||||
Searches Yerel Hukuk Mahkemesi (Local Civil Court) decisions using Bedesten API.
|
||||
This provides access to local court decisions that are not available through other APIs.
|
||||
Currently the only available tool for searching Yerel Hukuk Mahkemesi decisions.
|
||||
|
||||
Returns a simplified response with decision list and metadata.
|
||||
"""
|
||||
search_data = BedestenSearchData(
|
||||
pageSize=pageSize,
|
||||
pageNumber=pageNumber,
|
||||
itemTypeList=["YERELHUKUK"], # Local Civil Court decisions
|
||||
phrase=phrase
|
||||
)
|
||||
|
||||
search_request = BedestenSearchRequest(data=search_data)
|
||||
|
||||
logger.info(f"Tool 'search_yerel_hukuk_bedesten' called: phrase='{phrase}', page={pageNumber}")
|
||||
|
||||
try:
|
||||
response = await bedesten_client_instance.search_documents(search_request)
|
||||
|
||||
# Return simplified response format
|
||||
return {
|
||||
"decisions": [d.model_dump() for d in response.data.emsalKararList],
|
||||
"total_records": response.data.total,
|
||||
"requested_page": pageNumber,
|
||||
"page_size": pageSize
|
||||
}
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'search_yerel_hukuk_bedesten'")
|
||||
raise
|
||||
|
||||
@app.tool()
|
||||
async def get_yerel_hukuk_bedesten_document_markdown(
|
||||
documentId: str = Field(..., description="Document ID from Bedesten search results")
|
||||
) -> BedestenDocumentMarkdown:
|
||||
"""
|
||||
Retrieves a Yerel Hukuk Mahkemesi decision document from Bedesten API and converts to Markdown.
|
||||
Supports both HTML and PDF content types.
|
||||
Use documentId from search_yerel_hukuk_bedesten results.
|
||||
"""
|
||||
logger.info(f"Tool 'get_yerel_hukuk_bedesten_document_markdown' called for ID: {documentId}")
|
||||
|
||||
if not documentId or not documentId.strip():
|
||||
raise ValueError("Document ID must be a non-empty string.")
|
||||
|
||||
try:
|
||||
return await bedesten_client_instance.get_document_as_markdown(documentId)
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'get_yerel_hukuk_bedesten_document_markdown'")
|
||||
raise
|
||||
|
||||
# --- MCP Tools for Bedesten (İstinaf Hukuk Mahkemesi Search) ---
|
||||
@app.tool()
|
||||
async def search_istinaf_hukuk_bedesten(
|
||||
phrase: str = Field(..., description="Aranacak kavram/kelime"),
|
||||
pageSize: int = Field(10, ge=1, le=100, description="Sayfa başına sonuç sayısı"),
|
||||
pageNumber: int = Field(1, ge=1, description="Sayfa numarası")
|
||||
) -> dict:
|
||||
"""
|
||||
Searches İstinaf Hukuk Mahkemesi (Civil Court of Appeals) decisions using Bedesten API.
|
||||
This provides access to appellate court decisions that are not available through other APIs.
|
||||
Currently the only available tool for searching İstinaf Hukuk Mahkemesi decisions.
|
||||
|
||||
İstinaf courts are intermediate appellate courts in the Turkish judicial system,
|
||||
handling appeals from local civil courts before cases reach Yargıtay.
|
||||
|
||||
Returns a simplified response with decision list and metadata.
|
||||
"""
|
||||
search_data = BedestenSearchData(
|
||||
pageSize=pageSize,
|
||||
pageNumber=pageNumber,
|
||||
itemTypeList=["ISTINAFHUKUK"], # Civil Court of Appeals decisions
|
||||
phrase=phrase
|
||||
)
|
||||
|
||||
search_request = BedestenSearchRequest(data=search_data)
|
||||
|
||||
logger.info(f"Tool 'search_istinaf_hukuk_bedesten' called: phrase='{phrase}', page={pageNumber}")
|
||||
|
||||
try:
|
||||
response = await bedesten_client_instance.search_documents(search_request)
|
||||
|
||||
# Return simplified response format
|
||||
return {
|
||||
"decisions": [d.model_dump() for d in response.data.emsalKararList],
|
||||
"total_records": response.data.total,
|
||||
"requested_page": pageNumber,
|
||||
"page_size": pageSize
|
||||
}
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'search_istinaf_hukuk_bedesten'")
|
||||
raise
|
||||
|
||||
@app.tool()
|
||||
async def get_istinaf_hukuk_bedesten_document_markdown(
|
||||
documentId: str = Field(..., description="Document ID from Bedesten search results")
|
||||
) -> BedestenDocumentMarkdown:
|
||||
"""
|
||||
Retrieves an İstinaf Hukuk Mahkemesi decision document from Bedesten API and converts to Markdown.
|
||||
Supports both HTML and PDF content types.
|
||||
Use documentId from search_istinaf_hukuk_bedesten results.
|
||||
"""
|
||||
logger.info(f"Tool 'get_istinaf_hukuk_bedesten_document_markdown' called for ID: {documentId}")
|
||||
|
||||
if not documentId or not documentId.strip():
|
||||
raise ValueError("Document ID must be a non-empty string.")
|
||||
|
||||
try:
|
||||
return await bedesten_client_instance.get_document_as_markdown(documentId)
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'get_istinaf_hukuk_bedesten_document_markdown'")
|
||||
raise
|
||||
|
||||
# --- MCP Tools for Bedesten (Kanun Yararına Bozma Search) ---
|
||||
@app.tool()
|
||||
async def search_kyb_bedesten(
|
||||
phrase: str = Field(..., description="Aranacak kavram/kelime"),
|
||||
pageSize: int = Field(10, ge=1, le=100, description="Sayfa başına sonuç sayısı"),
|
||||
pageNumber: int = Field(1, ge=1, description="Sayfa numarası")
|
||||
) -> dict:
|
||||
"""
|
||||
Searches Kanun Yararına Bozma (KYB - Extraordinary Appeal) decisions using Bedesten API.
|
||||
This provides access to extraordinary appeal decisions that are not available through other APIs.
|
||||
Currently the only available tool for searching KYB decisions.
|
||||
|
||||
KYB decisions are extraordinary appeals in the Turkish judicial system,
|
||||
where the Public Prosecutor's Office can request review of finalized decisions
|
||||
in favor of the law and defendants.
|
||||
|
||||
Returns a simplified response with decision list and metadata.
|
||||
"""
|
||||
search_data = BedestenSearchData(
|
||||
pageSize=pageSize,
|
||||
pageNumber=pageNumber,
|
||||
itemTypeList=["KYB"], # Kanun Yararına Bozma decisions
|
||||
phrase=phrase
|
||||
)
|
||||
|
||||
search_request = BedestenSearchRequest(data=search_data)
|
||||
|
||||
logger.info(f"Tool 'search_kyb_bedesten' called: phrase='{phrase}', page={pageNumber}")
|
||||
|
||||
try:
|
||||
response = await bedesten_client_instance.search_documents(search_request)
|
||||
|
||||
# Return simplified response format
|
||||
return {
|
||||
"decisions": [d.model_dump() for d in response.data.emsalKararList],
|
||||
"total_records": response.data.total,
|
||||
"requested_page": pageNumber,
|
||||
"page_size": pageSize
|
||||
}
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'search_kyb_bedesten'")
|
||||
raise
|
||||
|
||||
@app.tool()
|
||||
async def get_kyb_bedesten_document_markdown(
|
||||
documentId: str = Field(..., description="Document ID from Bedesten search results")
|
||||
) -> BedestenDocumentMarkdown:
|
||||
"""
|
||||
Retrieves a Kanun Yararına Bozma (KYB) decision document from Bedesten API and converts to Markdown.
|
||||
Supports both HTML and PDF content types.
|
||||
Use documentId from search_kyb_bedesten results.
|
||||
"""
|
||||
logger.info(f"Tool 'get_kyb_bedesten_document_markdown' called for ID: {documentId}")
|
||||
|
||||
if not documentId or not documentId.strip():
|
||||
raise ValueError("Document ID must be a non-empty string.")
|
||||
|
||||
try:
|
||||
return await bedesten_client_instance.get_document_as_markdown(documentId)
|
||||
except Exception as e:
|
||||
logger.exception("Error in tool 'get_kyb_bedesten_document_markdown'")
|
||||
raise
|
||||
|
||||
# --- Application Shutdown Handling ---
|
||||
def perform_cleanup():
|
||||
logger.info("MCP Server performing cleanup...")
|
||||
@@ -775,7 +1118,8 @@ def perform_cleanup():
|
||||
globals().get('anayasa_norm_client_instance'),
|
||||
globals().get('anayasa_bireysel_client_instance'),
|
||||
globals().get('kik_client_instance'),
|
||||
globals().get('rekabet_client_instance')
|
||||
globals().get('rekabet_client_instance'),
|
||||
globals().get('bedesten_client_instance')
|
||||
]
|
||||
async def close_all_clients_async():
|
||||
tasks = []
|
||||
|
||||
@@ -1,7 +1,32 @@
|
||||
# yargitay_mcp_module/models.py
|
||||
|
||||
from pydantic import BaseModel, Field, HttpUrl
|
||||
from typing import List, Optional, Dict, Any
|
||||
from typing import List, Optional, Dict, Any, Literal
|
||||
|
||||
# Yargıtay Chamber/Board Options
|
||||
YargitayBirimEnum = Literal[
|
||||
"", # Empty string for "All" chambers
|
||||
# Hukuk (Civil) Chambers
|
||||
"Hukuk Genel Kurulu",
|
||||
"1. Hukuk Dairesi", "2. Hukuk Dairesi", "3. Hukuk Dairesi", "4. Hukuk Dairesi",
|
||||
"5. Hukuk Dairesi", "6. Hukuk Dairesi", "7. Hukuk Dairesi", "8. Hukuk Dairesi",
|
||||
"9. Hukuk Dairesi", "10. Hukuk Dairesi", "11. Hukuk Dairesi", "12. Hukuk Dairesi",
|
||||
"13. Hukuk Dairesi", "14. Hukuk Dairesi", "15. Hukuk Dairesi", "16. Hukuk Dairesi",
|
||||
"17. Hukuk Dairesi", "18. Hukuk Dairesi", "19. Hukuk Dairesi", "20. Hukuk Dairesi",
|
||||
"21. Hukuk Dairesi", "22. Hukuk Dairesi", "23. Hukuk Dairesi",
|
||||
"Hukuk Daireleri Başkanlar Kurulu",
|
||||
# Ceza (Criminal) Chambers
|
||||
"Ceza Genel Kurulu",
|
||||
"1. Ceza Dairesi", "2. Ceza Dairesi", "3. Ceza Dairesi", "4. Ceza Dairesi",
|
||||
"5. Ceza Dairesi", "6. Ceza Dairesi", "7. Ceza Dairesi", "8. Ceza Dairesi",
|
||||
"9. Ceza Dairesi", "10. Ceza Dairesi", "11. Ceza Dairesi", "12. Ceza Dairesi",
|
||||
"13. Ceza Dairesi", "14. Ceza Dairesi", "15. Ceza Dairesi", "16. Ceza Dairesi",
|
||||
"17. Ceza Dairesi", "18. Ceza Dairesi", "19. Ceza Dairesi", "20. Ceza Dairesi",
|
||||
"21. Ceza Dairesi", "22. Ceza Dairesi", "23. Ceza Dairesi",
|
||||
"Ceza Daireleri Başkanlar Kurulu",
|
||||
# General Assembly
|
||||
"Büyük Genel Kurulu"
|
||||
]
|
||||
|
||||
class YargitayDetailedSearchRequest(BaseModel):
|
||||
"""
|
||||
@@ -10,11 +35,17 @@ class YargitayDetailedSearchRequest(BaseModel):
|
||||
Based on the payload provided by the user.
|
||||
"""
|
||||
arananKelime: Optional[str] = Field("", description="Keyword to search for.")
|
||||
# Department/Board selection. Based on user provided payload.
|
||||
# birimYrg* fields seem to be the ones used for filtering.
|
||||
birimYrgKurulDaire: Optional[str] = Field("", description="Yargitay Board Unit (e.g., 'Hukuk Genel Kurulu').")
|
||||
birimYrgHukukDaire: Optional[str] = Field("", description="Yargitay Civil Chamber (e.g., '1. Hukuk Dairesi').")
|
||||
birimYrgCezaDaire: Optional[str] = Field("", description="Yargitay Criminal Chamber.")
|
||||
# Department/Board selection - Complete Yargıtay chamber hierarchy
|
||||
birimYrgKurulDaire: YargitayBirimEnum = Field("", description="""
|
||||
Yargıtay chamber/board selection. Options include:
|
||||
- Empty string ('') for ALL chambers
|
||||
- Civil: 'Hukuk Genel Kurulu', '1. Hukuk Dairesi' through '23. Hukuk Dairesi', 'Hukuk Daireleri Başkanlar Kurulu'
|
||||
- Criminal: 'Ceza Genel Kurulu', '1. Ceza Dairesi' through '23. Ceza Dairesi', 'Ceza Daireleri Başkanlar Kurulu'
|
||||
- General: 'Büyük Genel Kurulu'
|
||||
Total: 49 possible values (including empty string for all chambers)
|
||||
""")
|
||||
birimYrgHukukDaire: Optional[str] = Field("", description="Legacy field - use birimYrgKurulDaire instead")
|
||||
birimYrgCezaDaire: Optional[str] = Field("", description="Legacy field - use birimYrgKurulDaire instead")
|
||||
|
||||
esasYil: Optional[str] = Field("", description="Case year for 'Esas No'.")
|
||||
esasIlkSiraNo: Optional[str] = Field("", description="Starting sequence number for 'Esas No'.")
|
||||
|
||||
Reference in New Issue
Block a user