행정규칙 전문 조회가 항상 NOT_FOUND — 체인이 `행정규칙ID`를 넘기지만 API는 `행정규칙일련번호`를 받음 (법제처는 지원함)
## 요약
자연어 라우팅으로 행정규칙을 조회하면 **항상** `[NOT_FOUND] 행정규칙 전문을 조회할 수 없습니다` 가 나옵니다. 안내문이 「법제처 API 제한」을 지목하지만, **법제처는 해당 전문을 정상 제공합니다.** 체인이 `get_admin_rule` 에 넘기는 식별자가 잘못된 것이 원인입니다.
`get_admin_rule` 을 직접 호출하면 정상 동작하므로, 영향 범위는 자연어 라우팅·체인 경로입니다.
## 재현 (v4.9.0)
```bash
export LAW_OC=<인증키>
npx -y -p korean-law-mcp@4.9.0 korean-law "장기요양급여 산정방법 고시"
```
```
[라우팅] search_admin_rule — 행정규칙 키워드 → 행정규칙 검색
행정규칙 검색 결과 (총 1건):
1. 장기요양급여 제공기준 및 급여비용 산정방법 등에 관한 고시
- 행정규칙일련번호: 2100000271110
[NOT_FOUND] 행정규칙 전문을 조회할 수 없습니다.
[주의] 법제처 API 제한: 일부 행정규칙은 전문 조회가 지원되지 않습니다.
```
반면 `get_admin_rule` 에 **행정규칙일련번호**를 직접 넘기면 정상입니다.
```
execute_tool(tool_name="get_admin_rule", params={"id": "2100000271110"})
→ 약 50,000자 반환 (조문 본문 포함)
```
## 원인
`src/lib/tool-chain-config.ts`
```ts
search_admin_rule: {
detailTool: "get_admin_rule",
detailParam: "id",
idRegex: /행정규칙ID:\s*(\S+)/, // 행정규칙은 [ID] 형식이 아님
},
```
체인이 검색 결과 텍스트에서 **`행정규칙ID`** 를 뽑습니다. 그런데 법제처 `lawService.do?target=admrul&ID=` 가 받는 값은 **`행정규칙일련번호`** 입니다. 두 값은 다릅니다.
| 넘긴 값 | 응답 |
|---|---|
| `2100000279208` (행정규칙**일련번호**) | 707,733 B — `조문내용` 33블록 |
| `26273` (행정규칙**ID**) | 138 B — 빈 응답 |
`src/tools/admin-rule.ts:78` 의 스키마 설명도 같은 혼동을 담고 있습니다.
```ts
id: z.string().describe("행정규칙ID (search_admin_rule에서 획득)"),
```
`search_admin_rule` 출력이 두 값을 나란히 내보내므로(`admin-rule.ts:56-57`), 이 설명을 보는 LLM 역시 `행정규칙ID` 를 고를 가능성이 높습니다.
## 법제처는 지원합니다 — 확인 결과
`target=admrul&ID=<행정규칙일련번호>` 로 조문 본문이 정상적으로 옵니다. XML·JSON 모두 동작합니다.
```
GET /DRF/lawService.do?OC=***&target=admrul&type=XML&ID=2100000279208
→ <AdmRulService>
<행정규칙기본정보>… 조문형식여부: Y …</행정규칙기본정보>
<조문내용> × 33
<부칙> <별표> <제개정이유> <첨부파일>
```
조문 번호와 제목이 모두 들어 있어, 법령과 동일한 수준의 인용 검증이 가능합니다.
| 고시 | 인용 | 대조 결과 |
|---|---|---|
| 장기요양급여비용 청구 및 심사·지급업무 처리기준 | 제5조 | ✓ 실존 — '장기요양급여비용 청구방법 신청' |
| 〃 | 제8조 | ✓ 실존 — '장기요양급여비용 청구 전 절차' |
| 〃 | 제9999조 | ✗ 없음 (존재 범위 제1조~제28조) |
| 장기요양급여 제공기준 및 급여비용 산정방법 등에 관한 고시 | 제64조 | ✓ 실존 — '급여비용 감액산정의 원칙' |
| 〃 | 제11조의5 | ✓ 실존 — '요양보호사 보수교육' |
참고로 `조문형식여부=N` 인 행정규칙은 첨부파일로만 제공되는데, `get_admin_rule` 은 이미 그 경우를 별도 안내로 처리하고 있습니다(`admin-rule.ts:113`). 즉 「전문 조회 미지원」 안내는 그쪽 경우에만 맞고, 이번 사례(둘 다 `조문형식여부=Y`)에는 맞지 않습니다.
## 제안
**(a) 체인 식별자 수정** — 한 줄입니다.
```diff
search_admin_rule: {
detailTool: "get_admin_rule",
detailParam: "id",
- idRegex: /행정규칙ID:\s*(\S+)/,
+ idRegex: /행정규칙일련번호:\s*(\S+)/,
},
```
**(b) 스키마 설명 수정** — LLM이 직접 호출할 때 같은 실수를 하지 않도록.
```diff
-id: z.string().describe("행정규칙ID (search_admin_rule에서 획득)"),
+id: z.string().describe("행정규칙일련번호 (search_admin_rule 결과의 '행정규칙일련번호'. 13자리. '행정규칙ID'가 아님)"),
```
**(c) 안내문 조정** — 빈 응답을 곧바로 「법제처 API 제한」으로 단정하면 원인 추적이 어려워집니다. `조문형식여부` 나 응답 크기로 구분해 안내하면 좋겠습니다. 실제로 이 메시지 때문에 저희 쪽에서는 한동안 법제처의 제약으로 판단하고 우회 설계를 검토했습니다.
## 영향
행정규칙(고시·훈령·예규)을 근거로 삼는 실무 문서에서 인용 검증이 통째로 빠집니다. 예를 들어 장기요양 청구 업무는 판단 근거의 상당 부분이 법률이 아니라 고시·처리기준에 있어, 이 경로가 막히면 검증 대상의 핵심이 사각지대가 됩니다.
## 환경
- korean-law-mcp v4.9.0 (npm)
- Node v24.14.0 / macOS
- 대조는 법제처 OPEN API 직접 호출로 확인
덧붙여 #70 을 v4.9.0 으로 빠르게 반영해 주셔서 감사합니다. `「」`·`같은 법` 조응 모두 해소된 것을 확인했습니다.
```
입력: 「노인장기요양보험법」 제38조제1항 및 같은 법 시행규칙 제30조에 따라 …
[VERIFIED] 총 2건 | ✓ 2 실존 | ✗ 0 오류 | ⚠ 0 확인필요
✓ 노인장기요양보험법 제38조(재가 및 시설 급여비용의 청구 및 지급 등) 제1항 실존
✓ 노인장기요양보험법 시행규칙 제30조(장기요양급여비용의 청구 등) 실존
```
issue