Skip to main content
Glama
README.md
# πŸ‡°πŸ‡· Korean Land MCP (ν† μ§€ 곡간정보 MCP) β€” v2.0

**V-World API 기반 ν† μ§€Β·λ„μ‹œκ³„νš 곡간정보 MCP μ„œλ²„**
ꡭ토ꡐ톡뢀 V-World Open APIλ₯Ό λ°±μ—”λ“œλ‘œ μ‚¬μš©ν•΄, ν† μ§€μ΄μŒ(eum.go.kr)μ—μ„œ μ‚¬λžŒμ΄ μˆ˜λ™μœΌλ‘œ ν™•μΈν•˜λ˜ **μš©λ„μ§€μ—­Β·μš©λ„μ§€κ΅¬Β·μš©λ„κ΅¬μ—­Β·μ§€κ΅¬λ‹¨μœ„κ³„νšΒ·λ„μ‹œκ³„νšμ‹œμ„€Β·λ‹€λ₯Έ 법령 지정사항**을 AIκ°€ μžμ—°μ–΄λ‘œ μ‘°νšŒν•  수 있게 λ§Œλ“  **Model Context Protocol** μ„œλ²„μž…λ‹ˆλ‹€.

> **korean-law-mcp** (법령 ν…μŠ€νŠΈ) 와 짝이 λ˜λŠ” **곡간 λ ˆμ΄μ–΄ MCP**. 두 MCPλ₯Ό ν•¨κ»˜ μ“°λ©΄ "이 ν•„μ§€κ°€ 어디에 μ†ν•˜λŠ”κ°€ β†’ ν•΄λ‹Ή 법령·쑰둀가 무엇을 ν—ˆμš©/μ œν•œν•˜λŠ”κ°€" κΉŒμ§€ μžμ—°μ–΄ ν•œ μ€„λ‘œ μ—°κ²°λ©λ‹ˆλ‹€.

## ✨ v2.0 μ•„ν‚€ν…μ²˜ 원칙

1. **V-World API μ „μš©**. λ‹€λ₯Έ μƒμš© APIΒ·μŠ€ν¬λž˜ν•‘Β·λͺ¨μ˜(mock) 데이터 μ—†μŒ.
2. **μ •μ§ν•œ μ‹€νŒ¨**. νŠΉμ • λ ˆμ΄μ–΄μ—μ„œ V-Worldκ°€ 500을 λ˜μ§€λ©΄ `layer_errors`에 κ·ΈλŒ€λ‘œ λ…ΈμΆœ. μ ˆλŒ€ κ°€μ§œ λ°μ΄ν„°λ‘œ μ±„μš°μ§€ μ•ŠμŒ.
3. **korean-law-mcp와 μ—­ν•  뢄리**. 이 MCPλŠ” "**곡간상 어디에 μ†ν•˜λŠ”κ°€**"만 닡함. μ‘°λ¬Έ 해석은 korean-law-mcp둜.
4. **κ΅­ν† κ³„νšλ²• 제76μ‘°β‘€ μš°μ„  μœ„μž„ μžλ™ 감지**. 농업진ν₯κ΅¬μ—­Β·λ³΄μ „μ‚°μ§€Β·μƒμˆ˜μ›λ³΄ν˜Έκ΅¬μ—­Β·κ΅­κ°€μ‚°μ—…λ‹¨μ§€ 등이 필지에 걸리면 `priority_delegation_hint` 둜 "κ΅­ν† κ³„νšλ²• μ‹œν–‰λ Ή λ³„ν‘œ λŒ€μ‹  μ–΄λŠ 법령을 λ¨Όμ € 봐야 ν•˜λŠ”κ°€"λ₯Ό μ•Œλ €μ€Œ.

## πŸ› οΈ 제곡 도ꡬ (7개)

| 도ꡬ | μ„€λͺ… |
|---|---|
| `resolve_parcel` | μ£Όμ†Œ/μ§€λ²ˆ/PNU β†’ ν‘œμ€€ν™”λœ PNUΒ·μ§€λͺ©Β·κ³΅μ‹œμ§€κ°€Β·ν–‰μ •ꡬ역·WGS84 μ’Œν‘œ |
| `get_zoning` | μš©λ„μ§€μ—­ (λ„μ‹œ/관리/농림/μžμ—°ν™˜κ²½) + μš©λ„μ§€κ΅¬ (8μ’…) + μš©λ„κ΅¬μ—­ (κ°œλ°œμ œν•œΒ·λ„μ‹œμžμ—°κ³΅μ›) + ν† μ§€κ±°λž˜ν—ˆκ°€κ΅¬μ—­ |
| `get_district_plan` | μ§€κ΅¬λ‹¨μœ„κ³„νšκ΅¬μ—­ + κ°œλ°œν–‰μœ„ν—ˆκ°€μ œν•œκ΅¬μ—­ |
| `get_urban_facility` | λ„μ‹œκ³„νšμ‹œμ„€ 9μ’… (λ„λ‘œΒ·κ΅ν†΅Β·κ³΅κ°„Β·μœ ν†΅κ³΅κΈ‰Β·κ³΅κ³΅λ¬Έν™”μ²΄μœ‘Β·λ°©μž¬Β·λ³΄κ±΄μœ„μƒΒ·ν™˜κ²½κΈ°μ΄ˆΒ·κΈ°νƒ€). `radius_m` νŒŒλΌλ―Έν„°λ‘œ "저촉" vs "접함" ꡬ뢄 |
| `get_other_law_designations` | 42개 λ‹€λ₯Έ 법령 μ§€μ • λ ˆμ΄μ–΄ (λ†μ§€Β·μ‚°λ¦ΌΒ·μ‚°μ—…λ‹¨μ§€Β·μˆ˜μ§ˆν™˜κ²½Β·μΆ•μ‚°Β·λ¬Έν™”μž¬Β·μžμ—°κ³΅μ›Β·νŠΉμˆ˜μ§€κ΅¬Β·μ£Όκ±°μ •λΉ„Β·μž¬ν•΄Β·ν•΄μ–‘Β·ν•­κ³΅). 제76μ‘°β‘€ μš°μ„  μœ„μž„ 후보 μžλ™ ν‘œμ‹œ |
| `get_land_attributes` | μ§€λͺ©(28μ’…) νŒŒμ‹± + κ°œλ³„κ³΅μ‹œμ§€κ°€ + 건물 정보 |
| `analyze_parcel` | μœ„ 6개 도ꡬλ₯Ό ν•œ λ²ˆμ— 병렬 호좜 + korean-law-mcp λ‹€μŒ 단계 힌트 생성 |

`discover_tools` 도 ν¬ν•¨λ˜μ–΄ μžˆμ–΄ 도ꡬ μΉ΄νƒˆλ‘œκ·Έλ₯Ό μžμ—°μ–΄λ‘œ 탐색 κ°€λŠ₯.

## πŸ“‘ V-World λ ˆμ΄μ–΄ 컀버리지

- **μš©λ„μ§€μ—­**: `LT_C_UQ111/112/113/114` (λ„μ‹œΒ·κ΄€λ¦¬Β·λ†λ¦ΌΒ·μžμ—°ν™˜κ²½λ³΄μ „ 전체)
- **μš©λ„μ§€κ΅¬Β·κ΅¬μ—­**: `LT_C_UQ121~130`, `LT_C_UD801`, `LT_C_UQ162`
- **μ§€κ΅¬λ‹¨μœ„κ³„νšΒ·ν—ˆκ°€μ œν•œ**: `LT_C_UPISUQ161`, `LT_C_UPISUQ171`
- **λ„μ‹œκ³„νšμ‹œμ„€**: `LT_C_UPISUQ151~159`
- **λ‹€λ₯Έ 법령 μ§€μ •**: 농지(AGRIXUE) Β· μ‚°λ¦Ό(UF) Β· 산업단지(WGISIE\*, DAM\*) Β· μˆ˜μ§ˆν™˜κ²½(UM, WGISARWET) Β· μΆ•μ‚°(UM000) Β· λ¬Έν™”μž¬(UO) Β· μžμ—°κ³΅μ›(WGISNP\*) Β· νŠΉμˆ˜μ§€κ΅¬(UO/UJ/UH/UB) Β· μ£Όκ±°μ •λΉ„(UD) Β· μž¬ν•΄(UP) Β· ν•΄μ–‘(TFISMPA, WGISRE\*) Β· 항곡(AIS\*)
- **필지·건물**: `LP_PA_CBND_BUBUN`, `LT_C_BLDGINFO`, `A2SM_LNDPRCPS`

## πŸš€ λΉ λ₯Έ μ‹œμž‘

### 1. ν•œ 방에 μ…‹μ—…
```bash
git clone https://github.com/UrbanWatcherKr/korean-land-mcp.git
cd korean-land-mcp
npm run setup
```

`npm run setup` 은 `npm install` β†’ `npm run build` β†’ μΈν„°λž™ν‹°λΈŒ **configure** 순으둜 μ‹€ν–‰λ©λ‹ˆλ‹€. configure λ‹¨κ³„μ—μ„œ V-World API 킀·도메인을 묻고 `.env` νŒŒμΌμ„ μžλ™ μƒμ„±ν•©λ‹ˆλ‹€.

**V-World API ν‚€ λ°œκΈ‰**: https://www.vworld.kr/dev/v4api.do (둜그인 β†’ μ˜€ν”ˆAPI β†’ 인증킀 λ°œκΈ‰, 무료). 둜컬 개발용이면 도메인은 `localhost`둜 등둝.

### 2. μ„€μ •λ§Œ λ‹€μ‹œ ν•˜κΈ°
API ν‚€λ₯Ό λ°”κΎΈκ±°λ‚˜ 도메인을 μˆ˜μ •ν•˜κ³  μ‹ΆμœΌλ©΄ μ–Έμ œλ“ :
```bash
npm run configure
```

### 3. Claude Desktop / Claude Code 에 등둝
configure κ°€ λλ‚˜λ©΄ 뢙여넣을 JSON 블둝을 터미널에 좜λ ₯ν•©λ‹ˆλ‹€. λ˜λŠ” μˆ˜λ™μœΌλ‘œ:
```json
{
  "mcpServers": {
    "korean-land": {
      "command": "node",
      "args": ["/absolute/path/to/korean-land-mcp/dist/server.js"],
      "env": {
        "VWORLD_API_KEY": "your_real_key_here",
        "VWORLD_DOMAIN": "localhost"
      }
    }
  }
}
```

## πŸ’¬ μ‚¬μš© μ˜ˆμ‹œ

- "경기도 ν‰νƒμ‹œ 포승읍 내기리 680 μš©λ„μ§€μ—­ μ•Œλ €μ€˜" β†’ `get_zoning`
- "이 필지에 제76μ‘°β‘€ μš°μ„  μœ„μž„ μ μš©λ˜λŠ”μ§€ μ²΄ν¬ν•΄μ€˜" β†’ `get_other_law_designations`
- "반경 50m μ•ˆμ— λ„μ‹œκ³„νšμ‹œμ„€ 저촉·접함 μžˆμ–΄?" β†’ `get_urban_facility({ radius_m: 50 })`
- "이 μ§€λ²ˆ 전체 λΆ„μ„ν•˜κ³  korean-law λ‹€μŒ 단계 μ•Œλ €μ€˜" β†’ `analyze_parcel`

## 🧭 korean-law-mcp μ™€μ˜ μ›Œν¬ν”Œλ‘œμš°

```
μ‚¬μš©μž: "이 μ§€λ²ˆμ— 곡μž₯ 지을 수 μžˆμ–΄?"
  ↓
korean-land-mcp Β· analyze_parcel
  ↓ (μš©λ„μ§€μ—­=μΌλ°˜κ³΅μ—…, 산업단지=μ•„μ‚°ν¬μŠΉ, μš°μ„ μœ„μž„=μ‚°μ—…μž…μ§€λ²•)
korean-law-mcp Β· search_law("μ‚°μ—…μž…μ§€λ²•")
  ↓
korean-law-mcp Β· get_law_text(μ‚°μ—…μž…μ§€λ²• 제33μ‘°)
  ↓
κ²°λ‘  + 원문 κ·Όκ±°
```

## πŸ—‚οΈ ν”„λ‘œμ νŠΈ ꡬ쑰

```
src/
β”œβ”€β”€ server.ts                          # MCP stdio μ—”νŠΈλ¦¬, 7개 도ꡬ 등둝
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ vworld.ts                      # V-World HTTP ν΄λΌμ΄μ–ΈνŠΈ (5xx μž¬μ‹œλ„ 1회)
β”‚   β”œβ”€β”€ overlays.ts                    # 병렬 λ ˆμ΄μ–΄ 쿼리 + POINT/BOX ν•„ν„°
β”‚   β”œβ”€β”€ resolve.ts                     # μ£Όμ†Œ/μ§€λ²ˆ/PNU 해석
β”‚   └── jimok.ts                       # μ§€λͺ© μ½”λ“œ 28μ’… λ§€ν•‘
└── tools/
    β”œβ”€β”€ resolve_parcel.ts
    β”œβ”€β”€ get_zoning.ts
    β”œβ”€β”€ get_district_plan.ts
    β”œβ”€β”€ get_urban_facility.ts
    β”œβ”€β”€ get_other_law_designations.ts
    β”œβ”€β”€ get_land_attributes.ts
    └── analyze_parcel.ts
```

## πŸ§ͺ ν…ŒμŠ€νŠΈ

**μœ λ‹› ν…ŒμŠ€νŠΈ** (순수 ν•¨μˆ˜, API ν‚€ λΆˆν•„μš”):
```bash
npm test
```

**Live smoke test** (μ‹€μ œ V-World 호좜, `VWORLD_API_KEY` ν•„μš”):
```bash
# 단일 μ§€λ²ˆ 디버그
npx tsx tests/live/smoke-polygon.ts "μ„œμšΈνŠΉλ³„μ‹œ 마포ꡬ 연남동 229-1"

# 3개 ν”½μŠ€μ²˜ νšŒκ·€ ν…ŒμŠ€νŠΈ (μŠ€λƒ…μƒ· 비ꡐ)
npx tsx tests/live/smoke-fixtures.ts

# μŠ€λƒ…μƒ· κ°±μ‹  (V-World 데이터 λ³€κ²½ μ‹œ)
npx tsx tests/live/smoke-fixtures.ts --update
```

Fixtures: λ„μ‹œ μ£Όκ±°μ§€(연남동), 농림지역+μš°μ„ μœ„μž„(μ„ΈμΆœλ¦¬), 볡합 μš©λ„μ§€μ—­+λ„μ‹œκ°œλ°œ(갈맀리).

## ⚠️ μ•Œλ €μ§„ ν•œκ³„

- **점 기반 νŒμ •**: κΈ°λ³Έ μΏΌλ¦¬λŠ” ν•„μ§€ 쀑심점 1개λ₯Ό V-World에 λ˜μ§„λ‹€. ν•„μ§€ 폴리곀 ꡐ차가 μ•„λ‹ˆλ―€λ‘œ 경계에 걸친 μΌ€μ΄μŠ€λŠ” 놓칠 수 있음. `get_urban_facility` 의 `radius_m` λŠ” BOX ν•„ν„°λ‘œ 이 ν•œκ³„λ₯Ό μ™„ν™”ν•˜μ§€λ§Œ, "저촉" vs "접함" μ΅œμ’… νŒμ •μ€ μ‚¬μš©μž λ˜λŠ” λ‹΄λ‹Ή κ³΅λ¬΄μ›μ˜ 폴리곀 ꡐ차 μž¬κ²€μ¦μ΄ ν•„μš”.
- **V-World λ ˆμ΄μ–΄ μž₯μ• **: 일뢀 λ ˆμ΄μ–΄κ°€ κ°„ν—μ μœΌλ‘œ HTTP 500을 λ°˜ν™˜ν•¨. 5xx 1회 μž¬μ‹œλ„ 후에도 μ‹€νŒ¨ μ‹œ `layer_errors` 에 λ…ΈμΆœλ˜λ©°, λ‚˜λ¨Έμ§€ λ ˆμ΄μ–΄ κ²°κ³ΌλŠ” 정상 λ°˜ν™˜λœλ‹€.
- **μ§€μžμ²΄ μ‘°λ‘€ 미포함**: 이 MCPλŠ” 곡간 λ ˆμ΄μ–΄λ§Œ. μ§€μžμ²΄ λ„μ‹œκ³„νšμ‘°λ‘€ 쑰문은 **korean-law-mcp** λ˜λŠ” λ²•μ œμ²˜ μžμΉ˜λ²•κ·œ API둜 별도 쑰회.

## πŸ“œ λΌμ΄μ„ μŠ€

MIT License.

## 🀝 κΈ°μ—¬

이슈·PR ν™˜μ˜. μƒˆ V-World λ ˆμ΄μ–΄ μΆ”κ°€ μ‹œ `src/tools/*.ts` 의 `LAYERS` 배열에 `{ id, label }` 만 μΆ”κ°€ν•˜λ©΄ μžλ™μœΌλ‘œ `queryOverlays` νŒŒμ΄ν”„λΌμΈμ— νŽΈμž…λ©λ‹ˆλ‹€.

TDQS

A4.1/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: resolve_parcel for resolution, get_land_attributes for parcel details, get_zoning for zoning overlays, get_district_plan for district plans, get_urban_facility for facilities, get_other_law_designations for other laws, analyze_parcel as a composite, and discover_tools for listing. No two tools overlap in functionality.

Naming Consistency4/5

Most tools follow a 'get_X' pattern, but three use different verbs: analyze_parcel, discover_tools, resolve_parcel. The structure is still clear and predictable, and all names use snake_case, so the inconsistency is minor.

Tool Count5/5

With 8 tools, the server covers essential land information queries and includes a composite tool for one-shot analysis. This is well-scoped; each tool earns its place without being overwhelming or sparse.

Completeness4/5

The tool set covers parcel resolution, attributes, zoning, district plans, urban facilities, other law designations, and a composite with buildings. Minor gaps exist (no separate building tool, no area field), but the composite mitigates these and the domain is well-covered.

Maintenance

ActivityInactive
ResponsivenessNo issues