Clarify Korean law setup modes to avoid credential confusion

A review found the new korean-law-search docs treated LAW_OC as an unconditional prerequisite even though the upstream remote MCP endpoint is configured separately from the local CLI/server path. This update makes the docs and regression tests mode-specific: local CLI/MCP uses LAW_OC, while the remote endpoint stays a korean-law-mcp-only url fallback without a user-supplied credential.

Constraint: Upstream korean-law-mcp uses LAW_OC on the local CLI/server path while the documented remote MCP endpoint is configured with url only
Rejected: Keep LAW_OC mandatory for every korean-law-mcp mode | contradicts upstream docs and reviewer evidence
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep README/setup/skill docs and regression tests aligned on the local-vs-remote korean-law-mcp contract
Tested: node --test scripts/skill-docs.test.js; npm install -g korean-law-mcp && korean-law list && korean-law help search_law; npx tsc --noEmit --pretty false --project /Users/jeffrey/Projects/k-skill/tsconfig.json; npm run ci; lsp_diagnostics scripts/skill-docs.test.js
Not-tested: Live remote MCP endpoint connection against https://korean-law-mcp.fly.dev/mcp
This commit is contained in:
Jeffrey (Dongkyu) Kim 2026-04-01 09:39:03 +09:00
commit e981a81e46
8 changed files with 49 additions and 18 deletions

View file

@ -23,7 +23,7 @@ Claude Code, Codex, OpenCode, OpenClaw/ClawHub 등 각종 코딩 에이전트
| 카카오톡 Mac CLI | macOS에서 kakaocli로 대화 조회, 검색, 테스트 전송, 확인 후 실제 전송 | 불필요 | [카카오톡 Mac CLI 가이드](docs/features/kakaotalk-mac.md) |
| 서울 지하철 도착정보 조회 | self-host 또는 배포 확인이 끝난 `k-skill-proxy` 경유로 역 기준 실시간 도착 예정 열차 확인 | 프록시 URL 필요 | [서울 지하철 도착정보 가이드](docs/features/seoul-subway-arrival.md) |
| 사용자 위치 미세먼지 조회 | `k-skill-proxy` 로 현재 위치 또는 지역 fallback 기준 PM10/PM2.5 확인 | 불필요 | [사용자 위치 미세먼지 조회 가이드](docs/features/fine-dust-location.md) |
| 한국 법령 검색 | `korean-law-mcp` 기반 법령/조문/판례/유권해석 조회 | 필요 | [한국 법령 검색 가이드](docs/features/korean-law-search.md) |
| 한국 법령 검색 | `korean-law-mcp` 기반 법령/조문/판례/유권해석 조회 | 로컬 CLI/MCP면 `LAW_OC` 필요, remote endpoint면 불필요 | [한국 법령 검색 가이드](docs/features/korean-law-search.md) |
| KBO 경기 결과 조회 | 날짜별 경기 일정, 결과, 팀별 필터링 | 불필요 | [KBO 결과 가이드](docs/features/kbo-results.md) |
| K리그 경기 결과 조회 | 날짜별 K리그1/K리그2 경기 결과, 팀별 필터링, 현재 순위 확인 | 불필요 | [K리그 결과 가이드](docs/features/kleague-results.md) |
| 토스증권 조회 | `tossctl` 기반 계좌 요약, 포트폴리오, 시세, 주문내역, 관심종목 조회 | 필요 | [토스증권 조회 가이드](docs/features/toss-securities.md) |

View file

@ -16,11 +16,14 @@
- 인터넷 연결
- `node` 18+
- `npm install -g korean-law-mcp`
- `LAW_OC` 환경변수
- `npm install -g korean-law-mcp` (로컬 CLI/로컬 MCP server 경로일 때)
- remote MCP endpoint를 쓸 MCP 클라이언트
무료 API key 발급처: `https://open.law.go.kr`
로컬 CLI 또는 로컬 MCP server 경로는 `LAW_OC` 가 필요하다.
remote MCP endpoint는 사용자 `LAW_OC` 없이 `url`만으로 연결한다.
```bash
npm install -g korean-law-mcp
export LAW_OC=your-api-key
@ -58,6 +61,8 @@ remote endpoint 예시:
}
```
위 remote 예시는 upstream 문서 기준으로 사용자 `LAW_OC` 를 따로 넣지 않는다. 사용자 쪽에서 준비할 것은 `url` 등록뿐이다.
## 기본 흐름
1. 질의가 법령/판례/행정해석/자치법규 중 어디에 가까운지 분류한다.
@ -79,7 +84,8 @@ korean-law search_precedents --query "부당해고"
- `화관법` 같은 약칭은 `search_law` / `search_all` 로 정식 법령명을 먼저 확인한다.
- 조문 번호가 헷갈리면 `get_law_text` 전에 법령 식별자부터 다시 확인한다.
- `LAW_OC` 가 없으면 credential resolution order에 따라 확보를 안내하고, 다른 검색 경로로 우회하지 않는다.
- 로컬 CLI/MCP 경로를 쓰는데 `LAW_OC` 가 없으면 credential resolution order에 따라 확보를 안내하고, 다른 검색 경로로 우회하지 않는다.
- remote MCP endpoint를 쓰면 사용자 `LAW_OC` 없이 `url` 등록 상태만 확인한다.
- 요약은 할 수 있지만 법률 자문처럼 단정적으로 결론을 내리지는 않는다.
## 라이브 확인 메모
@ -89,4 +95,4 @@ korean-law search_precedents --query "부당해고"
- `korean-law list`
- `korean-law help search_law`
즉, `korean-law-mcp` CLI 설치와 기본 명령 진입은 검증했다. 실제 법령 검색은 `LAW_OC` 가 준비된 환경에서 바로 이어서 사용할 수 있다.
즉, `korean-law-mcp` CLI 설치와 기본 명령 진입은 검증했다. 실제 법령 검색은 로컬 CLI/MCP 경로라면 `LAW_OC` 가 준비된 환경에서 바로 이어서 사용할 수 있고, remote MCP endpoint는 사용자 `LAW_OC` 없이 URL 등록만으로 붙일 수 있다.

View file

@ -74,6 +74,9 @@ npx --yes skills add <owner/repo> \
`korean-law-search` 는 skill 설치 후 upstream CLI/MCP도 준비해야 한다.
- 로컬 CLI/MCP 경로는 `LAW_OC` 를 채운다.
- remote endpoint는 `LAW_OC` 없이 `url`만 등록한다.
```bash
npm install -g korean-law-mcp
export LAW_OC=your-api-key

View file

@ -64,6 +64,6 @@ KSKILL_PROXY_BASE_URL=https://your-proxy.example.com
- `AIR_KOREA_OPEN_API_KEY`
- `KSKILL_PROXY_BASE_URL`
`LAW_OC``korean-law-mcp` 가 법제처 Open API 를 호출할 때 쓰는 표준 변수명이다. 프록시 운영자 문맥에서는 upstream 환경변수 `SEOUL_OPEN_API_KEY` 도 사용할 수 있다. 다만 일반 사용자/client 쪽 기본 secrets 파일에는 넣지 않는다. `KSKILL_PROXY_BASE_URL` 도 서울 지하철 route가 실제 배포된 proxy URL 로만 넣는다.
`LAW_OC``korean-law-mcp` 가 법제처 Open API 를 호출할 때 쓰는 표준 변수명이다. 이 값은 로컬 CLI/로컬 MCP server 경로에서만 사용자 쪽에 필요하고, upstream remote MCP endpoint 예시는 사용자 `LAW_OC` 없이 `url`만 등록한다. 프록시 운영자 문맥에서는 upstream 환경변수 `SEOUL_OPEN_API_KEY` 도 사용할 수 있다. 다만 일반 사용자/client 쪽 기본 secrets 파일에는 넣지 않는다. `KSKILL_PROXY_BASE_URL` 도 서울 지하철 route가 실제 배포된 proxy URL 로만 넣는다.
이 레포의 credential-bearing skill은 전부 이 정책을 전제로 작성한다. 자세한 공통 설치 절차는 [공통 설정 가이드](setup.md)를 본다.

View file

@ -1,6 +1,6 @@
# 공통 설정 가이드
`k-skill` 전체 스킬을 설치한 뒤, 인증 정보가 필요한 기능(SRT 예매, KTX 예매, 한국 법령 검색용 `LAW_OC`, self-host 프록시 운영용 서울 지하철/미세먼지 upstream key, 또는 배포 확인이 끝난 proxy URL 공유)이 있으면 이 절차를 진행하면 된다.
`k-skill` 전체 스킬을 설치한 뒤, 인증 정보가 필요한 기능(SRT 예매, KTX 예매, 한국 법령 검색의 로컬 CLI/MCP 경로`LAW_OC`, self-host 프록시 운영용 서울 지하철/미세먼지 upstream key, 또는 배포 확인이 끝난 proxy URL 공유)이 있으면 이 절차를 진행하면 된다.
## Credential resolution order
@ -35,7 +35,9 @@ chmod 0600 ~/.config/k-skill/secrets.env
서울 지하철 도착정보는 hosted public route rollout 이 끝나기 전까지 `KSKILL_PROXY_BASE_URL` 을 self-host 또는 배포 확인이 끝난 proxy URL 로 채워야 한다. 미세먼지만 쓴다면 이 값을 비워 두고 skill 기본 hosted path를 그대로 써도 된다.
한국 법령 검색은 `korean-law-mcp` 를 전제로 하므로 `LAW_OC` 를 채운 뒤 `npm install -g korean-law-mcp``korean-law list` 로 설치 상태를 확인한다.
한국 법령 검색의 로컬 CLI/MCP 경로용 `LAW_OC``korean-law-mcp` 로컬 실행에 쓴다. 로컬 CLI/MCP 경로는 `LAW_OC` 를 채운 뒤 `npm install -g korean-law-mcp``korean-law list` 로 설치 상태를 확인한다.
remote MCP endpoint는 사용자 `LAW_OC` 없이 `url`만으로 연결한다. 이 경우에도 다른 구현으로 우회하지 않고 `korean-law-mcp` endpoint만 사용한다.
## 확인
@ -56,7 +58,8 @@ bash scripts/check-setup.sh
| --- | --- |
| SRT 예매 | `KSKILL_SRT_ID`, `KSKILL_SRT_PASSWORD` |
| KTX 예매 | `KSKILL_KTX_ID`, `KSKILL_KTX_PASSWORD` |
| 한국 법령 검색 | `LAW_OC` |
| 한국 법령 검색 (로컬 CLI/MCP) | `LAW_OC` |
| 한국 법령 검색 (remote MCP endpoint) | 사용자 시크릿 불필요 (`url`만 등록) |
| 서울 지하철 도착정보 조회 | self-host 또는 배포 확인이 끝난 `KSKILL_PROXY_BASE_URL` |
| 사용자 위치 미세먼지 조회 | `KSKILL_PROXY_BASE_URL` 또는 `AIR_KOREA_OPEN_API_KEY` |

View file

@ -78,6 +78,8 @@ chmod 0600 ~/.config/k-skill/secrets.env
서울 지하철 도착정보는 hosted public route rollout 이 끝나기 전까지 `KSKILL_PROXY_BASE_URL` 을 self-host 또는 배포 확인이 끝난 proxy URL 로 채운다. 미세먼지만 hosted proxy 로 쓸 때는 이 값을 비워 둘 수 있다.
한국 법령 검색은 로컬 `korean-law-mcp` 경로를 쓸 때만 `LAW_OC` 를 채운다. remote endpoint는 사용자 `LAW_OC` 없이 `url`만 등록하면 된다.
### Missing secret response template
인증 스킬에서 값이 빠졌을 때는 credential resolution order에 따라 확보한다.
@ -86,7 +88,8 @@ chmod 0600 ~/.config/k-skill/secrets.env
- SRT: `KSKILL_SRT_ID`, `KSKILL_SRT_PASSWORD`
- KTX: `KSKILL_KTX_ID`, `KSKILL_KTX_PASSWORD`
- 한국 법령 검색: `LAW_OC` + `korean-law-mcp`
- 로컬 한국 법령 검색: `LAW_OC` + `korean-law-mcp`
- 한국 법령 검색 remote endpoint: 사용자 `LAW_OC` 없이 `url`만 등록
- 서울 지하철: self-host 또는 배포 확인이 끝난 `KSKILL_PROXY_BASE_URL`
- 사용자 위치 미세먼지 조회: `KSKILL_PROXY_BASE_URL` 또는 `AIR_KOREA_OPEN_API_KEY`

View file

@ -40,11 +40,14 @@ metadata:
- 인터넷 연결
- `node` 18+
- `npm install -g korean-law-mcp`
- `LAW_OC` 환경변수 (법제처 Open API key)
- `npm install -g korean-law-mcp` (로컬 CLI/로컬 MCP server 경로일 때)
- MCP 클라이언트에 remote endpoint를 등록할 수 있는 환경
무료 API key: `https://open.law.go.kr`
로컬 CLI 또는 로컬 MCP server 경로는 `LAW_OC` 가 필요하다.
remote MCP endpoint는 사용자 `LAW_OC` 없이 `url`만으로 연결한다.
```bash
npm install -g korean-law-mcp
export LAW_OC=your-api-key
@ -72,7 +75,7 @@ Claude Desktop / Cursor / Windsurf 같은 MCP 클라이언트에는 아래처럼
}
```
설치가 막힌 환경에서는 remote endpoint를 사용한다.
설치가 막힌 환경에서는 remote endpoint를 사용한다. 이 upstream 예시는 사용자 `LAW_OC` 없이 `url`만 등록한다.
```json
{
@ -116,7 +119,8 @@ korean-law search_all --query "개인정보 처리방침 행정해석"
- 약칭(`화관법`)이면 `search_law` / `search_all` 로 정식 법령명을 먼저 확인한다.
- 조문 요청이면 검색 결과의 식별자(`mst`)를 확인한 뒤 `get_law_text` 로 본문을 가져온다.
- 판례/유권해석/자치법규는 각각 전용 search tool을 우선 사용한다.
- 키(`LAW_OC`)가 없으면 credential resolution order에 따라 확보 방법을 짧게 안내하고, 임의의 크롤링/검색엔진 우회로 넘어가지 않는다.
- 로컬 CLI/MCP 경로를 쓰는데 `LAW_OC` 가 없으면 credential resolution order에 따라 확보 방법을 짧게 안내하고, 임의의 크롤링/검색엔진 우회로 넘어가지 않는다.
- remote MCP endpoint를 쓰면 사용자 `LAW_OC` 없이 `url` 등록 상태만 확인한다.
- 법적 판단이 필요한 경우 `검색 결과 요약``원문 출처`까지만 제공하고 법률 자문처럼 단정하지 않는다.
## Done when
@ -124,7 +128,8 @@ korean-law search_all --query "개인정보 처리방침 행정해석"
- 한국 법령 관련 질의에 대해 `korean-law-mcp` 사용 경로가 선택되었다.
- 필요한 검색/조회 명령이 정해졌다.
- 법령/조문/판례/유권해석 중 맞는 도구로 결과를 조회했다.
- `LAW_OC` 가 없으면 확보 방법을 정확한 변수 이름으로 안내했다.
- 로컬 경로라면 `LAW_OC` 확보 방법을 정확한 변수 이름으로 안내했다.
- remote endpoint라면 사용자 `LAW_OC` 없이 `url` 등록 상태를 확인했다.
## Notes

View file

@ -999,7 +999,7 @@ test("package-lock captures the toss-securities workspace metadata for npm ci",
assert.equal(packageLock.packages["packages/toss-securities"].engines.node, ">=18");
});
test("repository docs advertise the korean-law-search skill and its korean-law-mcp dependency", () => {
test("repository docs advertise the korean-law-search skill with mode-specific korean-law-mcp setup guidance", () => {
const readme = read("README.md");
const install = read(path.join("docs", "install.md"));
const setup = read(path.join("docs", "setup.md"));
@ -1007,12 +1007,22 @@ test("repository docs advertise the korean-law-search skill and its korean-law-m
const sources = read(path.join("docs", "sources.md"));
const roadmap = read(path.join("docs", "roadmap.md"));
const setupSkill = read(path.join("k-skill-setup", "SKILL.md"));
const featureDoc = read(path.join("docs", "features", "korean-law-search.md"));
const featureDocPath = path.join(repoRoot, "docs", "features", "korean-law-search.md");
assert.ok(fs.existsSync(featureDocPath), "expected docs/features/korean-law-search.md to exist");
assert.match(readme, /\| 한국 법령 검색 \|/);
assert.match(readme, /\[한국 법령 검색 가이드\]\(docs\/features\/korean-law-search\.md\)/);
assert.match(readme, /로컬 CLI\/MCP면 `LAW_OC` 필요, remote endpoint면 불필요/);
assert.match(install, /--skill korean-law-search/);
assert.match(install, /로컬 CLI\/MCP 경로는 `LAW_OC`/);
assert.match(install, /remote endpoint는 `LAW_OC` 없이 `url`만/);
assert.match(setup, /한국 법령 검색의 로컬 CLI\/MCP 경로용 `LAW_OC`/);
assert.match(setup, /remote MCP endpoint는 사용자 `LAW_OC` 없이 `url`만으로 연결/);
assert.match(featureDoc, /로컬 CLI 또는 로컬 MCP server 경로는 `LAW_OC`/);
assert.match(featureDoc, /remote MCP endpoint는 사용자 `LAW_OC` 없이 `url`만으로 연결/);
assert.match(setupSkill, /로컬 한국 법령 검색: `LAW_OC` \+ `korean-law-mcp`/);
assert.match(setupSkill, /remote endpoint: 사용자 `LAW_OC` 없이 `url`만 등록/);
for (const doc of [setup, security, setupSkill]) {
assert.match(doc, /LAW_OC/);
@ -1023,7 +1033,7 @@ test("repository docs advertise the korean-law-search skill and its korean-law-m
assert.match(roadmap, /한국 법령 검색 스킬 출시/);
});
test("korean-law-search skill requires korean-law-mcp for Korean law lookups without adding a repo package", () => {
test("korean-law-search skill keeps korean-law-mcp-only lookups while separating local LAW_OC setup from remote MCP fallback", () => {
const skillPath = path.join(repoRoot, "korean-law-search", "SKILL.md");
const featureDoc = read(path.join("docs", "features", "korean-law-search.md"));
const examplesSecrets = read(path.join("examples", "secrets.env.example"));
@ -1038,7 +1048,8 @@ test("korean-law-search skill requires korean-law-mcp for Korean law lookups wit
for (const doc of [skill, featureDoc]) {
assert.match(doc, /반드시 .*korean-law-mcp|korean-law-mcp.*반드시/u);
assert.match(doc, /npm install -g korean-law-mcp/);
assert.match(doc, /LAW_OC/);
assert.match(doc, /로컬 CLI 또는 로컬 MCP server 경로는 `LAW_OC`/);
assert.match(doc, /remote MCP endpoint는 사용자 `LAW_OC` 없이 `url`만으로 연결/);
assert.match(doc, /open\.law\.go\.kr/);
assert.match(doc, /search_law/);
assert.match(doc, /get_law_text/);