korean-law-mcp 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,47 +1,68 @@
1
1
  # Korean Law MCP
2
2
 
3
- **87 tools to search, retrieve, and analyze Korean law** statutes, precedents, ordinances, treaties, and more.
3
+ **대한민국 법령 검색·조회·분석 89개 도구** 법령, 판례, 행정규칙, 자치법규, 조약, 해석례를 AI 어시스턴트나 터미널에서 바로 사용.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/korean-law-mcp.svg)](https://www.npmjs.com/package/korean-law-mcp)
6
6
  [![MCP 1.27](https://img.shields.io/badge/MCP-1.27-blue)](https://modelcontextprotocol.io)
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue)](https://www.typescriptlang.org/)
9
8
 
10
- > MCP server + CLI for Korea's official legal database (법제처 Open API). Works with Claude Desktop, Cursor, Windsurf, Zed, and any MCP-compatible client.
9
+ > 법제처 Open API 기반 MCP 서버 + CLI. Claude Desktop, Cursor, Windsurf, Zed, Claude.ai 등에서 바로 사용 가능.
11
10
 
12
- [한국어](./README-KR.md)
11
+ [English](./README-EN.md)
12
+
13
+ ![Korean Law MCP 데모](./demo.gif)
13
14
 
14
15
  ---
15
16
 
16
- ## Why this exists
17
+ ## v2.3.0 변경사항
18
+
19
+ - **도구 프로필 (lite/full)** — 웹 클라이언트(Claude.ai 등)용 lite 프로필 도입. 89개 → 14개로 자동 축소하여 컨텍스트 소비 87% 절감. `/mcp?profile=lite`로 사용.
20
+ - **체인 8개** + 핵심 직접 도구 4개 + 메타 도구 2개 = 14개로 동일 기능 커버
21
+ - `discover_tools`: 의도/카테고리로 숨겨진 전문 도구 검색
22
+ - `execute_tool`: discover로 찾은 도구를 프록시 실행
23
+ - **kordoc 통합 파서** — 자체 HWP5/HWPX/PDF 파서 5개를 [kordoc](https://github.com/chrisryugj/kordoc) 통합 파서로 교체. 의존성 경량화.
24
+
25
+ <details>
26
+ <summary>v2.2.0 변경사항</summary>
27
+
28
+ - **23개 신규 도구 (64 → 87)** — 조약, 법령-자치법규 연계, 학칙/공단/공공기관 규정, 특별행정심판, 감사원 결정, 조항상세, 문서분석, 행정규칙 신구대조 등 대폭 확장.
29
+ - **문서분석 엔진** — 8종 문서유형 분류, 17개 리스크규칙, 금액/기간 추출, 조항 충돌 탐지.
30
+ - **법령-자치법규 연계 (4개 도구)** — 법률↔조례 위임 체인을 양방향 추적.
31
+ - **조약 지원 (2개 도구)** — 대한민국이 체결한 양자/다자 조약 검색 및 전문 조회.
32
+ - **보안 강화** — CORS 오리진 제어, API 키 헤더 전용, 보안 헤더, 세션 ID 마스킹.
17
33
 
18
- South Korea has **1,600+ active laws**, **10,000+ administrative rules**, and a precedent system spanning Supreme Court, Constitutional Court, tax tribunals, and customs rulings. All of this lives behind a clunky government API with zero developer experience.
34
+ </details>
19
35
 
20
- This project wraps that entire legal system into **87 structured tools** that any AI assistant or script can call. Built by a Korean civil servant who got tired of manually searching [법제처](https://www.law.go.kr) for the hundredth time.
36
+ <details>
37
+ <summary>v1.8.0 – v1.9.0 기능</summary>
38
+
39
+ - **체인 도구 8개** — 복합 리서치를 한 번의 호출로: `chain_full_research`(AI검색→법령→판례→해석), `chain_law_system`, `chain_action_basis`, `chain_dispute_prep`, `chain_amendment_track`, `chain_ordinance_compare`, `chain_procedure_detail`.
40
+ - **일괄 조문 조회** — `get_batch_articles`가 `laws` 배열로 복수 법령 한 번에 조회.
41
+ - **AI 검색 법령종류 필터** — `search_ai_law`에 `lawTypes` 필터 추가.
42
+ - **구조화 에러 포맷** — `[에러코드] + 도구명 + 제안` 형식으로 64개 도구 통일.
43
+ - **HWP 테이블 수정** — 구형 HWP 파서에서 `paragraph.controls[].content` 경로의 테이블 추출 지원.
44
+
45
+ </details>
21
46
 
22
47
  ---
23
48
 
24
- ## Features
49
+ ## 왜 만들었나
50
+
51
+ 대한민국에는 **1,600개 이상의 현행 법률**, **10,000개 이상의 행정규칙**, 그리고 대법원·헌법재판소·조세심판원·관세청까지 이어지는 방대한 판례 체계가 있습니다. 이 모든 게 [법제처](https://www.law.go.kr)라는 하나의 사이트에 있지만, 개발자 경험은 최악입니다.
25
52
 
26
- - **87 Legal Tools** Statutes, precedents, admin rules, ordinances, constitutional decisions, tax rulings, customs interpretations, treaties, institutional rules, legal terminology
27
- - **MCP + CLI** — Use from Claude Desktop or from your terminal. Same 87 tools.
28
- - **Korean Law Intelligence** — Auto-resolves abbreviations (`화관법` → `화학물질관리법`), converts article numbers (`제38조` ↔ `003800`), visualizes 3-tier delegation
29
- - **Annex Extraction** — Downloads HWPX/HWP annexes and converts tables to Markdown automatically
30
- - **8 Chain Tools** — Composite research workflows in a single call (e.g. `chain_full_research`: AI search → statutes → precedents → interpretations)
31
- - **Caching** — 1-hour search cache, 24-hour article cache
32
- - **Remote Endpoint** — Use without installation via `https://korean-law-mcp.fly.dev/mcp`
53
+ 프로젝트는 전체 법령 시스템을 **89개 구조화된 도구**로 감싸서, AI 어시스턴트나 스크립트에서 바로 호출할 있게 만듭니다. 법제처를 번째 수동 검색하다 지친 공무원이 만들었습니다.
33
54
 
34
55
  ---
35
56
 
36
- ## Quick Start
57
+ ## 빠른 시작
37
58
 
38
- ### Option 1: MCP Server (Claude Desktop / Cursor / Windsurf)
59
+ ### MCP 서버 (Claude Desktop / Cursor / Windsurf)
39
60
 
40
61
  ```bash
41
62
  npm install -g korean-law-mcp
42
63
  ```
43
64
 
44
- Add to your MCP client config:
65
+ MCP 클라이언트 설정에 추가:
45
66
 
46
67
  ```json
47
68
  {
@@ -56,17 +77,17 @@ Add to your MCP client config:
56
77
  }
57
78
  ```
58
79
 
59
- Get your free API key at [법제처 Open API](https://open.law.go.kr/LSO/openApi/guideResult.do).
80
+ API 키는 [법제처 Open API](https://open.law.go.kr/LSO/openApi/guideResult.do)에서 무료 발급.
60
81
 
61
- | Client | Config File |
62
- |--------|------------|
82
+ | 클라이언트 | 설정 파일 |
83
+ |-----------|----------|
63
84
  | Claude Desktop | `%APPDATA%\Claude\claude_desktop_config.json` (Win) / `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac) |
64
85
  | Cursor | `.cursor/mcp.json` |
65
86
  | Windsurf | `.windsurf/mcp.json` |
66
87
  | Continue | `~/.continue/config.json` |
67
88
  | Zed | `~/.config/zed/settings.json` |
68
89
 
69
- ### Option 2: Remote (No Install)
90
+ ### 원격 MCP (설치 없이 바로)
70
91
 
71
92
  ```json
72
93
  {
@@ -78,7 +99,21 @@ Get your free API key at [법제처 Open API](https://open.law.go.kr/LSO/openApi
78
99
  }
79
100
  ```
80
101
 
81
- ### Option 3: CLI
102
+ **Claude.ai 클라이언트** — 컨텍스트 절약을 위해 lite 프로필 권장:
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "korean-law": {
108
+ "url": "https://korean-law-mcp.fly.dev/mcp?profile=lite"
109
+ }
110
+ }
111
+ }
112
+ ```
113
+
114
+ > lite 프로필은 체인 8개 + 핵심 4개 + 메타 2개 = **14개 도구**로 동일 기능 커버. 특수 도구가 필요하면 `discover_tools` → `execute_tool`로 접근.
115
+
116
+ ### CLI
82
117
 
83
118
  ```bash
84
119
  npm install -g korean-law-mcp
@@ -87,221 +122,77 @@ export LAW_OC=your-api-key
87
122
  korean-law search_law --query "관세법"
88
123
  korean-law get_law_text --mst 160001 --jo "제38조"
89
124
  korean-law search_precedents --query "부당해고"
90
- korean-law list # all 87 tools
91
- korean-law list --category 판례 # filter by category
92
- korean-law help search_law # tool help
93
- ```
94
-
95
- ### Option 4: Docker
96
-
97
- ```bash
98
- docker build -t korean-law-mcp .
99
- docker run -e LAW_OC=your-api-key -p 3000:3000 korean-law-mcp
125
+ korean-law list # 89개 전체 도구 목록
126
+ korean-law list --category 판례 # 카테고리별 필터
127
+ korean-law help search_law # 도구 도움말
100
128
  ```
101
129
 
102
130
  ---
103
131
 
104
- ## Tool Categories (87 total)
105
-
106
- ### Search (11)
107
-
108
- | Tool | Description |
109
- |------|-------------|
110
- | `search_law` | Search statutes (auto-resolves abbreviations) |
111
- | `search_admin_rule` | Search administrative rules |
112
- | `search_ordinance` | Search local ordinances |
113
- | `search_precedents` | Search court precedents |
114
- | `search_interpretations` | Search legal interpretations |
115
- | `search_all` | Unified search across all categories |
116
- | `suggest_law_names` | Law name autocomplete |
117
- | `advanced_search` | Advanced search with date/keyword filters |
118
- | `get_law_history` | Law amendment history by date |
119
- | `get_annexes` | Retrieve annexes + extract HWPX/HWP to Markdown |
120
- | `parse_jo_code` | Article number ↔ JO code conversion |
121
-
122
- ### Retrieve (9)
123
-
124
- | Tool | Description |
125
- |------|-------------|
126
- | `get_law_text` | Full statute text |
127
- | `get_admin_rule` | Full administrative rule |
128
- | `get_ordinance` | Full local ordinance |
129
- | `get_precedent_text` | Full precedent text |
130
- | `get_interpretation_text` | Full interpretation text |
131
- | `get_batch_articles` | Batch article retrieval (multiple laws) |
132
- | `get_article_with_precedents` | Article + related precedents |
133
- | `compare_old_new` | Old vs. new law comparison |
134
- | `get_three_tier` | Law → Decree → Rule 3-tier comparison |
135
-
136
- ### Analyze (10)
137
-
138
- | Tool | Description |
139
- |------|-------------|
140
- | `compare_articles` | Cross-law article comparison |
141
- | `get_law_tree` | Delegation structure tree |
142
- | `get_article_history` | Article amendment history |
143
- | `summarize_precedent` | Precedent summary |
144
- | `extract_precedent_keywords` | Precedent keyword extraction |
145
- | `find_similar_precedents` | Similar precedent search |
146
- | `get_law_statistics` | Law statistics |
147
- | `parse_article_links` | Parse in-text legal references |
148
- | `get_external_links` | Generate external links |
149
- | `analyze_document` | Document analysis with legal context |
150
-
151
- ### Specialized: Tax & Customs (4)
152
-
153
- | Tool | Description |
154
- |------|-------------|
155
- | `search_tax_tribunal_decisions` | Tax tribunal decision search |
156
- | `get_tax_tribunal_decision_text` | Tax tribunal decision full text |
157
- | `search_customs_interpretations` | Customs interpretation search |
158
- | `get_customs_interpretation_text` | Customs interpretation full text |
159
-
160
- ### Specialized: Constitutional & Admin Appeals (4)
161
-
162
- | Tool | Description |
163
- |------|-------------|
164
- | `search_constitutional_decisions` | Constitutional Court decision search |
165
- | `get_constitutional_decision_text` | Constitutional Court decision full text |
166
- | `search_admin_appeals` | Administrative appeal decision search |
167
- | `get_admin_appeal_text` | Administrative appeal decision full text |
168
-
169
- ### Specialized: Committee Decisions (8)
170
-
171
- | Tool | Description |
172
- |------|-------------|
173
- | `search_ftc_decisions` | Fair Trade Commission decision search |
174
- | `get_ftc_decision_text` | Fair Trade Commission decision full text |
175
- | `search_pipc_decisions` | Privacy Commission decision search |
176
- | `get_pipc_decision_text` | Privacy Commission decision full text |
177
- | `search_nlrc_decisions` | Labor Relations Commission decision search |
178
- | `get_nlrc_decision_text` | Labor Relations Commission decision full text |
179
- | `search_acr_decisions` | Board of Audit & Inspection decision search |
180
- | `get_acr_decision_text` | Board of Audit & Inspection decision full text |
181
-
182
- ### Specialized: Special Admin Appeals (4) `NEW`
183
-
184
- | Tool | Description |
185
- |------|-------------|
186
- | `search_acr_special_appeals` | Special administrative appeal search |
187
- | `get_acr_special_appeal_text` | Special administrative appeal full text |
188
- | `search_appeal_review_decisions` | Appeal review decision search |
189
- | `get_appeal_review_decision_text` | Appeal review decision full text |
190
-
191
- ### Law-Ordinance Linkage (4) `NEW`
192
-
193
- | Tool | Description |
194
- |------|-------------|
195
- | `get_linked_ordinances` | Find ordinances linked to a law |
196
- | `get_linked_ordinance_articles` | Get linked ordinance article details |
197
- | `get_delegated_laws` | Find laws delegating to ordinances |
198
- | `get_linked_laws_from_ordinance` | Find parent laws from an ordinance |
199
-
200
- ### Treaties (2) `NEW`
201
-
202
- | Tool | Description |
203
- |------|-------------|
204
- | `search_treaties` | Treaty search |
205
- | `get_treaty_text` | Treaty full text |
206
-
207
- ### Institutional Rules (6) `NEW`
208
-
209
- | Tool | Description |
210
- |------|-------------|
211
- | `search_school_rules` | School rule search |
212
- | `get_school_rule_text` | School rule full text |
213
- | `search_public_corp_rules` | Public corporation rule search |
214
- | `get_public_corp_rule_text` | Public corporation rule full text |
215
- | `search_public_institution_rules` | Public institution rule search |
216
- | `get_public_institution_rule_text` | Public institution rule full text |
217
-
218
- ### Knowledge Base (7)
219
-
220
- | Tool | Description |
221
- |------|-------------|
222
- | `get_legal_term_kb` | Legal terminology search |
223
- | `get_legal_term_detail` | Term definition |
224
- | `get_daily_term` | Everyday language search |
225
- | `get_daily_to_legal` | Everyday → legal term mapping |
226
- | `get_legal_to_daily` | Legal → everyday term mapping |
227
- | `get_term_articles` | Articles using a term |
228
- | `get_related_laws` | Related laws |
229
-
230
- ### Chain Tools (8)
231
-
232
- Composite research workflows — multiple tools in a single call.
233
-
234
- | Tool | Workflow |
235
- |------|----------|
236
- | `chain_law_system` | Search → 3-tier comparison → batch articles |
237
- | `chain_action_basis` | Law system → interpretations → precedents → appeals |
238
- | `chain_dispute_prep` | Precedents + appeals + specialized decisions |
239
- | `chain_amendment_track` | Old/new comparison + article history |
240
- | `chain_ordinance_compare` | Parent law → nationwide ordinance search |
241
- | `chain_full_research` | AI search → statutes → precedents → interpretations |
242
- | `chain_procedure_detail` | Law system → annexes → enforcement rule annexes |
243
- | `chain_document_review` | Document analysis → related laws → precedents |
244
-
245
- ### Other (10)
246
-
247
- | Tool | Description |
248
- |------|-------------|
249
- | `search_ai_law` | Natural language AI search |
250
- | `search_english_law` | English law search |
251
- | `get_english_law_text` | English law full text |
252
- | `search_historical_law` | Historical law search |
253
- | `get_historical_law` | Historical law full text |
254
- | `search_legal_terms` | Legal dictionary search |
255
- | `get_law_system_tree` | Law system tree visualization |
256
- | `get_law_abbreviations` | Law abbreviation list |
257
- | `get_article_detail` | Single article detail retrieval |
258
- | `compare_admin_rule_old_new` | Admin rule old vs. new comparison |
259
-
260
- ---
261
-
262
- ## Usage Examples
132
+ ## 사용 예시
263
133
 
264
134
  ```
265
- User: "관세법 제38조 알려줘"
266
- → search_law("관세법") → get_law_text(mst, jo="003800")
135
+ "관세법 제38조 알려줘"
136
+ → search_law("관세법") → MST 획득 → get_law_text(mst, jo="003800")
267
137
 
268
- User: "화관법 최근 개정 비교"
269
- → "화관법" → "화학물질관리법" auto-resolved → compare_old_new(mst)
138
+ "화관법 최근 개정 비교"
139
+ → "화관법" → "화학물질관리법" 자동 변환 → compare_old_new(mst)
270
140
 
271
- User: "근로기준법 제74조 해석례"
141
+ "근로기준법 제74조 해석례"
272
142
  → search_interpretations("근로기준법 제74조") → get_interpretation_text(id)
273
143
 
274
- User: "산업안전보건법 별표1 내용"
275
- → get_annexes("산업안전보건법 별표1") → HWPX download → Markdown table
144
+ "산업안전보건법 별표1 내용 알려줘"
145
+ → get_annexes(lawName="산업안전보건법 별표1") → HWPX 파일 다운로드 표/텍스트 Markdown 변환
276
146
  ```
277
147
 
278
148
  ---
279
149
 
280
- ## Environment Variables
150
+ ## 도구 목록 (89개)
151
+
152
+ | 카테고리 | 개수 | 주요 도구 |
153
+ |----------|------|----------|
154
+ | **검색** | 11 | `search_law`, `search_precedents`, `search_all`, `get_annexes` |
155
+ | **조회** | 9 | `get_law_text`, `get_batch_articles`, `compare_old_new`, `get_three_tier` |
156
+ | **분석** | 10 | `compare_articles`, `get_law_tree`, `summarize_precedent`, `analyze_document` |
157
+ | **전문: 조세/관세** | 4 | `search_tax_tribunal_decisions`, `search_customs_interpretations` |
158
+ | **전문: 헌재/행심** | 4 | `search_constitutional_decisions`, `search_admin_appeals` |
159
+ | **전문: 위원회 결정** | 8 | 공정위, 개보위, 노동위, 감사원 |
160
+ | **특별행정심판** | 4 | `search_acr_special_appeals`, `search_appeal_review_decisions` |
161
+ | **법령-자치법규 연계** | 4 | `get_linked_ordinances`, `get_delegated_laws` |
162
+ | **조약** | 2 | `search_treaties`, `get_treaty_text` |
163
+ | **학칙/공단/공공기관** | 6 | `search_school_rules`, `search_public_corp_rules`, `search_public_institution_rules` |
164
+ | **지식베이스** | 7 | `get_legal_term_kb`, `get_daily_to_legal`, `get_related_laws` |
165
+ | **체인** | 8 | `chain_full_research`, `chain_law_system`, `chain_document_review` |
166
+ | **메타** | 2 | `discover_tools`, `execute_tool` (lite 프로필용) |
167
+ | **기타** | 10 | AI 검색, 영문법령, 연혁법령, 법령용어, 약칭, 법체계도, 행정규칙비교 |
168
+
169
+ 전체 도구 상세는 [영문 README](./README-EN.md#tool-categories-89-total) 참조.
281
170
 
282
- | Variable | Required | Default | Description |
283
- |----------|----------|---------|-------------|
284
- | `LAW_OC` | Yes | — | 법제처 API key ([get one free](https://open.law.go.kr/LSO/openApi/guideResult.do)) |
285
- | `PORT` | No | 3000 | HTTP server port |
286
- | `CORS_ORIGIN` | No | `*` | CORS allowed origin |
287
- | `RATE_LIMIT_RPM` | No | 60 | Requests per minute per IP |
171
+ ---
172
+
173
+ ## 주요 특징
288
174
 
289
- ## Documentation
175
+ - **89개 법률 도구** — 법령, 판례, 행정규칙, 자치법규, 헌재결정, 조세심판, 관세해석, 조약, 학칙/공단/공공기관 규정, 법령용어
176
+ - **MCP + CLI** — Claude Desktop에서도, 터미널에서도 같은 89개 도구 사용
177
+ - **법률 도메인 특화** — 약칭 자동 인식(`화관법` → `화학물질관리법`), 조문번호 변환(`제38조` ↔ `003800`), 3단 위임 구조 시각화
178
+ - **별표/별지서식 본문 추출** — HWPX·HWP 파일 자동 다운로드 → 표/텍스트를 Markdown 변환
179
+ - **8개 체인 도구** — 복합 리서치를 한 번의 호출로 (예: `chain_full_research`: AI검색→법령→판례→해석)
180
+ - **도구 프로필** — 웹 클라이언트용 lite(14개), 파워유저용 full(89개) 자동 선택
181
+ - **캐시** — 검색 1시간, 조문 24시간 TTL
182
+ - **원격 엔드포인트** — 설치 없이 `https://korean-law-mcp.fly.dev/mcp`로 바로 사용
290
183
 
291
- - [docs/API.md](docs/API.md) — 87-tool reference
292
- - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — System design
293
- - [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — Development guide
184
+ ---
294
185
 
295
- ## Credits
186
+ ## 문서
296
187
 
297
- - [법제처](https://www.law.go.kr) Open API Korea's official legal database
298
- - [Anthropic](https://anthropic.com) — Model Context Protocol
299
- - [kordoc](https://github.com/chrisryugj/kordoc) — HWP/HWPX parser (same author)
188
+ - [docs/API.md](docs/API.md) 89개 도구 레퍼런스 (프로필 포함)
189
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — 시스템 설계
190
+ - [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — 개발 가이드
300
191
 
301
- ## License
192
+ ## 라이선스
302
193
 
303
194
  [MIT](./LICENSE)
304
195
 
305
196
  ---
306
197
 
307
- <sub>Made by a Korean civil servant @ 광진구청 AI동호회 AI.Do</sub>
198
+ <sub>Made by 류주임 @ 광진구청 AI동호회 AI.Do</sub>
package/build/index.js CHANGED
@@ -13,9 +13,9 @@ import { VERSION } from "./version.js";
13
13
  const LAW_OC = process.env.LAW_OC || "";
14
14
  const apiClient = new LawApiClient({ apiKey: LAW_OC });
15
15
  // MCP 서버 팩토리 (HTTP 모드: 세션마다 새 인스턴스 필요)
16
- function createServer() {
16
+ function createServer(profile) {
17
17
  const s = new Server({ name: "korean-law", version: VERSION }, { capabilities: { tools: {} } });
18
- registerTools(s, apiClient);
18
+ registerTools(s, apiClient, profile ?? "full");
19
19
  return s;
20
20
  }
21
21
  // 서버 시작
@@ -1,11 +1,11 @@
1
1
  /**
2
- * 별표 파일 파서 (HWPX / HWP / PDF 분기)
2
+ * 별표 파일 파서 kordoc 위임
3
3
  *
4
- * - HWPX (신형): hwpx-parser.ts (manifest 멀티섹션, colSpan/rowSpan, 중첩 테이블)
5
- * - HWP (구형): hwp5-parser.ts (OLE2 직접 파싱, UTF-16LE 텍스트, 레코드 기반 테이블)
6
- * - PDF: pdf-parser.ts (pdfjs-dist 서버사이드 텍스트 추출)
4
+ * HWPX/HWP5/PDF 모두 kordoc 통합 파서에 위임.
5
+ * kordoc은 colAddr/rowAddr 기반 HWP5 배치, PDF 라인+클러스터 이중 테이블 감지,
6
+ * ZIP bomb 방지, 깨진 ZIP 복구 등 강화된 파싱 기능을 제공.
7
7
  *
8
- * 참고: https://github.com/roboco-io/hwp2md
8
+ * @see https://github.com/chrisryugj/kordoc
9
9
  */
10
10
  export interface AnnexParseResult {
11
11
  success: boolean;
@@ -1,90 +1,28 @@
1
1
  /**
2
- * 별표 파일 파서 (HWPX / HWP / PDF 분기)
2
+ * 별표 파일 파서 kordoc 위임
3
3
  *
4
- * - HWPX (신형): hwpx-parser.ts (manifest 멀티섹션, colSpan/rowSpan, 중첩 테이블)
5
- * - HWP (구형): hwp5-parser.ts (OLE2 직접 파싱, UTF-16LE 텍스트, 레코드 기반 테이블)
6
- * - PDF: pdf-parser.ts (pdfjs-dist 서버사이드 텍스트 추출)
4
+ * HWPX/HWP5/PDF 모두 kordoc 통합 파서에 위임.
5
+ * kordoc은 colAddr/rowAddr 기반 HWP5 배치, PDF 라인+클러스터 이중 테이블 감지,
6
+ * ZIP bomb 방지, 깨진 ZIP 복구 등 강화된 파싱 기능을 제공.
7
7
  *
8
- * 참고: https://github.com/roboco-io/hwp2md
8
+ * @see https://github.com/chrisryugj/kordoc
9
9
  */
10
- import { parseHwpxDocument } from "./hwpx-parser.js";
11
- import { parseHwp5Document } from "./hwp5-parser.js";
12
- // ─── 매직바이트 감지 ─────────────────────────────────
13
- function isHwpxFile(buffer) {
14
- const bytes = new Uint8Array(buffer.slice(0, 4));
15
- return bytes[0] === 0x50 && bytes[1] === 0x4b && bytes[2] === 0x03 && bytes[3] === 0x04;
16
- }
17
- function isOldHwpFile(buffer) {
18
- const bytes = new Uint8Array(buffer.slice(0, 4));
19
- return bytes[0] === 0xd0 && bytes[1] === 0xcf && bytes[2] === 0x11 && bytes[3] === 0xe0;
20
- }
21
- function isPdfFile(buffer) {
22
- const bytes = new Uint8Array(buffer.slice(0, 4));
23
- return bytes[0] === 0x25 && bytes[1] === 0x50 && bytes[2] === 0x44 && bytes[3] === 0x46;
24
- }
10
+ import { parse } from "kordoc";
25
11
  // ─── 메인 엔트리 ─────────────────────────────────────
26
12
  export async function parseAnnexFile(buffer) {
27
- if (isHwpxFile(buffer)) {
28
- return parseHwpx(buffer);
29
- }
30
- if (isOldHwpFile(buffer)) {
31
- return parseHwp(buffer);
32
- }
33
- if (isPdfFile(buffer)) {
34
- return parsePdf(buffer);
35
- }
36
- return { success: false, fileType: "unknown", error: "지원하지 않는 파일 형식입니다." };
37
- }
38
- // ─── HWPX 파서 (hwpx-parser.ts 위임) ────────────────
39
- async function parseHwpx(buffer) {
40
- try {
41
- const markdown = await parseHwpxDocument(buffer);
42
- return { success: true, fileType: "hwpx", markdown };
43
- }
44
- catch (err) {
45
- return { success: false, fileType: "hwpx", error: err instanceof Error ? err.message : "HWPX 파싱 실패" };
46
- }
47
- }
48
- // ─── 구형 HWP 파서 (hwp5-parser.ts 위임) ────────────
49
- async function parseHwp(buffer) {
50
- try {
51
- const markdown = parseHwp5Document(Buffer.from(buffer));
52
- return { success: true, fileType: "hwp", markdown };
53
- }
54
- catch (err) {
55
- return { success: false, fileType: "hwp", error: err instanceof Error ? err.message : "HWP 파싱 실패" };
56
- }
57
- }
58
- // ─── PDF 파서 (pdf-parser.ts 위임) ──────────────────
59
- async function parsePdf(buffer) {
60
- try {
61
- const { parsePdfDocument } = await import("./pdf-parser.js");
62
- const result = await parsePdfDocument(buffer);
63
- if (result.isImageBased) {
64
- return {
65
- success: false,
66
- fileType: "pdf",
67
- isImageBased: true,
68
- pageCount: result.pageCount,
69
- error: result.error,
70
- };
71
- }
72
- if (!result.success || !result.markdown) {
73
- return {
74
- success: false,
75
- fileType: "pdf",
76
- pageCount: result.pageCount,
77
- error: result.error || "PDF 텍스트 추출 실패",
78
- };
79
- }
13
+ const result = await parse(buffer);
14
+ if (result.success) {
80
15
  return {
81
16
  success: true,
82
- fileType: "pdf",
17
+ fileType: result.fileType,
83
18
  markdown: result.markdown,
84
- pageCount: result.pageCount,
85
19
  };
86
20
  }
87
- catch (err) {
88
- return { success: false, fileType: "pdf", error: err instanceof Error ? err.message : "PDF 파싱 실패" };
89
- }
21
+ return {
22
+ success: false,
23
+ fileType: result.fileType,
24
+ isImageBased: result.isImageBased,
25
+ pageCount: result.pageCount,
26
+ error: result.error,
27
+ };
90
28
  }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * 도구 프로필 — 클라이언트별 도구 노출 제어
3
+ *
4
+ * lite: 체인 중심 14개 (Claude 웹 등 컨텍스트 제한 클라이언트용)
5
+ * full: 87개 전체 (Claude Code, STDIO 등 파워 클라이언트용)
6
+ */
7
+ import type { McpTool } from "./types.js";
8
+ export type ToolProfile = "lite" | "full";
9
+ /** 도구 카테고리 매핑 (discover_tools용) */
10
+ export declare const TOOL_CATEGORIES: Record<string, string[]>;
11
+ /** 프로필 파싱 (잘못된 값이면 full) */
12
+ export declare function parseProfile(value: string | undefined): ToolProfile;
13
+ /** 프로필에 맞는 도구 필터링 */
14
+ export declare function filterToolsByProfile(tools: McpTool[], profile: ToolProfile): McpTool[];
@@ -0,0 +1,76 @@
1
+ /**
2
+ * 도구 프로필 — 클라이언트별 도구 노출 제어
3
+ *
4
+ * lite: 체인 중심 14개 (Claude 웹 등 컨텍스트 제한 클라이언트용)
5
+ * full: 87개 전체 (Claude Code, STDIO 등 파워 클라이언트용)
6
+ */
7
+ /**
8
+ * lite 프로필에 노출할 도구 목록
9
+ * - 체인 8개: 내부에서 하위 도구를 직접 호출하므로 기능 손실 없음
10
+ * - 핵심 직접 도구 4개: 체인으로 커버 안 되는 단순 조회용
11
+ * - 메타 도구 2개: discover_tools + execute_tool (특수 도구 접근용)
12
+ */
13
+ const LITE_TOOLS = new Set([
14
+ // 체인 도구 — 80%+ 유스케이스 커버
15
+ "chain_full_research",
16
+ "chain_law_system",
17
+ "chain_action_basis",
18
+ "chain_dispute_prep",
19
+ "chain_amendment_track",
20
+ "chain_ordinance_compare",
21
+ "chain_procedure_detail",
22
+ "chain_document_review",
23
+ // 핵심 직접 도구 — 단순 조회
24
+ "search_law",
25
+ "get_law_text",
26
+ "search_precedents",
27
+ "get_precedent_text",
28
+ // 메타 도구 — 나머지 73개 접근용
29
+ "discover_tools",
30
+ "execute_tool",
31
+ ]);
32
+ /** 도구 카테고리 매핑 (discover_tools용) */
33
+ export const TOOL_CATEGORIES = {
34
+ "법령검색": ["search_law", "search_all", "advanced_search", "suggest_law_names", "search_ai_law"],
35
+ "법령조회": ["get_law_text", "get_article_detail", "get_batch_articles", "get_article_with_precedents"],
36
+ "행정규칙": ["search_admin_rule", "get_admin_rule", "compare_admin_rule_old_new"],
37
+ "자치법규": ["search_ordinance", "get_ordinance"],
38
+ "법령연계": ["get_linked_ordinances", "get_linked_ordinance_articles", "get_delegated_laws", "get_linked_laws_from_ordinance"],
39
+ "비교분석": ["compare_old_new", "get_three_tier", "compare_articles"],
40
+ "별표서식": ["get_annexes"],
41
+ "법체계": ["get_law_tree", "get_law_system_tree"],
42
+ "통계링크": ["get_law_statistics", "get_external_links", "parse_article_links"],
43
+ "이력": ["get_article_history", "get_law_history", "get_historical_law", "search_historical_law"],
44
+ "판례": ["search_precedents", "get_precedent_text", "summarize_precedent", "extract_precedent_keywords", "find_similar_precedents"],
45
+ "해석례": ["search_interpretations", "get_interpretation_text"],
46
+ "조세심판": ["search_tax_tribunal_decisions", "get_tax_tribunal_decision_text"],
47
+ "관세": ["search_customs_interpretations", "get_customs_interpretation_text"],
48
+ "헌재": ["search_constitutional_decisions", "get_constitutional_decision_text"],
49
+ "행정심판": ["search_admin_appeals", "get_admin_appeal_text"],
50
+ "공정위": ["search_ftc_decisions", "get_ftc_decision_text"],
51
+ "개인정보위": ["search_pipc_decisions", "get_pipc_decision_text"],
52
+ "노동위": ["search_nlrc_decisions", "get_nlrc_decision_text"],
53
+ "권익위": ["search_acr_decisions", "get_acr_decision_text"],
54
+ "소청심사": ["search_appeal_review_decisions", "get_appeal_review_decision_text"],
55
+ "권익위심판": ["search_acr_special_appeals", "get_acr_special_appeal_text"],
56
+ "학칙": ["search_school_rules", "get_school_rule_text"],
57
+ "공사공단": ["search_public_corp_rules", "get_public_corp_rule_text"],
58
+ "공공기관": ["search_public_institution_rules", "get_public_institution_rule_text"],
59
+ "조약": ["search_treaties", "get_treaty_text"],
60
+ "영문법령": ["search_english_law", "get_english_law_text"],
61
+ "용어": ["search_legal_terms", "get_legal_term_kb", "get_legal_term_detail", "get_daily_term", "get_daily_to_legal", "get_legal_to_daily", "get_term_articles", "get_related_laws"],
62
+ "문서분석": ["analyze_document"],
63
+ "유틸리티": ["parse_jo_code", "get_law_abbreviations"],
64
+ };
65
+ /** 프로필 파싱 (잘못된 값이면 full) */
66
+ export function parseProfile(value) {
67
+ if (value === "lite")
68
+ return "lite";
69
+ return "full";
70
+ }
71
+ /** 프로필에 맞는 도구 필터링 */
72
+ export function filterToolsByProfile(tools, profile) {
73
+ if (profile === "full")
74
+ return tools;
75
+ return tools.filter(t => LITE_TOOLS.has(t.name));
76
+ }
@@ -2,4 +2,5 @@
2
2
  * Streamable HTTP 서버 - 리모트 배포용 (MCP 표준)
3
3
  */
4
4
  import type { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
- export declare function startHTTPServer(createServer: () => Server, port: number): Promise<void>;
5
+ import { type ToolProfile } from "../lib/tool-profiles.js";
6
+ export declare function startHTTPServer(createServer: (profile?: ToolProfile) => Server, port: number): Promise<void>;