chain_law_system
Automatically chain legal statute searches, compare articles, and retrieve annexes to analyze legal structures.
Instructions
[⛓체인] 법체계 파악. 법령검색→3단비교→조문→별표 자동 연쇄. 법 구조 질문 시.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | 법령명 또는 키워드 (예: '관세법', '건축법 허가') | |
| articles | No | 조회할 조문 번호 (예: ['제38조', '제39조']) | |
| apiKey | No |
Implementation Reference
- src/tools/chains.ts:219-258 (handler)The main handler function for chain_law_system. It searches for laws, performs a 3-tier comparison (law/enforcement decree/enforcement rules), optionally fetches articles, and expands to annexes based on keyword detection.
export async function chainLawSystem( apiClient: LawApiClient, input: z.infer<typeof chainLawSystemSchema> ): Promise<ToolResponse> { try { const laws = await findLaws(apiClient, input.query, input.apiKey) if (laws.length === 0) return noResult(input.query) const p = laws[0] const parts = [ `═══ 법체계 확인: ${p.lawName} ═══`, `법령ID: ${p.lawId} | MST: ${p.mst} | 구분: ${p.lawType}`, ] // 3단 비교 const threeTier = await callTool(getThreeTier, apiClient, { mst: p.mst, apiKey: input.apiKey }) if (!threeTier.isError) parts.push(sec("3단 비교 (법률·시행령·시행규칙)", threeTier.text)) // 조문 조회 if (input.articles?.length) { const batch = await callTool(getBatchArticles, apiClient, { mst: p.mst, articles: input.articles, apiKey: input.apiKey, }) if (!batch.isError) parts.push(sec("핵심 조문", batch.text)) } // 키워드 확장: 별표 const exp = detectExpansions(input.query) if (exp.includes("annex_fee") || exp.includes("annex_table") || exp.includes("annex_form")) { const annexes = await callTool(getAnnexes, apiClient, { lawName: p.lawName, apiKey: input.apiKey }) if (!annexes.isError) parts.push(sec("별표/서식", annexes.text)) } return wrapResult(parts.join("\n")) } catch (error) { return wrapError(error) } } - src/tools/chains.ts:213-217 (schema)Zod schema for chain_law_system input validation: query (string), optional articles (array of strings), and optional apiKey.
export const chainLawSystemSchema = z.object({ query: z.string().describe("법령명 또는 키워드 (예: '관세법', '건축법 허가')"), articles: z.array(z.string()).optional().describe("조회할 조문 번호 (예: ['제38조', '제39조'])"), apiKey: z.string().optional(), }) - src/tool-registry.ts:603-609 (registration)Registration of chain_law_system in the MCP tool registry with name, description, schema, and handler.
// === 체인 도구 (다단계 자동 실행) === { name: "chain_law_system", description: "[⛓체인] 법체계 파악. 법령검색→3단비교→조문→별표 자동 연쇄. 법 구조 질문 시.", schema: chainLawSystemSchema, handler: chainLawSystem }, - src/tools/chains.ts:94-130 (helper)Helper function findLaws used by chainLawSystem to search and rank laws by relevance.
async function findLaws( apiClient: LawApiClient, query: string, apiKey?: string, max = 3 ): Promise<LawInfo[]> { // 1차: 원본 쿼리로 검색 let results: LawInfo[] = [] try { const xmlText = await apiClient.searchLaw(query, apiKey) results = parseLawXml(xmlText, max) } catch { /* 2차 시도로 진행 */ } // 2차: 결과 없으면 부가 키워드 제거 후 재시도 if (results.length === 0) { const stripped = stripNonLawKeywords(query) if (stripped && stripped !== query) { try { const xmlText = await apiClient.searchLaw(stripped, apiKey) results = parseLawXml(xmlText, max) } catch { /* 빈 결과 반환 */ } } } // 쿼리와 법령명 관련도 기반 정렬 (정확 매칭 > 부분 매칭 > 나머지) if (results.length > 1) { const queryWords = query.replace(NON_LAW_NAME_RE, " ") .trim().split(/\s+/).filter(w => w.length > 0) results.sort((a, b) => { const scoreA = scoreLawRelevance(a.lawName, query, queryWords) const scoreB = scoreLawRelevance(b.lawName, query, queryWords) return scoreB - scoreA }) } return results } - src/lib/query-router.ts:275-284 (helper)Query router rule that routes patterns like '3단 비교', '법 체계' etc. to the chain_law_system tool.
{ name: "law_system", patterns: [ /3단\s*비교|위임\s*조문|인용\s*조문|법\s*체계|시행령\s*비교/, ], tool: "chain_law_system", extract: (query) => ({ query: extractLawName(query) || query }), reason: "법체계/3단비교 키워드 → 법체계 체인", priority: 10, },