korean-law-mcp 2.2.0 → 2.3.1
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 +124 -217
- package/build/index.js +2 -2
- package/build/lib/annex-file-parser.d.ts +5 -5
- package/build/lib/annex-file-parser.js +16 -78
- package/build/lib/tool-profiles.d.ts +14 -0
- package/build/lib/tool-profiles.js +76 -0
- package/build/server/http-server.d.ts +2 -1
- package/build/server/http-server.js +14 -5
- package/build/tool-registry.d.ts +4 -2
- package/build/tool-registry.js +36 -13
- package/build/tools/admin-rule.js +1 -1
- package/build/tools/annex.js +22 -2
- package/build/tools/chains.js +10 -0
- package/build/tools/customs-interpretations.js +1 -1
- package/build/tools/interpretations.js +1 -1
- package/build/tools/law-tree.js +1 -1
- package/build/tools/meta-tools.d.ts +19 -0
- package/build/tools/meta-tools.js +82 -0
- package/build/tools/ordinance-search.js +1 -1
- package/build/tools/ordinance.js +1 -1
- package/build/tools/tax-tribunal-decisions.js +1 -1
- package/build/tools/treaties.js +1 -1
- package/package.json +2 -3
- package/build/lib/hwp5-parser.d.ts +0 -2
- package/build/lib/hwp5-parser.js +0 -176
- package/build/lib/hwp5-record.d.ts +0 -24
- package/build/lib/hwp5-record.js +0 -101
- package/build/lib/hwpx-parser.d.ts +0 -2
- package/build/lib/hwpx-parser.js +0 -199
- package/build/lib/hwpx-table.d.ts +0 -25
- package/build/lib/hwpx-table.js +0 -154
- package/build/lib/pdf-parser.d.ts +0 -23
- package/build/lib/pdf-parser.js +0 -213
package/README.md
CHANGED
|
@@ -1,47 +1,78 @@
|
|
|
1
1
|
# Korean Law MCP
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**대한민국 법령 검색·조회·분석 89개 도구** — 법령, 판례, 행정규칙, 자치법규, 조약, 해석례를 AI 어시스턴트나 터미널에서 바로 사용.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/korean-law-mcp)
|
|
6
6
|
[](https://modelcontextprotocol.io)
|
|
7
7
|
[](LICENSE)
|
|
8
|
-
[](https://www.typescriptlang.org/)
|
|
9
8
|
|
|
10
|
-
>
|
|
9
|
+
> 법제처 Open API 기반 MCP 서버 + CLI. Claude Desktop, Cursor, Windsurf, Zed, Claude.ai 등에서 바로 사용 가능.
|
|
11
10
|
|
|
12
|
-
[
|
|
11
|
+
[English](./README-EN.md)
|
|
12
|
+
|
|
13
|
+

|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
16
|
-
##
|
|
17
|
+
## v2.3.1 변경사항
|
|
18
|
+
|
|
19
|
+
- **URL 쿼리 API 키 지원** — 원격 MCP 접속 시 `?oc=your-key`로 API 키를 URL에 포함 가능. 매 요청마다 키를 전달할 필요 없이 세션 전체에 자동 적용. Claude.ai 등 커스텀 헤더 설정이 어려운 웹 클라이언트에서 유용.
|
|
20
|
+
- **체인 도구 자동 전문 조회** — `chain_ordinance_compare`가 자치법규 검색 후 상위 1건 전문을 자동 조회하여 반환. 별도로 `get_ordinance`를 호출할 필요 없음.
|
|
21
|
+
- **lite 프로필 도구 라우팅 개선** — 체인/메타 도구 description을 INPUT 의도 기반으로 재작성. 예시 포함으로 Claude 웹이 자치법규 검색·조회 등 올바른 도구를 선택하도록 개선.
|
|
22
|
+
- **도구 힌트 execute_tool 경로 통일** — 비lite 도구 안내를 `execute_tool()` 호출 예시로 변경. Claude 웹이 존재하지 않는 도구를 직접 호출하는 문제 방지.
|
|
23
|
+
|
|
24
|
+
<details>
|
|
25
|
+
<summary>v2.3.0 변경사항</summary>
|
|
26
|
+
|
|
27
|
+
- **도구 프로필 (lite/full)** — 웹 클라이언트(Claude.ai 등)용 lite 프로필 도입. 89개 → 14개로 자동 축소하여 컨텍스트 소비 87% 절감. `/mcp?profile=lite`로 사용.
|
|
28
|
+
- **체인 8개** + 핵심 직접 도구 4개 + 메타 도구 2개 = 14개로 동일 기능 커버
|
|
29
|
+
- `discover_tools`: 의도/카테고리로 숨겨진 전문 도구 검색
|
|
30
|
+
- `execute_tool`: discover로 찾은 도구를 프록시 실행
|
|
31
|
+
- **kordoc 통합 파서** — 자체 HWP5/HWPX/PDF 파서 5개를 [kordoc](https://github.com/chrisryugj/kordoc) 통합 파서로 교체. 의존성 경량화.
|
|
32
|
+
|
|
33
|
+
</details>
|
|
34
|
+
|
|
35
|
+
<details>
|
|
36
|
+
<summary>v2.2.0 변경사항</summary>
|
|
37
|
+
|
|
38
|
+
- **23개 신규 도구 (64 → 87)** — 조약, 법령-자치법규 연계, 학칙/공단/공공기관 규정, 특별행정심판, 감사원 결정, 조항상세, 문서분석, 행정규칙 신구대조 등 대폭 확장.
|
|
39
|
+
- **문서분석 엔진** — 8종 문서유형 분류, 17개 리스크규칙, 금액/기간 추출, 조항 충돌 탐지.
|
|
40
|
+
- **법령-자치법규 연계 (4개 도구)** — 법률↔조례 위임 체인을 양방향 추적.
|
|
41
|
+
- **조약 지원 (2개 도구)** — 대한민국이 체결한 양자/다자 조약 검색 및 전문 조회.
|
|
42
|
+
- **보안 강화** — CORS 오리진 제어, API 키 헤더 전용, 보안 헤더, 세션 ID 마스킹.
|
|
43
|
+
|
|
44
|
+
</details>
|
|
17
45
|
|
|
18
|
-
|
|
46
|
+
<details>
|
|
47
|
+
<summary>v1.8.0 – v1.9.0 기능</summary>
|
|
19
48
|
|
|
20
|
-
|
|
49
|
+
- **체인 도구 8개** — 복합 리서치를 한 번의 호출로: `chain_full_research`(AI검색→법령→판례→해석), `chain_law_system`, `chain_action_basis`, `chain_dispute_prep`, `chain_amendment_track`, `chain_ordinance_compare`, `chain_procedure_detail`.
|
|
50
|
+
- **일괄 조문 조회** — `get_batch_articles`가 `laws` 배열로 복수 법령 한 번에 조회.
|
|
51
|
+
- **AI 검색 법령종류 필터** — `search_ai_law`에 `lawTypes` 필터 추가.
|
|
52
|
+
- **구조화 에러 포맷** — `[에러코드] + 도구명 + 제안` 형식으로 64개 도구 통일.
|
|
53
|
+
- **HWP 테이블 수정** — 구형 HWP 파서에서 `paragraph.controls[].content` 경로의 테이블 추출 지원.
|
|
54
|
+
|
|
55
|
+
</details>
|
|
21
56
|
|
|
22
57
|
---
|
|
23
58
|
|
|
24
|
-
##
|
|
59
|
+
## 왜 만들었나
|
|
60
|
+
|
|
61
|
+
대한민국에는 **1,600개 이상의 현행 법률**, **10,000개 이상의 행정규칙**, 그리고 대법원·헌법재판소·조세심판원·관세청까지 이어지는 방대한 판례 체계가 있습니다. 이 모든 게 [법제처](https://www.law.go.kr)라는 하나의 사이트에 있지만, 개발자 경험은 최악입니다.
|
|
25
62
|
|
|
26
|
-
|
|
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`
|
|
63
|
+
이 프로젝트는 그 전체 법령 시스템을 **89개 구조화된 도구**로 감싸서, AI 어시스턴트나 스크립트에서 바로 호출할 수 있게 만듭니다. 법제처를 백 번째 수동 검색하다 지친 공무원이 만들었습니다.
|
|
33
64
|
|
|
34
65
|
---
|
|
35
66
|
|
|
36
|
-
##
|
|
67
|
+
## 빠른 시작
|
|
37
68
|
|
|
38
|
-
###
|
|
69
|
+
### MCP 서버 (Claude Desktop / Cursor / Windsurf)
|
|
39
70
|
|
|
40
71
|
```bash
|
|
41
72
|
npm install -g korean-law-mcp
|
|
42
73
|
```
|
|
43
74
|
|
|
44
|
-
|
|
75
|
+
MCP 클라이언트 설정에 추가:
|
|
45
76
|
|
|
46
77
|
```json
|
|
47
78
|
{
|
|
@@ -56,29 +87,49 @@ Add to your MCP client config:
|
|
|
56
87
|
}
|
|
57
88
|
```
|
|
58
89
|
|
|
59
|
-
|
|
90
|
+
API 키는 [법제처 Open API](https://open.law.go.kr/LSO/openApi/guideResult.do)에서 무료 발급.
|
|
60
91
|
|
|
61
|
-
|
|
|
62
|
-
|
|
92
|
+
| 클라이언트 | 설정 파일 |
|
|
93
|
+
|-----------|----------|
|
|
63
94
|
| Claude Desktop | `%APPDATA%\Claude\claude_desktop_config.json` (Win) / `~/Library/Application Support/Claude/claude_desktop_config.json` (Mac) |
|
|
64
95
|
| Cursor | `.cursor/mcp.json` |
|
|
65
96
|
| Windsurf | `.windsurf/mcp.json` |
|
|
66
97
|
| Continue | `~/.continue/config.json` |
|
|
67
98
|
| Zed | `~/.config/zed/settings.json` |
|
|
68
99
|
|
|
69
|
-
###
|
|
100
|
+
### 원격 MCP (설치 없이 바로)
|
|
101
|
+
|
|
102
|
+
API 키를 URL에 포함하여 바로 사용:
|
|
70
103
|
|
|
71
104
|
```json
|
|
72
105
|
{
|
|
73
106
|
"mcpServers": {
|
|
74
107
|
"korean-law": {
|
|
75
|
-
"url": "https://korean-law-mcp.fly.dev/mcp"
|
|
108
|
+
"url": "https://korean-law-mcp.fly.dev/mcp?oc=your-api-key"
|
|
76
109
|
}
|
|
77
110
|
}
|
|
78
111
|
}
|
|
79
112
|
```
|
|
80
113
|
|
|
81
|
-
|
|
114
|
+
**Claude.ai 등 웹 클라이언트** — 컨텍스트 절약을 위해 lite 프로필 권장:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
https://korean-law-mcp.fly.dev/mcp?profile=lite&oc=your-api-key
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
> lite 프로필은 체인 8개 + 핵심 4개 + 메타 2개 = **14개 도구**로 동일 기능 커버. 특수 도구가 필요하면 `discover_tools` → `execute_tool`로 접근.
|
|
121
|
+
|
|
122
|
+
**API 키 전달 방법** (우선순위순):
|
|
123
|
+
|
|
124
|
+
| 방법 | 예시 | 설명 |
|
|
125
|
+
|------|------|------|
|
|
126
|
+
| URL 쿼리 | `?oc=your-key` | 웹 클라이언트에서 가장 간편. 세션 전체에 자동 적용 |
|
|
127
|
+
| HTTP 헤더 | `apikey: your-key` | `law-oc`, `x-api-key`, `Authorization: Bearer` 등도 지원 |
|
|
128
|
+
| 도구 파라미터 | `apiKey: "your-key"` | 개별 도구 호출 시 직접 전달 |
|
|
129
|
+
|
|
130
|
+
> API 키는 [법제처 Open API](https://open.law.go.kr/LSO/openApi/guideResult.do)에서 무료 발급.
|
|
131
|
+
|
|
132
|
+
### CLI
|
|
82
133
|
|
|
83
134
|
```bash
|
|
84
135
|
npm install -g korean-law-mcp
|
|
@@ -87,221 +138,77 @@ export LAW_OC=your-api-key
|
|
|
87
138
|
korean-law search_law --query "관세법"
|
|
88
139
|
korean-law get_law_text --mst 160001 --jo "제38조"
|
|
89
140
|
korean-law search_precedents --query "부당해고"
|
|
90
|
-
korean-law list #
|
|
91
|
-
korean-law list --category 판례 #
|
|
92
|
-
korean-law help search_law #
|
|
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
|
|
141
|
+
korean-law list # 89개 전체 도구 목록
|
|
142
|
+
korean-law list --category 판례 # 카테고리별 필터
|
|
143
|
+
korean-law help search_law # 도구 도움말
|
|
100
144
|
```
|
|
101
145
|
|
|
102
146
|
---
|
|
103
147
|
|
|
104
|
-
##
|
|
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
|
|
148
|
+
## 사용 예시
|
|
263
149
|
|
|
264
150
|
```
|
|
265
|
-
|
|
266
|
-
→ search_law("관세법") → get_law_text(mst, jo="003800")
|
|
151
|
+
"관세법 제38조 알려줘"
|
|
152
|
+
→ search_law("관세법") → MST 획득 → get_law_text(mst, jo="003800")
|
|
267
153
|
|
|
268
|
-
|
|
269
|
-
→ "화관법" → "화학물질관리법"
|
|
154
|
+
"화관법 최근 개정 비교"
|
|
155
|
+
→ "화관법" → "화학물질관리법" 자동 변환 → compare_old_new(mst)
|
|
270
156
|
|
|
271
|
-
|
|
157
|
+
"근로기준법 제74조 해석례"
|
|
272
158
|
→ search_interpretations("근로기준법 제74조") → get_interpretation_text(id)
|
|
273
159
|
|
|
274
|
-
|
|
275
|
-
→ get_annexes("산업안전보건법 별표1") → HWPX
|
|
160
|
+
"산업안전보건법 별표1 내용 알려줘"
|
|
161
|
+
→ get_annexes(lawName="산업안전보건법 별표1") → HWPX 파일 다운로드 → 표/텍스트 Markdown 변환
|
|
276
162
|
```
|
|
277
163
|
|
|
278
164
|
---
|
|
279
165
|
|
|
280
|
-
##
|
|
166
|
+
## 도구 목록 (89개)
|
|
167
|
+
|
|
168
|
+
| 카테고리 | 개수 | 주요 도구 |
|
|
169
|
+
|----------|------|----------|
|
|
170
|
+
| **검색** | 11 | `search_law`, `search_precedents`, `search_all`, `get_annexes` |
|
|
171
|
+
| **조회** | 9 | `get_law_text`, `get_batch_articles`, `compare_old_new`, `get_three_tier` |
|
|
172
|
+
| **분석** | 10 | `compare_articles`, `get_law_tree`, `summarize_precedent`, `analyze_document` |
|
|
173
|
+
| **전문: 조세/관세** | 4 | `search_tax_tribunal_decisions`, `search_customs_interpretations` |
|
|
174
|
+
| **전문: 헌재/행심** | 4 | `search_constitutional_decisions`, `search_admin_appeals` |
|
|
175
|
+
| **전문: 위원회 결정** | 8 | 공정위, 개보위, 노동위, 감사원 |
|
|
176
|
+
| **특별행정심판** | 4 | `search_acr_special_appeals`, `search_appeal_review_decisions` |
|
|
177
|
+
| **법령-자치법규 연계** | 4 | `get_linked_ordinances`, `get_delegated_laws` |
|
|
178
|
+
| **조약** | 2 | `search_treaties`, `get_treaty_text` |
|
|
179
|
+
| **학칙/공단/공공기관** | 6 | `search_school_rules`, `search_public_corp_rules`, `search_public_institution_rules` |
|
|
180
|
+
| **지식베이스** | 7 | `get_legal_term_kb`, `get_daily_to_legal`, `get_related_laws` |
|
|
181
|
+
| **체인** | 8 | `chain_full_research`, `chain_law_system`, `chain_document_review` |
|
|
182
|
+
| **메타** | 2 | `discover_tools`, `execute_tool` (lite 프로필용) |
|
|
183
|
+
| **기타** | 10 | AI 검색, 영문법령, 연혁법령, 법령용어, 약칭, 법체계도, 행정규칙비교 |
|
|
184
|
+
|
|
185
|
+
전체 도구 상세는 [영문 README](./README-EN.md#tool-categories-89-total) 참조.
|
|
281
186
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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 |
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 주요 특징
|
|
288
190
|
|
|
289
|
-
|
|
191
|
+
- **89개 법률 도구** — 법령, 판례, 행정규칙, 자치법규, 헌재결정, 조세심판, 관세해석, 조약, 학칙/공단/공공기관 규정, 법령용어
|
|
192
|
+
- **MCP + CLI** — Claude Desktop에서도, 터미널에서도 같은 89개 도구 사용
|
|
193
|
+
- **법률 도메인 특화** — 약칭 자동 인식(`화관법` → `화학물질관리법`), 조문번호 변환(`제38조` ↔ `003800`), 3단 위임 구조 시각화
|
|
194
|
+
- **별표/별지서식 본문 추출** — HWPX·HWP 파일 자동 다운로드 → 표/텍스트를 Markdown 변환
|
|
195
|
+
- **8개 체인 도구** — 복합 리서치를 한 번의 호출로 (예: `chain_full_research`: AI검색→법령→판례→해석)
|
|
196
|
+
- **도구 프로필** — 웹 클라이언트용 lite(14개), 파워유저용 full(89개) 자동 선택
|
|
197
|
+
- **캐시** — 검색 1시간, 조문 24시간 TTL
|
|
198
|
+
- **원격 엔드포인트** — 설치 없이 `https://korean-law-mcp.fly.dev/mcp`로 바로 사용
|
|
290
199
|
|
|
291
|
-
|
|
292
|
-
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — System design
|
|
293
|
-
- [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — Development guide
|
|
200
|
+
---
|
|
294
201
|
|
|
295
|
-
##
|
|
202
|
+
## 문서
|
|
296
203
|
|
|
297
|
-
- [
|
|
298
|
-
- [
|
|
299
|
-
- [
|
|
204
|
+
- [docs/API.md](docs/API.md) — 89개 도구 레퍼런스 (프로필 포함)
|
|
205
|
+
- [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) — 시스템 설계
|
|
206
|
+
- [docs/DEVELOPMENT.md](docs/DEVELOPMENT.md) — 개발 가이드
|
|
300
207
|
|
|
301
|
-
##
|
|
208
|
+
## 라이선스
|
|
302
209
|
|
|
303
210
|
[MIT](./LICENSE)
|
|
304
211
|
|
|
305
212
|
---
|
|
306
213
|
|
|
307
|
-
<sub>Made by
|
|
214
|
+
<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
|
-
* 별표 파일 파서
|
|
2
|
+
* 별표 파일 파서 — kordoc 위임
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* HWPX/HWP5/PDF 모두 kordoc 통합 파서에 위임.
|
|
5
|
+
* kordoc은 colAddr/rowAddr 기반 HWP5 셀 배치, PDF 라인+클러스터 이중 테이블 감지,
|
|
6
|
+
* ZIP bomb 방지, 깨진 ZIP 복구 등 강화된 파싱 기능을 제공.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
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
|
-
* 별표 파일 파서
|
|
2
|
+
* 별표 파일 파서 — kordoc 위임
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* HWPX/HWP5/PDF 모두 kordoc 통합 파서에 위임.
|
|
5
|
+
* kordoc은 colAddr/rowAddr 기반 HWP5 셀 배치, PDF 라인+클러스터 이중 테이블 감지,
|
|
6
|
+
* ZIP bomb 방지, 깨진 ZIP 복구 등 강화된 파싱 기능을 제공.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* @see https://github.com/chrisryugj/kordoc
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
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
|
-
|
|
28
|
-
|
|
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:
|
|
17
|
+
fileType: result.fileType,
|
|
83
18
|
markdown: result.markdown,
|
|
84
|
-
pageCount: result.pageCount,
|
|
85
19
|
};
|
|
86
20
|
}
|
|
87
|
-
|
|
88
|
-
|
|
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
|
+
}
|