Emsal
PYPI · EMSAL-MCP
Citation-safe Turkish legal research: court decisions and legislation from official sources.
Available components
Last scanned (2 hours ago)
Scores higher than 60% of PyPI servers
Deprecated
This server is marked deprecated in the MCP registry.
The registry records this reason: Renamed to io.github.afsozer/dayanak (PyPI: dayanak).
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security50
- Malware scan not yet available for this package.Unverified
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs setuptools.build_meta at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 3 of 40 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency74
- Repository check failed: the declared repository URL redirects; it must resolve directly. See how to fix → View diagnostics → Fail
- Cryptographically verified build provenance (signed, bound to afsozer/emsal-mcp). View diagnostics → Pass
- Clear OSI-approved license (AGPL-3.0-only).Pass
- Actively maintained (last published 14 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability49
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 4880 tokens (~443/item across 11 items; 11 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management33
- Stability observed for 10 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
- Structured output schemas are declared (9% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 11 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 11 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 23 Oct 26 −13
- Malware scan: pass → unverified ▼ security
- Security disclosure: unverified → pass ▲ functional
- 22 Oct 26 +18
- Malware scan: unverified → pass ▲ security
- Security disclosure: pass → unverified ▼ functional
- Stability: unverified → 0.27 ▲ functional
- 18 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- 17 Oct 26 +15
- Malware scan: unverified → pass ▲ security
- 15 Oct 26 −15
- Malware scan: pass → unverified ▼ security
- 14 Oct 26 +24
- Injection markers: unverified → pass ▲ security
- First check of Judged manipulation: pass security
- Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window). security
- Tool coverage: unverified → 100 ▲ functional
- MCP protocol: unverified → pass ▲ functional
- First check of Tool coverage: 0 functional
- First check of Schema quality: fail functional
- First check of Destructive annotations: pass functional
- First check of Schema quality: fail functional
- First check of Schema quality: good functional
- First check of Tool coverage: 9 functional
- 13 Oct 26 +11
- Known CVEs: unverified → pass ▲ security
- Dependency health: unverified → 0.97 ▲ functional
- 12 Oct 26 34
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 24 Oct 2026 · Analysed pypi/emsal-mcp@1.1.1
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | afsozer/emsal-mcp |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/afsozer/emsal-mcp/.github/workflows/publish.yml@refs/tags/v1.1.1 |
| Rekor log index | 3133271951 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:5fe5dea9ec4f6ad1ccccaa6fc87a51dff37e1018fb8d107a37ab31c3755f9532 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | allowlisted | setuptools.build_meta |
Background: Why install scripts are a supply-chain risk →
Dependencies 40 packages
| Packages resolved | 40 |
|---|---|
| Stale | 3 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
export_document ~377
Unified document export: DOCX, UDF, PDF, plain text, or bundle. Args: format: 'docx' (default), 'udf', 'pdf', 'plain', 'bundle', or 'capabilities' (returns supported formats). draft_path: Path to draft.md (for docx/plain). draft_json: Draft metadata dict (for docx). text: Text to write (for udf; plain text — petition formatting such as bold title/labels/headings is applied automatically). out_path: Output file path (for docx/udf/plain). out_dir: Output directory (for bundle). pack_dir: Pack directory (for bundle). draft_dir: Draft output directory (for bundle). docx_path: Path to a .docx (for bundle; for udf this is the PREFERRED input — converts DOCX directly to UDF preserving bold, alignment, indent and line spacing). udf_path: Path to a .udf — converts it to docx or pdf via LibreOffice (replaces convert_udf_to_docx/pdf). title_centered: Center the title in UDF output. title: Document title (for legacy export_bundle). body: Document body (for legacy export_bundle). documents: List of document dicts (for legacy export_bundle).
| Name | Type | Req | Description |
|---|---|---|---|
| body | – | – | – |
| documents | – | – | – |
| docx_path | – | – | – |
| draft_dir | – | – | – |
| draft_json | – | – | – |
| draft_path | – | – | – |
| format | string | – | – |
| out_dir | – | – | – |
| out_path | – | – | – |
| pack_dir | – | – | – |
| text | – | – | – |
| title | – | – | – |
| title_centered | boolean | – | – |
| udf_path | – | – | – |
No output schema declared.
No examples provided.
get_document ~254
Fetch a single document by ID from the given source. Args: source: Source identifier. document_id: Document ID (must not be empty). include_raw: If True, include the raw upstream response in the output (debugging). Default: False (deduplicated output with single markdown text field). page_number: 1-indexed page number for long documents (>= 40 000 chars). Default 1 returns the first page. Long documents are split at paragraph boundaries so no page starts or ends mid-paragraph. Returns: Document dict with deduplicated metadata and content fields. Text is served as a single ``markdown`` field; ``full_text``, ``raw``, and ``metadata.content`` are omitted by default. For long documents (>= 40 000 chars), the response includes ``current_page``, ``total_pages``, and ``total_chars`` so the agent can request subsequent pages via ``page_number``.
| Name | Type | Req | Description |
|---|---|---|---|
| document_id | string | yes | – |
| include_raw | boolean | – | – |
| page_number | integer | – | – |
| source | string | yes | – |
No output schema declared.
No examples provided.
get_legislation ~150
Get legislation content from the Mevzuat source. Args: document_id: Mevzuat document ID. source: Source ID (default: "mevzuat"). part: 'document' (default, full text), 'article_tree' the part/section/article tree, 'gerekce' the rationale. page_number: page of part='document' (40 000 chars/page). Returns: Dict for the requested part; 'document' also carries current_page/total_pages/total_chars.
| Name | Type | Req | Description |
|---|---|---|---|
| document_id | string | yes | – |
| page_number | integer | – | – |
| part | string | – | – |
| source | – | – | – |
No output schema declared.
No examples provided.
health_check ~95
Run a consolidated health check across sources, breakers, indexes and cron jobs. Returns overall status plus source smoke summary, circuit breaker states, search index status and ``scheduled_jobs`` — the last run of the daily crawl, weekly legislation update, monthly merge and the legislation semantic index (read from their log files). ``overall`` is "degraded" when a job is late or ended with rc != 0.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
load_extended_tools ~349
Load extra tool categories into the running MCP server (no restart). Core profile registers 11 tools. Everything else waits here; load a category when the task needs it. Categories: drafting — citation_check (atif dogrula/bicimlendir/guvenlik), prepare_petition (dilekce input_pack/outline/taslak) files — read_legal_file (UDF/PDF dosyasi oku) meta — list_sources (kaynaklar, birim kodlari, mevzuat turleri), legal_research_guide (arama/Solr/daire/atif rehberi) legislation — mevzuat_degisiklik_raporu (haftalik mevzuat degisimi) drafting_advanced — coklu-mesele paketi, sablonlar, argüman zinciri, draft_document, export_bundle chambers — daire profili, timeline, benzer daire privacy — PII tarama/maskeleme/denetim watch — arastirma izleme listeleri indexing — index_status (semantik indeks durumu) health_admin — circuit breaker, kaynak sagligi/smoke udf_admin — UDF/PDF araci durumu, PDF tam metne yukseltme Args: categories: List of category names, e.g. ["drafting", "files"]. Returns: Dict with ok, loaded tools, already_loaded, invalid_categories, and a note if the MCP client may need to refresh its tool list.
| Name | Type | Req | Description |
|---|---|---|---|
| categories | array | yes | – |
No output schema declared.
No examples provided.
mevzuat_korpus_ara ~188
YEREL korpusta MADDE bazında arama (çevrimdışı, madde metinlerinde). mode: "hybrid" (varsayılan; BM25+anlam RRF), "lexical" (FTS5, kelime AND), "semantic" (ifade metinde geçmese de bulur). 0 sonuç "hüküm yok" DEMEK DEĞİL: korpus yalnız çekilmişi içerir, search_legislation çağır. mevzuat_no tek mevzuatla sınırlar (ör. "6098"). Sonuç: mevzuat_adi, madde_no, baslik, snippet, kaynak_url.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | – |
| mevzuat_no | string | – | – |
| mode | string | – | – |
| query | string | yes | – |
No output schema declared.
No examples provided.
mevzuat_madde_getir ~93
Yerel korpustan tek maddenin TAM metni (çevrimdışı). madde_no "390", "12/A", "Geçici 1" kabul eder. Korpusta yoksa NOT_FOUND döner — uydurma, canlı get_legislation çağır.
| Name | Type | Req | Description |
|---|---|---|---|
| madde_no | string | yes | – |
| mevzuat_no | string | yes | – |
No output schema declared.
No examples provided.
research_topic ~83
Search sources, fetch documents, and build a research bundle. Returns bundle metadata with query, sources, result_count, fetched_count, content_status_summary, citation_safe_count, generated_files, warnings, and recommended_next_steps.
| Name | Type | Req | Description |
|---|---|---|---|
| fetch_count | integer | – | – |
| filters | – | – | – |
| output_dir | – | – | – |
| query | string | yes | – |
| sources | – | – | – |
No output schema declared.
No examples provided.
search_decisions ~2,400
✅ PRIMARY, MANDATORY TOOL FOR ALL CASE-LAW / DECISION / MEVZUAT RESEARCH. For ANY question about court decisions, precedents, case law, or legislation you MUST call THIS tool first. It is the ONLY tool that retrieves real, current documents LIVE from the official source (online — e.g. Bedesten/Yargıtay, Mevzuat). HARD RULES — no exceptions, no interpretation: - Do NOT answer case-law questions from memory, training data, or web search. - Do NOT use search_local_corpus to FIND decisions — it searches ONLY the local corpus and cannot discover anything not fetched here first. - Every esas/karar number, date, and chamber you cite MUST come from a document returned by THIS tool and verified via get_document full text. - If you have not called this tool yet, you have NO case law to cite. --- QUERY HYGIENE (CRITICAL) --- - Do NOT paste the user's question in. Solr matches tokens, not natural language. Reduce it to 2–5 legal keywords: "işçi alacağı zamanaşımı" ✓, not "işçinin fazla mesai ve kıdem tazminatı konusunda zamanaşımı süresi". - Preserve Turkish diacritics exactly; stripping them silently drops matches. "kararı" ✓ not "karari" ✗. --- BEDESTEN SOLR OPERATOR COOKBOOK --- ⚠️ THE DEFAULT OPERATOR IS OR — whitespace between bare terms means UNION. `tahliye taahhüdü geçerlilik` matches ANY of the three words. To require all, prefix each with `+` or join with UPPERCASE `AND`. +required must appear (+tazminat) -excluded must not (-bölge) "exact" phrase ("iş kazası") AND/OR/NOT UPPERCASE only (grouping) sub-expressions ⚠️ CHARACTER WHITELIST (measured live): Bedesten accepts ONLY letters, digits, spaces and the operators above. Wildcards (* ?), fuzzy (~), boost (^) and ANY punctuation (/ . , ' : ; _ …) are rejected outright with INVALID_QUERY — there is NO wildcard search, write the full word. Article numbers: `"83 a"` not `83/a` (the index stores 83/a as the two tokens 83 and a). The tool strips/converts such characters before sending (`83/a…
| Name | Type | Req | Description |
|---|---|---|---|
| birimAdi | – | – | – |
| court_types | – | – | – |
| dil | – | – | – |
| esas_no | – | – | – |
| include_raw | boolean | – | – |
| include_snippets | boolean | – | – |
| karar_no | – | – | – |
| karar_tarihi_end | – | – | – |
| karar_tarihi_start | – | – | – |
| limit | integer | – | – |
| page | integer | – | – |
| query | – | – | – |
| sort_by | – | – | – |
| source | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | – | yes | – |
No examples provided.
search_legislation ~394
Search legislation via the Mevzuat source. Use ``mevzuat_adi`` to search ONLY in titles (e.g. "kişisel veri" → KVKK surfaces). Use ``mevzuat_no`` for direct lookup by official number (e.g. "6698" → KVKK, "5237" → TCK) — never guess the number; if unsure use ``mevzuat_adi`` first. ``query`` does a body-text/concept search. Common abbreviations (TCK, HMK, KVKK, ...) in ``query`` are auto-routed to ``mevzuat_no``. Args: query: Search phrase (body-text). Auto-routes TCK/HMK/etc → number. sources: Source IDs (default: ["mevzuat"]). legislation_type: Filter by type (e.g. "Kanun", "Yönetmelik"). limit: Max results. scope: 'law' (default) or 'article'. document_id: Required when scope='article'. sort_by: "relevance" (default) | "date" | "kayit_tarihi". mevzuat_adi: Title-only search. mevzuat_no: Official legislation number (NEVER guess). mevzuat_tur_list: Multi-type filter (KANUN, KHK, YONETMELIK, ...). Returns: Dict with ok, query, results, total_results, warnings, etc.
| Name | Type | Req | Description |
|---|---|---|---|
| document_id | – | – | – |
| legislation_type | – | – | – |
| limit | integer | – | – |
| mevzuat_adi | – | – | – |
| mevzuat_no | – | – | – |
| mevzuat_tur_list | – | – | – |
| query | string | yes | – |
| scope | string | – | – |
| sort_by | – | – | – |
| sources | – | – | – |
No output schema declared.
No examples provided.
search_local_corpus ~497
Concept DISCOVERY over the local corpus. Searches the local corpus (decisions already fetched this session or via the corpus crawl) for a legal CONCEPT when the exact wording is unknown. Each result carries ``related_quotes`` — matched passages — so you can spot relevant precedent without fetching every full text. Roles are complementary: THIS tool = DISCOVERY over the local corpus; ``search_decisions`` = live CURRENT search + citation verification. The corpus may lag; always confirm any decision you cite with ``search_decisions`` + ``get_document`` first. QUERY FORM: 2–6 legal keywords, NOT a sentence. All terms are required (AND) and match anywhere in the text, so narrative filler only shrinks the result set. Quote words to require them adjacent: ``kıdem tazminatı zamanaşımı`` · ``"tahliye taahhüdü" geçerlilik``. Unlike Bedesten this index folds diacritics (kamulastirma = kamulaştırma). Args: query: 2–6 legal keywords; `"quoted spans"` match as phrases. mode: 'lexical' (default; FTS5/BM25, sub-second), 'rrf' (BM25+TF-IDF fusion; SLOW — minutes on a large corpus), 'semantic' (dense embeddings), 'hybrid'. limit: Max results. filters: Optional dict with source, court, chamber, content_status. provider: Embedding provider name for semantic modes (ignored for lexical). source/court/chamber/date/esas_no/karar_no/document_id: Flat filters — equivalent to putting them in ``filters``. content_status/draft_usable/quote_usable: Content filters. sort: 'relevance' (default) or 'date' — lexical mode only.
| Name | Type | Req | Description |
|---|---|---|---|
| chamber | – | – | – |
| content_status | – | – | – |
| court | – | – | – |
| date | – | – | – |
| document_id | – | – | – |
| draft_usable | – | – | – |
| esas_no | – | – | – |
| filters | – | – | – |
| karar_no | – | – | – |
| limit | integer | – | – |
| mode | string | – | – |
| provider | – | – | – |
| query | string | yes | – |
| quote_usable | – | – | – |
| sort | string | – | – |
| source | – | – | – |
No output schema declared.
No examples provided.
How do I install the Emsal MCP server?
Emsal runs locally as a PyPI package, launched with uvx emsal-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · emsal-mcp
claude mcp add afsozer-emsal-mcp -- uvx emsal-mcp
What is the Emsal MCP server?
Emsal is an MCP server listed in the public MCP registry as io.github.afsozer/emsal-mcp. Citation-safe Turkish legal research: court decisions and legislation from official sources. This page covers its PyPI package (emsal-mcp).
Is the Emsal MCP server safe to use?
Emsal scores 59 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 24 October 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Emsal MCP server expose?
Emsal exposes 11 tools: search_decisions, get_document, search_legislation, mevzuat_korpus_ara, mevzuat_madde_getir, and 6 more. Their descriptions and schemas cost roughly 4,880 tokens of context every time the server is loaded.
Is the Emsal MCP server still maintained?
Emsal is marked deprecated in the MCP registry. We last reached this channel on 24 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Emsal MCP server under?
Emsal declares the AGPL-3.0-only licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.