LexLink

LexLink

Enables AI systems to search, retrieve, and analyze Korean legal information from the National Law Information API (law.go.kr), including laws, administrative rules, English translations, and law-ordinance linkages.

Category
Visit Server

README

<div align="center"> <img src="assets/LexLink_logo.png" alt="LexLink Logo" width="200"/> <h1>LexLink - Korean National Law Information MCP Server</h1> </div>

🌐 Read this in other languages: English | 한국어 (Korean)

smithery badge MCP Python

LexLink is an MCP (Model Context Protocol) server that exposes the Korean National Law Information API (open.law.go.kr) to AI agents and LLM applications. It enables AI systems to search, retrieve, and analyze Korean legal information through standardized MCP tools.

Features

  • 15 MCP Tools for comprehensive Korean law information access
    • Search and retrieve Korean laws (effective date & announcement date)
    • Search and retrieve English-translated laws
    • Search and retrieve administrative rules (행정규칙)
    • Query specific articles, paragraphs, and sub-items
    • Law-ordinance linkage (법령-자치법규 연계)
    • Delegated law information (위임법령)
  • 100% Semantic Validation - All 15 tools confirmed returning real law data
  • Session Configuration - Configure once, use across all tool calls
  • Error Handling - Actionable error messages with resolution hints
  • Korean Text Support - Proper UTF-8 encoding for Korean characters
  • Response Formats - HTML or XML (multiple formats supported)

Project Status

🎉 Production Ready!

Metric Status
Tools Implemented 15/15 (100%) ✅
Semantic Validation 15/15 (100%) ✅
API Coverage essential ~10% of 150+ endpoints
LLM Integration ✅ Validated (Gemini)
Code Quality Clean, documented, tested

Achievement: All 15 tools confirmed returning real Korean law data through comprehensive validation testing.

Prerequisites

Quick Start

1. Install Dependencies

uv sync

2. Configure Your OC Identifier

Choose one of three methods:

Option A: Session Configuration (Recommended)

# Start dev server with OC in URL
uv run dev
# Then in Smithery UI, set oc field in session config

Option B: Environment Variable

# Copy example file
cp .env.example .env

# Edit .env and set your OC
LAW_OC=your_id_here

Option C: Pass in Tool Arguments

# Override OC in each tool call
eflaw_search(query="법령명", oc="your_id")

3. Run the Server

# Development mode (with hot reload)
uv run dev

# Interactive testing with Smithery Playground
uv run playground

Available Tools

Phase 1: Core Law APIs (6 tools)

1. eflaw_search - Search Laws by Effective Date

Search for laws organized by effective date (시행일 기준).

eflaw_search(
    query="자동차관리법",      # Search keyword
    display=10,                # Results per page
    type="XML",                # Response format
    ef_yd="20240101~20241231"  # Optional date range
)

2. law_search - Search Laws by Announcement Date

Search for laws organized by announcement date (공포일 기준).

law_search(
    query="민법",
    display=10,
    type="XML"
)

3. eflaw_service - Retrieve Law Content (Effective Date)

Get full law text and articles by effective date.

eflaw_service(
    id="001823",               # Law ID
    type="XML",
    jo="0001"                  # Optional: specific article
)

4. law_service - Retrieve Law Content (Announcement Date)

Get full law text and articles by announcement date.

law_service(
    id="001823",
    type="XML"
)

5. eflaw_josub - Query Article/Paragraph (Effective Date)

Query specific article, paragraph, or sub-item by effective date.

eflaw_josub(
    id="001823",
    jo="0001",                 # Article number
    type="XML"
)

6. law_josub - Query Article/Paragraph (Announcement Date)

Query specific article, paragraph, or sub-item by announcement date.

law_josub(
    id="001823",
    jo="0001",
    type="XML"
)

Phase 2: Extended APIs (9 tools)

7. elaw_search - Search English-Translated Laws

Search for Korean laws translated to English.

elaw_search(
    query="employment",
    display=10,
    type="XML"
)

8. elaw_service - Retrieve English Law Content

Get full English-translated law text.

elaw_service(
    id="009589",
    type="XML"
)

9. admrul_search - Search Administrative Rules

Search administrative rules (훈령, 예규, 고시, 공고, 지침).

admrul_search(
    query="학교",
    display=10,
    type="XML"
)

10. admrul_service - Retrieve Administrative Rule Content

Get full administrative rule text with annexes.

admrul_service(
    id="62505",
    type="XML"
)

11. lnkLs_search - Search Law-Ordinance Linkage

Find laws linked to local ordinances.

lnkLs_search(
    query="건축",
    display=10,
    type="XML"
)

12. lnkLsOrdJo_search - Search Ordinance Articles by Law

Find ordinance articles linked to specific law articles.

lnkLsOrdJo_search(
    knd="002118",              # Law ID
    display=10,
    type="XML"
)

13. lnkDep_search - Search Law-Ordinance Links by Ministry

Find laws linked to ordinances by government ministry.

lnkDep_search(
    org="1400000",             # Ministry code
    display=10,
    type="XML"
)

14. drlaw_search - Retrieve Law-Ordinance Linkage Statistics

Get linkage statistics table (HTML format).

drlaw_search(
    lid="001823",              # Law ID
    type="HTML"
)

15. lsDelegated_service - Retrieve Delegated Law Information

Get information about delegated laws, rules, and ordinances.

lsDelegated_service(
    id="001823",
    type="XML"
)

Configuration

Session Configuration Schema

Configure once in Smithery UI or URL parameters:

{
    "oc": "your_id",              # Required: law.go.kr user ID
    "debug": false,               # Optional: Enable verbose logging
    "base_url": "http://www.law.go.kr",  # Optional: API base URL
    "http_timeout_s": 15          # Optional: HTTP timeout (5-60s)
}

Parameter Priority

When resolving the OC identifier:

  1. Tool argument (highest priority) - oc parameter in tool call
  2. Session config - Set in Smithery UI/URL
  3. Environment variable - LAW_OC in .env file

Usage Examples

Example 1: Basic Search

# Search for automobile management law
result = eflaw_search(
    query="자동차관리법",
    display=5,
    type="XML"
)

# Returns:
{
    "status": "ok",
    "request_id": "uuid",
    "upstream_type": "XML",
    "data": {
        # Law search results...
    }
}

Example 2: Search with Date Range

# Find laws effective in 2024
result = eflaw_search(
    query="교통",
    ef_yd="20240101~20241231",
    type="XML"
)

Example 3: Error Handling

# Missing OC parameter
result = eflaw_search(query="test")

# Returns helpful error:
{
    "status": "error",
    "error_code": "MISSING_OC",
    "message": "OC parameter is required but not provided.",
    "hints": [
        "1. Tool argument: oc='your_value'",
        "2. Session config: Set 'oc' in Smithery settings",
        "3. Environment variable: LAW_OC=your_value"
    ]
}

Development

Project Structure

lexlink-ko-mcp/
├── src/lexlink/
│   ├── server.py       # Main MCP server with 15 tools
│   ├── config.py       # Session configuration schema
│   ├── params.py       # Parameter resolution & mapping
│   ├── validation.py   # Input validation
│   ├── client.py       # HTTP client for law.go.kr API
│   └── errors.py       # Error codes & responses
├── pyproject.toml       # Project configuration
└── README.md            # This file

Running Tests

# Install test dependencies
uv sync

# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=src/lexlink --cov-report=html

# Run specific test category
uv run pytest tests/unit/
uv run pytest tests/integration/
uv run pytest tests/e2e/

Adding New Tools

Current Status: 15/15 core tools implemented and validated

For implementing additional tools from the 150+ available APIs:

  1. Follow the pattern established in src/lexlink/server.py
  2. Use Context injection for session configuration
  3. Add semantic validation tests

Tool Implementation Pattern:

  • Each tool is a decorated function with MCP schema
  • Uses ctx: Context = None parameter for session config
  • 3-tier parameter resolution: tool arg > session > env
  • Comprehensive error handling with actionable hints

Deployment

Deploy to Smithery

  1. Create a GitHub repository:

    git init
    git add .
    git commit -m "Initial commit"
    git remote add origin https://github.com/YOUR_USERNAME/YOUR_REPO.git
    git push -u origin main
    
  2. Deploy at smithery.ai/new

  3. Configure session settings in Smithery UI

Troubleshooting

"OC parameter is required" error

Solution: Set your OC identifier using one of the three methods above.

Korean characters not displaying correctly

Solution: Ensure your terminal supports UTF-8:

export PYTHONIOENCODING=utf-8

"Timeout" errors

Solution: Increase timeout in session config:

{
    "oc": "your_id",
    "http_timeout_s": 30  # Increase from default 15s
}

Server won't start after updating dependencies

Solution: Re-sync dependencies:

uv sync --reinstall

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for new functionality
  4. Ensure all tests pass (uv run pytest)
  5. Commit changes (git commit -m 'Add amazing feature')
  6. Push to branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

License

This project is open source. See LICENSE file for details.

Acknowledgments

  • law.go.kr - Korean National Law Information API
  • MCP - Model Context Protocol by Anthropic
  • Smithery - MCP server deployment platform

Support


Changelog

v1.0.7 - 2025-11-10

Fix: Improve search reliability and LLM guidance

  • Issue: LLMs often failed to find common laws like "민법" (Civil Code) because:
    1. Ranking fetch limit (50 results) was too small for large result sets (e.g., 77 results for "민법")
    2. LLMs defaulted to small display values (e.g., 5), missing exact matches
    3. jo parameter rejected integers, causing validation errors and retry loops
  • Root Cause:
    • v1.0.5 ranking fetched only 50 results; "민법" was beyond position 50 alphabetically
    • Tool descriptions didn't guide LLMs to use larger display values
    • Parameter type strictness caused UX friction
  • Solution:
    • Increased ranking fetch limit from 50 to 100 results (API maximum)
    • Updated jo parameter to accept Union[str, int] with auto-conversion
    • Added guidance in tool descriptions: "Recommend 50-100 for law searches (법령 검색) to ensure exact matches are found"
  • Changes:
    • All 4 search tools now fetch up to 100 results for ranking
    • All 4 tools with jo parameter (eflaw_service, law_service, eflaw_josub, law_josub) now accept integers
    • All 7 search tool descriptions updated with display recommendations
  • Impact:
    • LLMs now find "민법" correctly even with small initial display values
    • No more validation errors when LLMs pass article numbers as integers
    • Better guidance leads to more efficient searches

v1.0.6 - 2025-11-10

Enhancement: Improve MCP server quality score (Smithery.ai optimization)

  • Changes:
    • Set OC configuration default value to "test" for easier onboarding
    • Added tool annotations to all 15 tools (readOnlyHint=True, destructiveHint=False, idempotentHint=True)
    • Enhanced parameter descriptions in docstrings for all tools
    • Implemented 3 MCP prompts for common use cases
  • Prompts Added:
    • search-korean-law: Search for a Korean law by name and provide a summary
    • get-law-article: Retrieve and explain a specific article from a law
    • search-admin-rules: Search administrative rules by keyword
  • Impact: Expected Smithery quality score improvement from 47/100 to ~73/100 (+26 points)
    • Tool annotations: +9pts
    • Parameter descriptions: +12pts
    • MCP prompts: +5pts

v1.0.5 - 2025-11-10

Fix: Improve ranking by fetching more results before ranking

  • Issue: v1.0.4 ranking was not working properly because it only ranked the limited results returned by the API (e.g., with display=5, only 5 alphabetically-ordered results were fetched). If "민법" wasn't in those first 5 results, ranking couldn't help.
  • Root Cause: Ranking logic was applied AFTER API returned limited results, so relevant matches outside the initial page were never considered.
  • Solution:
    • When ranking is enabled and display < 50, automatically fetch up to 50 results from API
    • Apply ranking to the larger result set (50 results)
    • Trim back to original requested display amount after ranking
    • Update numOfRows in response to reflect actual number of results returned
  • Implementation:
    • Updated all 4 search tools: eflaw_search, law_search, elaw_search, admrul_search
    • Added original_display tracking and ranking_enabled flag
    • Fetch 50 results when ranking applies, then trim to requested amount
  • Examples:
    • User requests display=5 for query "민법"
    • System fetches 50 results (includes "민법" even if it's not in first 5 alphabetically)
    • Ranking places "민법" first
    • System returns top 5 ranked results (now "민법" appears first)
  • Impact: Ranking now actually works - exact matches appear first regardless of alphabetical position in API results

v1.0.4 - 2025-11-10

Feature: Add relevance ranking to search results

  • Issue: law.go.kr API returns results in alphabetical order, causing irrelevant matches to appear first (e.g., searching "민법" returned "난민법" first instead of exact match "민법")
  • Solution:
    • Added intelligent relevance ranking that prioritizes exact matches over alphabetical ordering
    • Ranking applies automatically to XML responses for keyword searches
    • Results are reordered: exact match → starts with query → contains query → other matches
  • Implementation:
    • Added ranking.py module with rank_search_results(), should_apply_ranking(), and detect_query_language() functions
    • Added parser.py module for XML parsing and structured data extraction
    • Updated 4 major search tools: eflaw_search, law_search, elaw_search, admrul_search
    • Ranking preserves raw XML while adding ranked_data field for LLM consumption
    • Special handling for elaw_search: Detects query language (Korean vs English) and ranks by matching name field
  • Examples:
    • Query "민법" now returns: "민법" (exact) → "민법 시행령" (starts with) → "난민법" (alphabetical)
    • Query "insurance" ranks: "Insurance Act" → "Insurance Business Act" → other matches
  • Impact: Significantly improves search relevance, reducing LLM confusion and providing better user experience

v1.0.3 - 2025-11-10

Fix: Clarify article number format in tool descriptions

  • Issue: LLMs misinterpreted the 6-digit article number format (jo parameter), generating "000200" for Article 20 (제20조) instead of correct "002000", resulting in wrong article retrieval
  • Root Cause: Tool descriptions used ambiguous example "000200" for "Article 2", leading LLMs to incorrectly pattern-match Article 20 → "000200"
  • Solution:
    • Added comprehensive article number format documentation with multiple examples
    • Added format_article_number() helper function in validation.py for future use
    • Clarified that XXXXXX format = first 4 digits (article number, zero-padded) + last 2 digits (branch article suffix)
  • Changes:
    • Updated 4 tools: eflaw_service, law_service, eflaw_josub, law_josub
    • Updated lnkLsOrdJo_search which uses separate 4+2 digit format
    • Added clear examples: "000200" (Art. 2), "002000" (Art. 20), "001502" (Art. 15-2)
  • Impact: LLMs will now correctly format article numbers, preventing queries from returning wrong articles

v1.0.2 - 2025-11-10

Fix: Accept both string and integer for id/mst parameters

  • Issue: LLMs extract numeric values from XML responses as integers (e.g., <법령일련번호>188376</법령일련번호>mst=188376), but tools expected strings, causing Pydantic validation errors
  • Solution: Changed parameter types to accept both strings and integers with automatic conversion
  • Changes:
    • Updated 7 tool signatures: id: Optional[str]id: Optional[Union[str, int]]
    • Added automatic string conversion at start of each affected tool
    • Applied to: eflaw_service, law_service, eflaw_josub, law_josub, elaw_service, admrul_service, lsDelegated_service
  • Impact: LLMs can now pass numeric IDs as integers without validation errors

v1.0.1 - 2025-11-10

Fix: Remove JSON format option from all tools

  • Issue: LLMs were selecting JSON format, but law.go.kr API does not support JSON despite documentation (returns HTML error pages with "미신청된 목록/본문" message)
  • Solution: Removed JSON as an option from all 14 tool descriptions
  • Changes:
    • Updated type parameter documentation to explicitly state "JSON not supported by API"
    • Added warning in module docstring about JSON format limitation
    • Tool defaults remain XML (working format)
  • Impact: Prevents LLMs from requesting JSON format and receiving error pages

v1.0.0 - 2025-11-10

Initial Release

  • 15 MCP tools for Korean law information access
  • 6 core law APIs (eflaw/law search and retrieval)
  • 9 extended APIs (English laws, administrative rules, law-ordinance linkage)
  • Session configuration via Context injection
  • 100% semantic validation
  • Production-ready for Smithery deployment

Built with Smithery | Powered by MCP

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured