13 KiB
Constitutional Court (Anayasa Mahkemesi) Implementation - Architecture Analysis
Overview
The Anayasa Mahkemesi module provides comprehensive access to Turkish Constitutional Court decisions through two separate systems:
- Norm Denetimi (Norm Control) - Judicial review of laws
- Bireysel Başvuru (Individual Applications) - Individual constitutional complaints
Both systems have been unified into a single MCP interface (Phase 6 optimization - 361 tokens saved).
Current Architecture
1. Module Structure
anayasa_mcp_module/
├── __init__.py # Empty
├── models.py # Pydantic data models (230 lines)
├── client.py # Norm Denetimi client (356 lines)
├── bireysel_client.py # Bireysel Başvuru client (355 lines)
└── unified_client.py # Unified routing logic (122 lines)
2. API Endpoints
Norm Denetimi API:
- Base:
https://normkararlarbilgibankasi.anayasa.gov.tr - Search: GET
/Ara(with query parameters) - Document: Dynamic URLs from search results
Bireysel Başvuru API:
- Base:
https://kararlarbilgibankasi.anayasa.gov.tr - Search: GET
/Ara?KararBulteni=1(with query parameters for report-style results) - Document: Dynamic paths like
/BB/YYYY/NNNN
3. Current Search Implementation (Keyword-Based)
Norm Denetimi Search Parameters (19 parameters):
- Keyword logic:
keywords_all[],keywords_any[],keywords_exclude[](AND/OR/NOT) - Identifiers: case_number_esas, decision_number_karar
- Dates: first_review_date_start/end, decision_date_start/end, official_gazette_date_start/end
- Structural filters: period, application_type, rapporteur_name, norm_type, review_outcomes, reason_for_final_outcome
- Boolean filters: has_press_release, has_dissenting_opinion, has_different_reasoning
- Other: basis_constitution_article_numbers, attending_members_names
- Pagination: results_per_page (1-10), page_to_fetch, sort_by_criteria
Bireysel Başvuru Search Parameters (simple):
- keywords[] (AND logic only)
- page_to_fetch for pagination
Search Architecture (client.py):
_build_search_query_params_for_aym(): Converts Pydantic model to URL query parameters (tuples list)search_norm_denetimi_decisions(): Makes HTTP GET request with params, parses HTML response- Uses BeautifulSoup to find:
- Decision count: div.bulunankararsayisi (regex: "(\d+)\s*Karar Bulundu")
- Individual decisions: div.birkarar (contains reference number, metadata, keyword count)
- Decision details: Next sibling div.col-sm-12 with table containing norm information
- Returns AnayasaSearchResult with parsed decisions list
4. Document Retrieval (Full Text Conversion)
HTML to Markdown Conversion Process:
- Fetch document from URL
- Parse HTML with BeautifulSoup
- Extract main content:
- Find div#Karar (decision tab) or fallback to div.KararMetni or div.WordSection1
- Remove: scripts, styles, .item.col-sm-12 divs, .modal.fade divs
- Convert to Markdown using MarkItDown with BytesIO stream (no temp files)
- Extract metadata during fetch:
- Esas No./Karar No.: Find bold text in
tags containing "Esas No.:" and "Karar No.:"
- Karar Tarihi: Find bold text containing "Karar tarihi:" or regex "Karar Tarihi\s*:\s*([\d.]+)"
- Resmi Gazete: Find text containing "Resmî Gazete tarih ve sayısı:" or "Resmi Gazete tarih/sayı:"
- Esas No./Karar No.: Find bold text in
Pagination & Chunking:
- Split markdown into 5,000 character chunks
- Calculate: total_pages = ceil(len(markdown) / 5000)
- Return current_page_clamped (max 1, min total_pages)
- Include pagination metadata: current_page, total_pages, is_paginated flag
5. Data Models (models.py - 230 lines)
Norm Denetimi Models:
AnayasaNormDenetimiSearchRequest: 19 search parametersAnayasaReviewedNormInfo: norm_name_or_number, article_number, review_type_and_outcome, outcome_reason, basis_constitution_articles_cited[], postponement_periodAnayasaDecisionSummary: decision_reference_no, decision_page_url, keywords_found_count, application_type_summary, applicant_summary, decision_outcome_summary, decision_date_summary, reviewed_norms[]AnayasaSearchResult: decisions[], total_records_found, retrieved_page_numberAnayasaDocumentMarkdown: source_url, decision_reference_no_from_page, decision_date_from_page, official_gazette_info_from_page, markdown_chunk, current_page, total_pages, is_paginated
Bireysel Başvuru Models:
AnayasaBireyselReportSearchRequest: keywords[], page_to_fetchAnayasaBireyselReportDecisionDetail: hak, mudahale_iddiası, sonuç, giderim (4 fields per right examined)AnayasaBireyselReportDecisionSummary: title, decision_reference_no, decision_page_url, decision_type_summary, decision_making_body, application_date_summary, decision_date_summary, application_subject_summary, details[]AnayasaBireyselReportSearchResult: decisions[], total_records_found, retrieved_page_numberAnayasaBireyselBasvuruDocumentMarkdown: source_url, basvuru_no_from_page, karar_tarihi_from_page, basvuru_tarihi_from_page, karari_veren_birim_from_page, karar_turu_from_page, resmi_gazete_info_from_page, markdown_chunk, current_page, total_pages, is_paginated
Unified Models:
AnayasaUnifiedSearchRequest: decision_type (norm_denetimi|bireysel_basvuru), keywords[], page_to_fetch, results_per_page, + type-specific parametersAnayasaUnifiedSearchResult: decision_type, decisions[] (Dict[str, Any]), total_records_found, retrieved_page_numberAnayasaUnifiedDocumentMarkdown: decision_type, source_url, document_data (Dict), markdown_chunk, current_page, total_pages, is_paginated
6. Unified Client Routing (unified_client.py - 122 lines)
AnayasaUnifiedClient class:
- Maintains instances of both norm_client and bireysel_client
search_unified(): Routes based on decision_type parameter- norm_denetimi: Converts to AnayasaNormDenetimiSearchRequest, calls norm_client.search_norm_denetimi_decisions()
- bireysel_basvuru: Converts to AnayasaBireyselReportSearchRequest, calls bireysel_client.search_bireysel_basvuru_report()
- Returns unified AnayasaUnifiedSearchResult
get_document_unified(): Auto-detects decision type from URL- Checks for "normkararlarbilgibankasi" in netloc or "/ND/" in path → norm_denetimi
- Checks for "kararlarbilgibankasi" in netloc or "/BB/" in path → bireysel_basvuru
- Calls appropriate client, wraps result in unified model
7. MCP Tool Integration (mcp_server_main.py)
Active Tools (2 tools - Phase 6 optimization):
@app.tool(
description="Search Constitutional Court decisions from either Norm Control or Individual Applications",
annotations={"readOnlyHint": True, "openWorldHint": True, "idempotentHint": True}
)
async def search_anayasa_unified(
decision_type: Literal["norm_denetimi", "bireysel_basvuru"],
keywords: List[str],
page_to_fetch: int (1-100),
# Norm Denetimi specific (ignored for bireysel_basvuru)
keywords_all: List[str],
keywords_any: List[str],
decision_type_norm: Literal["ALL", "1", "2", "3"],
application_date_start: str,
application_date_end: str,
# Bireysel Başvuru specific (ignored for norm_denetimi)
decision_start_date: str,
decision_end_date: str,
norm_type: Literal["ALL", "1", "2", ...],
subject_category: str
) -> str (JSON)
@app.tool(
description="Retrieve full text of Constitutional Court decision. Auto-detects decision type from URL",
annotations={"readOnlyHint": True, "openWorldHint": False, "idempotentHint": True}
)
async def get_anayasa_document_unified(
document_url: str,
page_number: int (1-indexed)
) -> str (JSON)
Deactivated Tools (4 tools - Phase 6 optimization, marked with DEACTIVATED):
- search_anayasa_norm_denetimi_decisions
- get_anayasa_norm_denetimi_document_markdown
- search_anayasa_bireysel_basvuru_report
- get_anayasa_bireysel_basvuru_document_markdown
Search Capabilities Analysis
Current Keyword-Based Search Strengths
Norm Denetimi - Rich Structural Filtering:
- Multi-keyword logic with AND/OR/NOT operators
- Case/decision number search (exact matching)
- Date range filtering (review, decision, gazette dates)
- Norm categorization (14 norm types)
- Application type filtering (3 categories)
- Constitutional period selection (1961 vs 1982 constitutions)
- Decision outcome filtering (8 outcome types)
- Reasoning/grounds filtering (30 different grounds)
- Member/rapporteur filtering
- Constitutional articles cited filtering
Bireysel Başvuru - Report Format:
- Simple keyword search
- Rights/claims detailed in structured table format
- Remedy/solution tracking
Limitations of Current Keyword Search
- No semantic understanding: Different words for same concept ("mülkiyet hakkı" vs "property rights")
- No concept hierarchy: Can't find related legal principles
- No cross-language: Turkish-only, no English queries
- No abbreviation matching: "HADD" vs "Hukuk Alanında Değerli Dosya Denetimi"
- No synonym support: Formal vs informal terminology
- No semantic similarity: Can't find similar cases with different terminology
- No legal concept graph: Can't traverse related principles or doctrines
- No fuzzy matching: Typos or spelling variations fail completely
- No legal reasoning search: Can't query by legal arguments or doctrinal approaches
- No cross-system semantic linking: Norm Denetimi and Bireysel Başvuru not semantically linked
- Order dependency: Query order may affect results
- No ranking by relevance: Just keyword presence/absence
- No query expansion: No automatic synonym/related term expansion
HTML Document Structure
Norm Denetimi Search Results HTML:
div.birkarar (repeated for each decision)
├── div.bkararbaslik (header with E./K. numbers)
│ └── div.BulunanKelimeSayisi (keyword count)
└── div.kararbilgileri (metadata with | separators: application_type|applicant|outcome|date)
Next sibling:
div.col-sm-12
└── table.table > tbody > tr (one row per reviewed norm with 6 columns)
├── td: norm name/number
├── td: article number
├── td: review type and outcome
├── td: outcome reason
├── td: constitutional articles cited (comma-separated)
└── td: postponement period
Full Decision Content (both types):
div#Karar (decision tab)
└── div.KararMetni or div.WordSection1
└── HTML content in MS Word format (many nested divs with styles)
Metadata extracted from:
<p><b>Esas No.:</b> [number]</p>
<p><b>Karar No.:</b> [number]</p>
<p><b>Karar tarihi:</b> [date]</p>
<p>Resmî Gazete tarih ve sayısı: [info]</p>
Document Content Characteristics
- Language: Turkish legal language (specialized terminology)
- Format: Microsoft Word-generated HTML (nested divs, complex styles)
- Content types:
- Norm Denetimi: Constitutional principle analysis, legal reasoning, comparison with challenged norm
- Bireysel Başvuru: Right violated, remedy granted, procedural requirements
- Typical length: 5,000-50,000+ characters
- Citations: Internal cross-references to constitutional articles
- Structure: Formal legal document with sections, subsections, reasoning
Key Technical Insights for Semantic Search
Content Encoding
- Currently: HTML → BeautifulSoup parsing → MarkItDown → Markdown
- Extraction: Specific div/class/id selectors
- Metadata: Regex patterns and text parsing
Search Query Flow
- User provides keywords/filters
- Convert Pydantic model to URL query parameters
- HTTP GET request to Constitutional Court API
- HTML response parsed with BeautifulSoup
- Decision summaries extracted and validated
- Results returned as JSON
Document Retrieval Flow
- Get document URL from search results
- HTTP GET request to URL
- Parse HTML for metadata extraction
- MarkItDown converts HTML to Markdown
- Chunk by 5,000 characters
- Return paginated Markdown with metadata
Performance Baseline
- Search: ~1-5 seconds (HTML parsing + regex extraction)
- Document: ~2-10 seconds (fetch + parse + MarkItDown + chunking)
- Memory: Minimal (5,000 char chunks, no full document in memory)
- API Response Size: Typically 50-500 KB HTML for search, 100-1000 KB for full decision
Next Steps for Semantic Search Integration
- Vector Embeddings: Embed decisions using Turkish legal model
- Concept Extraction: Identify and tag legal concepts (rights, procedures, principles)
- Semantic Queries: Convert natural language questions to embeddings
- Hybrid Search: Combine keyword + semantic similarity
- Legal Ontology: Map Turkish Constitutional Court concepts and relationships
- Cross-system Linking: Semantically link Norm Denetimi and Bireysel Başvuru decisions
- Precedent Graph: Extract citations and create legal precedent relationships
- Fine-tuned Embeddings: Train embeddings specifically on Turkish Constitutional law
- Ranking: Re-rank results by semantic relevance to user's legal intent
- Explanation: Provide semantic reasoning for why result is relevant