Skip to main content
Glama
LimEulYoung

legal-search-mcp

by LimEulYoung

Lawful MCP

English | 한국어

Korean case law, statutes and sentencing data as MCP tools. Point an AI client at it and the model can look up statute text as it stood on a given date, find judgments by the facts of a case, read one judgment and answer a question about it, and compute a sentencing range the way a Korean court does.

Four read-only tools:

Tool

What it does

precedent_search

Find judgments by facts, charge, court, year or case number

precedent_dive

Read one judgment body and answer a question about it

statute_lookup

Statute and administrative-rule articles, current or as of a date

sentencing_analysis

Everything a sentence turns on for one charge — statutory range, the guideline, the factors, the observed sentences — and the arithmetic once the findings are supplied

This is the production system behind 로풀 (Lawful), a free Korean legal-AI service, and the descendant of the research prototype in legal_mcp — see Paper.

Quick start — hosted

The full corpus (220k+ judgments, statutes with their amendment history, administrative rules, sentencing guidelines) is served for you. No rate limits. Three ways in:

Claude / ChatGPT on the web — no code. Add a custom connector with this URL, sign in with OAuth when asked, and the four tools appear. No API key needed:

https://mcp.crow-tit.com/mcp

Step-by-step with the exact menu clicks: crow-tit.com/docs#mcp

Claude Code — one command, with a free key from console.crow-tit.com:

claude mcp add --transport http lawful https://mcp.crow-tit.com/mcp \
  --header "Authorization: Bearer ct_..."

Any other MCP client (Claude Desktop, Cursor, …) — JSON config, same key:

{
  "mcpServers": {
    "lawful": {
      "url": "https://mcp.crow-tit.com/mcp",
      "headers": { "Authorization": "Bearer ct_..." }
    }
  }
}

Related MCP server: Korean Law MCP

Quick start — self-host

The repository ships a sample corpus so a clone runs immediately:

git clone https://github.com/LimEulYoung/lawful-mcp
cd lawful-mcp
pip install -e .
lawful-mcp                 # stdio
lawful-mcp --transport http --port 8100

Register it with a client:

{
  "mcpServers": {
    "lawful-mcp": {
      "command": "lawful-mcp"
    }
  }
}

Configuration is all environment variables — see .env.example. Nothing is required; the defaults use the bundled corpus.

The dive tool needs a model

Three of the four tools are pure database reads. precedent_dive sends one public judgment body to a language model and asks it to extract an answer, so it needs an endpoint:

export DIVE_API_KEY=...
export DIVE_BASE_URL=https://api.openai.com/v1   # any OpenAI-compatible endpoint
export DIVE_MODEL=...

Without those three the tool is not registered and the other four run normally.

The corpus

The tools read one SQLite file. What ships here is a bounded sample, not the whole thing:

Sample (data/fixture.db)

Hosted

Judgments

800

220,000+

Statutes

27 core laws, current text

All, with amendment history

Administrative rules

20

All

Sentencing guidelines

Complete

Complete

Charge taxonomy

Complete

Complete

The sample is enough to exercise every tool and run the tests. For real work, use the hosted corpus.

Search combines two lexical indexes: a character-trigram FTS and a morpheme FTS built with Kiwi, fused with reciprocal rank fusion. The morpheme index is not an optimisation — Korean charge names are often two characters (사기, 절도, 폭행), and a trigram index cannot form a trigram from two characters, so those queries return nothing without it.

Judgments are non-copyrightable under Article 7 of the Korean Copyright Act. Court and case-number provenance is preserved in the data.

Building your own

scripts/build_sample_db.py carves a sample out of a full corpus and is also the reference for the schema — which tables the tools read, how the full-text indexes are built, and how statute versions resolve:

python scripts/build_sample_db.py --source /path/to/corpus.db \
    --dest my_sample.db --cases 5000 --statutes all

Paper

The retrieval and tool-use design was evaluated on the Korean Bar Examination:

Agentic RAG for Legal Question Answering in Civil Law: Evidence From the Korean Bar Examination Eul Young Lim and Jihun Park IEEE Access, vol. 14, pp. 124441–124458, 2026. doi:10.1109/ACCESS.2026.3722717 — open access

Benchmark code, questions and per-model results are archived in legal_mcp. If you use this tool in research, please cite the paper (CITATION.cff).

Also available

  • Lawful Agent API — one question in, a grounded answer out. crow-tit.com

  • 로풀 (Lawful) — the free consumer service, 법률AI: chat, search, labour calculators, legal document drafting. lawful.crow-tit.com

Notes

This is a search tool over public legal sources, not legal advice. What it returns is source material and statistics; deciding what they mean for a particular matter is a lawyer's job.

Development happens in a private repository and lands here in batches, so issues are welcome but pull requests may be merged by hand rather than through the button.

MIT licensed.

Available Tools

4 tools
compute_sentencing_rangeA
Read-onlyIdempotent

통합 양형 도구 — 죄명에서 법정형→처단형→권고형→선고 검증까지, 인자를 채울수록 깊은 단계로 자동 진행: charge만=lookup(법정형·권고범위·인자 enum) / +statutory_modifications=처단형(형법§56 순서 적용) / +guideline_type·guideline_factors=권고형 / +sentence_months·fine_amount(+probation_factors)=final(선고형·집행유예 검증). 결과는 양형기준이 정한 '범위'(예측 아님). 호출 간 상태가 없으므로 후속 호출마다 charge와 확정 선택·플래그·offense_date를 반복하고 새 인자를 추가. Args: charge=판결문형 죄명 문자열(예 '살인','도로교통법위반(음주운전)') — 호출당 하나(여러 죄는 각각 호출; list면 죄명별 유도[multiple_charges]), 숫자·ID 불가(조문번호·charge_id 아님; 숫자면 유도[charge_numeric]). offense_date=행위 일자(지정 시 행위시 조문). sg_category_id·statute_choice·branch_key·reference_choice=ambiguous_* 응답이 후보를 줄 때. is_attempted·is_accessory·is_solicitor=미수·방조·교사. statutory_modifications=가중감경 list(lookup enum에서). guideline_type·guideline_leaf_id·guideline_factors=권고유형(lookup 목록 명칭 그대로)·leaf_id·특별인자. sentence_months=검증 선고형(자유형·월)·fine_amount=벌금(원)·probation_factors=집행유예 인자(dict). act_count=동종 다행위 수(≥2면 경합범 가중 자동). 후속 단계 값은 이전 응답 enum에 있는 key만 쓰고 추측 금지. 응답의 '출처'(해설서 PDF)가 있으면 인용 링크로 제시.

ParametersJSON Schema
NameRequiredDescriptionDefault
chargeYes
act_countNo
branch_keyNo
fine_amountNo
is_accessoryNo
is_attemptedNo
is_solicitorNo
offense_dateNo
guideline_typeNo
sg_category_idNo
statute_choiceNo
sentence_monthsNo
reference_choiceNo
guideline_factorsNo
guideline_leaf_idNo
probation_factorsNo
statutory_modificationsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the read-only and idempotent annotations, the description discloses stateless multi-step behavior, range vs. prediction semantics, the need to reuse enums from prior responses, and automatic treatment of multi-act counts. This gives the agent a realistic model of how the tool behaves across calls.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but highly structured, front-loading the tool's purpose and stage progression before the argument details. Every sentence adds operational value, and the length is justified by the number of parameters and the multi-stage workflow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, 17 parameters, and existing output schema, the description is remarkably complete: it covers all parameter semantics, call sequencing, statelessness, enum reuse, and citation handling. An agent has enough information to invoke the tool correctly across successive calls.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden of explaining 17 parameters. It does so thoroughly: charge format constraints, offense_date semantics, ambiguous_* response parameters, statutory_modifications, guideline fields, sentence/fine/probation inputs, and act_count behavior are all explained with concrete examples and constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as a unified sentencing computation engine that progresses from statutory range to final sentence verification, with a specific verb and resource. It does not explicitly name sibling tools for differentiation, but the scope is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides strong contextual guidance: it explains the staged progression based on which parameters are filled, notes statelessness, and tells the caller to repeat charge and confirmed selections on each call. It does not explicitly state when to prefer this tool over a sibling like precedent_search or sentence_statistics, but the usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sentence_statisticsA
Read-onlyIdempotent

양형 선고 통계 — charges 또는 charge_id 중 하나는 필수. ① charges 하나로 정제된 죄명 후보(charge_id+표본수)를 반환(status=candidates), ② 후보에서 고른 charge_id 하나를 주면 그 죄명 하나만 유죄인 피고인의 1심 선고 분포(표본 30↑=형종별 평균·표준편차·집유율 + 11분위 비교판례 / 미만=개별 사례 그리드). 죄명이 이미 특정되면 곧바로 통계가 옵니다. 형량 전망·구형/양형 근거·자기 사건 위치를 가늠할 때 결론 전에 호출(compute_sentencing_range 공식 '범위'를 실데이터로 보완). status=candidates는 통계가 아니라 선택지 — 사안에 맞는 charge_id 하나로 재호출. 죄명·charge_id는 한 번에 하나씩. 경합 사안의 죄명별 단독 분포를 합산·평균·1.5배해 경합범 분포로 만들지 마세요. 형법 38조는 가장 중한 죄 장기(벌금은 다액)의 1/2까지 가중하되 각 죄 장기·다액 합계를 넘지 못하게 하는 처단형 상한이지 통계 결합식이 아닙니다. status=low_n_grid는 단독 개별 사례라 일반화 금지. Args: charges=죄명 텍스트 하나(후보 검색용; 구어 '보이스피싱·몰카·마약'·카테고리 '성범죄'·법률명 '도로교통법위반'도 인식). charge_id=후보에서 고른 pool id 하나(int; 통계 조회용, charges와 택일). year_from/year_to=판결 연도 범위. reference_year=비교 판례·그리드 기준 연도(가까운 사건 우선; None=최근). 비교 판례·그리드의 url만 인용 링크로, 집계 분포 수치는 링크 없이 제시.

ParametersJSON Schema
NameRequiredDescriptionDefault
chargesNo
year_toNo
charge_idNo
year_fromNo
reference_yearNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool read-only and idempotent, so the description adds substantial behavior beyond them: sample-size-dependent output (30+ aggregated stats vs status=low_n_grid individual cases), status values, the prohibition on combining charge distributions, the Criminal Act 38 caveat, and the citation-link rule. This goes well beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long and dense, but it is well structured with numbered modes, a usage-context sentence, warnings, and an Args section. Some sentences, such as the Criminal Act 38 explanation, are verbose, but they carry necessary misuse warnings. It is front-loaded with the core purpose and required-parameter condition, though it could be tightened.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 5 parameters, 0% schema coverage, and an output schema present, the description covers all essential operational aspects: required parameter choice, mode switching, sample-size thresholds, output statuses, and output citation rules. Nothing critical an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description is the only source of parameter meaning. It explains charges (candidate search, accepts colloquial/category/statute names), charge_id (pool id, mutually exclusive with charges), year_from/year_to (judgment year range), and reference_year (base year, None=recent). This fully compensates for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with '양형 선고 통계' and immediately explains the two-mode flow: charges returns charge candidates (status=candidates) and charge_id returns sentencing distribution for a single charge. It explicitly distinguishes itself from compute_sentencing_range by noting it complements that formula with real data. The verb+resource is specific and the two modes are clearly differentiated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use context: '형량 전망·구형/양형 근거·자기 사건 위치를 가늠할 때 결론 전에 호출' and names the alternative compute_sentencing_range as being complemented. It also provides when-not guidance: candidates are not statistics, one charge at a time, and do not combine distributions across charges. This is strong usage guidance even though it does not explicitly mention precedent_search or statute_lookup.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

statute_lookupA
Read-onlyIdempotent

법령·행정규칙 조회 — 법령의 요건·효과·기간·절차가 답의 뼈대가 되는 국면의 기본 도구이며, 죄명·법조 식별 후 조문 본문 확인에도 씁니다. 조문은 개정되므로 현행 본문은 이 도구만 압니다. 법률·대통령령·부령·규칙과 행정규칙(고시·훈령·예규)을 한 번에 검색합니다 — 종류를 가리는 인자는 없고 관련도 순으로 함께 나오며 각 결과에 종류가 붙습니다. 자주 쓰는 법령은 quick-access id로 바로 호출(statute_id+articles): 헌법 468·민법 584·상법 583·민사소송법 581·형법 578·형사소송법 574·행정기본법 4953·행정절차법 437·행정소송법 386·헌법재판소법 3629. query 또는 statute_id가 필수. 그 외는 two-step — ① query=법령명으로 후보 id를 받고 ② statute_id+articles로 본문 호출(조문 번호는 법령마다 달라 법령을 먼저 확정). Args: query=법령명·행정규칙명 또는 본문 키워드(id 모를 때). statute_id=검색이 준 식별자를 글자 그대로 — 법령은 정수(예 584; 위 목록 밖은 추측 금지 — 574는 형사소송법), 행정규칙은 'admrul-18060'. 접두사를 떼면 같은 번호의 다른 법령이 조회됩니다. articles=조문 번호 list[str] 최대 8개('347'/'제347조'=본조+가지, '347의2'=가지만, 범위 ['3','4','5']; 미지정 시 outline; 8개 초과는 앞 8개만 조회하고 나머지를 message로 알림 — 나눠 재호출). limit=검색 모드 최대 결과 수(기본 10·최대 50). offense_date=행위 일자(예 '2013.7.30') 지정 시 행위시점 조문, 미지정 시 현행. url만 인용 링크로 쓰고, text_kind: 공식 … 원문인 조문·행정규칙 본문만 직접인용하세요.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryNo
articlesNo
statute_idNo
offense_dateNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false. The description adds substantial behavioral detail beyond that: statutes are amended so only this tool knows current text, offense_date switches to the version in force at the time of the act, partial article-number prefix matching behavior, the 8-article truncation notice, and the warning that removing prefixes can fetch a different statute.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence carries operational value: purpose, scope, quick-access IDs, workflow, parameter semantics, and citation rules. It is front-loaded with the tool's role and then moves systematically through usage, and the dense content is justified by the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no required fields, an output schema, and complex interaction rules between query and statute_id, the description covers all necessary decision points: mode selection, article number syntax, result limits, time-based statute versions, and even citation/quoting constraints. An agent has enough information to invoke correctly in both search and article-lookup modes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden. It thoroughly explains query, statute_id (including integer vs 'admrul-18060' forms and the prefix hazard), articles syntax with examples like '347의2' and ranges, limit defaults/max, and offense_date format and semantics. This far exceeds what the bare schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description opens with a specific verb and resource: '법령·행정규칙 조회' and explains exactly when this is the basic tool — when statutory requirements, effects, periods, or procedures form the backbone of the answer. It also covers identification of criminal provisions then checking article text, which clearly differentiates it from sibling precedent-search and sentencing tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides rich usage context: two-step workflow, quick-access IDs, when to use query vs statute_id, and constraints such as needing to confirm the statute first because article numbering differs per statute. It does not explicitly name sibling tools as alternatives or state when not to use this tool, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedcompute_sentencing_range
    • First observedprecedent_search
    • First observedsentence_statistics
    • First observedstatute_lookup

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct resource: precedents, statutes, empirical sentencing data, and guideline-based range calculation. The sentencing pair is explicitly differentiated, with compute_sentencing_range producing guideline ranges and sentence_statistics providing real case distributions.

Naming Consistency3/5

All names are lowercase snake_case and readable, but they mix conventions: precedent_search and statute_lookup are object+verb, sentence_statistics is a noun phrase, and compute_sentencing_range is verb+object. The pattern is not predictable enough for an agent to infer a new tool's name.

Tool Count5/5

Four tools is well-scoped for a legal research and sentencing assistant. Each tool is broad and complex enough to justify its place, with no redundant tools.

Completeness2/5

The set covers statutes and sentencing well, but precedent_search explicitly instructs callers to continue with precedent_dive, which is not exposed in the tool list. This creates a dead end for full-text precedent access and is a significant gap for the stated legal-research purpose.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers