get_related_laws
Retrieve the hierarchy of related laws—enforcement decrees, rules, and notices—for a given law using its serial number or law ID.
Instructions
관련 법령·하위 행정규칙 조회 (법제처 lawService · target=lsStmd, 법령 체계도). 본법 → 시행령 → 시행규칙 → 고시·훈령·예규의 상하위 관계와 직접 매핑된 관련법령을 반환. PIPC가 결합법령으로 지정한 관계 외에 법제처 자체 매핑도 포함. mst(권장) 또는 lawId 필요. 다음: get_law_text(lawId·mst)로 본문, search_admin_rule(W2)로 PIPC 고시 본문.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mst | No | 법령일련번호 (search_law 결과의 [브래킷] 안 숫자, 권장) | |
| lawId | No | 법령ID (search_law 결과의 lawId 필드) |
Implementation Reference
- The main tool definition and handler function. The `getRelatedLaws` export is a Tool object with name='get_related_laws', an async handler that calls the lawService.do API with target=lsStmd to fetch the law system tree, then walks the JSON to extract related laws (상하위법 and 관련법령), deduplicates the base law, groups by type, and returns formatted text with suggestions.
export const getRelatedLaws: Tool<typeof inputSchema> = { name: "get_related_laws", description: "관련 법령·하위 행정규칙 조회 (법제처 lawService · target=lsStmd, 법령 체계도). " + "본법 → 시행령 → 시행규칙 → 고시·훈령·예규의 상하위 관계와 직접 매핑된 관련법령을 반환. " + "PIPC가 결합법령으로 지정한 관계 외에 법제처 자체 매핑도 포함. mst(권장) 또는 lawId 필요. " + "다음: get_law_text(lawId·mst)로 본문, search_admin_rule(W2)로 PIPC 고시 본문.", inputSchema, async handler(args, client) { try { if (!args.mst && !args.lawId) { throw new ValidationError("mst 또는 lawId 필수"); } const extraParams: Record<string, string> = {}; if (args.mst) extraParams.MST = args.mst; else if (args.lawId) extraParams.ID = args.lawId; const jsonText = await client.fetchApi({ endpoint: "lawService.do", target: "lsStmd", type: "JSON", extraParams, }); let parsed: SystemTreeResponse; try { parsed = JSON.parse(jsonText) as SystemTreeResponse; } catch { return notFoundResponse( `법령 체계도 응답 파싱 실패 (mst=${args.mst ?? "-"}, lawId=${args.lawId ?? "-"})`, [`search_law(query="...") — 유효한 mst·lawId 확인`] ); } const tree = parsed.법령체계도; if (!tree) { return notFoundResponse( `법령 체계도 데이터 없음 (mst=${args.mst ?? "-"}, lawId=${args.lawId ?? "-"})`, [`search_law(query="...") — 유효한 식별자 확인`] ); } const baseInfo = tree.기본정보 ?? {}; const baseName = baseInfo.법령명 ?? "(법령명 없음)"; const items: RelatedLawItem[] = []; collectInfos(tree.상하위법, "", items); collectInfos(tree.관련법령, "관련법령", items); // 본법 자체 제거 (체계도에 자기 자신이 포함될 수 있음) const filtered = items.filter( (i) => i.id !== baseInfo.법령ID && i.mst !== baseInfo.법령일련번호 ); if (filtered.length === 0) { return notFoundResponse(`관련 법령·하위 규칙 없음: ${baseName}`, [ `intelligent_law_search(query="${baseName}") — 키워드로 관련 조문 검색`, ]); } let text = `관련 법령·하위 규칙 — ${baseName}\n`; text += `총 ${filtered.length}건 (시행령·시행규칙·행정규칙·관련법령)\n\n`; // type별 그룹핑 const grouped = new Map<string, RelatedLawItem[]>(); for (const item of filtered) { const list = grouped.get(item.type) ?? []; list.push(item); grouped.set(item.type, list); } for (const [type, list] of grouped) { text += `[${type}] ${list.length}건\n`; for (const item of list) { text += ` - ${item.name}`; if (item.id) text += ` (ID: ${item.id})`; if (item.effectiveDate) text += ` · 시행 ${item.effectiveDate}`; text += "\n"; } text += "\n"; } const firstItem = filtered[0]; if (firstItem) { text = appendSuggestions(text, [ { tool: "get_law_text", args: firstItem.mst ? { mst: firstItem.mst } : { lawId: firstItem.id }, reason: `${firstItem.name} 본문 조회`, }, ]); } text += `\n${formatLawAttribution(baseName)}`; return { content: [{ type: "text", text }] }; } catch (err) { return formatToolError(err, "get_related_laws"); } }, }; - Zod input schema: accepts optional 'mst' (law serial number) and optional 'lawId' fields, with a refinement ensuring at least one is provided.
const inputSchema = z .object({ mst: z .string() .optional() .describe("법령일련번호 (search_law 결과의 [브래킷] 안 숫자, 권장)"), lawId: z.string().optional().describe("법령ID (search_law 결과의 lawId 필드)"), }) .refine((d) => d.mst || d.lawId, { message: "mst 또는 lawId 중 하나는 필수입니다", }); - src/tools/registry.ts:10-54 (registration)Import of getRelatedLaws from primitives (line 10) and registration in the ALL_TOOLS array (line 53), making it available as a server tool.
import { getRelatedLaws } from "./primitives/get-related-laws.js"; import { getAnnexes } from "./primitives/get-annexes.js"; import { searchAdminRule } from "./primitives/search-admin-rule.js"; import { searchPipcDecisions } from "./primitives/search-pipc-decisions.js"; import { searchConstitutionalDecisions } from "./primitives/search-constitutional-decisions.js"; import { searchAdminAppeals } from "./primitives/search-admin-appeals.js"; import { searchInterpretations } from "./primitives/search-interpretations.js"; import { searchEnglishLaw } from "./primitives/search-english-law.js"; import { getAdminRuleText } from "./primitives/get-admin-rule-text.js"; import { getPipcDecisionText } from "./primitives/get-pipc-decision-text.js"; import { getConstitutionalDecisionText } from "./primitives/get-constitutional-decision-text.js"; import { getAdminAppealText } from "./primitives/get-admin-appeal-text.js"; import { getInterpretationText } from "./primitives/get-interpretation-text.js"; import { getEnglishLawText } from "./primitives/get-english-law-text.js"; import { compareAdminRuleOldNew } from "./primitives/compare-admin-rule-old-new.js"; import { getLawHistory } from "./primitives/get-law-history.js"; import { getHistoricalLaw } from "./primitives/get-historical-law.js"; import { compareOldNew } from "./primitives/compare-old-new.js"; import { getThreeTier } from "./primitives/get-three-tier.js"; import { getArticleChangeHistory } from "./primitives/get-article-change-history.js"; import { getDelegatedLaws } from "./primitives/get-delegated-laws.js"; import { getLawSystemTree } from "./primitives/get-law-system-tree.js"; import { getIntelligentRelatedLaws } from "./primitives/get-intelligent-related-laws.js"; import { compareArticles } from "./primitives/compare-articles.js"; import { getLegalTerm } from "./primitives/get-legal-term.js"; import { getTermArticles } from "./primitives/get-term-articles.js"; import { getLawAbbreviations } from "./primitives/get-law-abbreviations.js"; import { getLawTree } from "./primitives/get-law-tree.js"; // W3 — Layer C corpus import { searchPrivacyCorpus } from "./corpus/search-privacy-corpus.js"; import { searchPrivacyCases } from "./corpus/search-privacy-cases.js"; import { searchPrivacyGuides } from "./corpus/search-privacy-guides.js"; // W3 — Layer B+ hints (PIPC 공식 출처 인덱스화) import { getSectoralRelatedLaws } from "./hints/get-sectoral-related-laws.js"; import { getPipcCuratedCorpus } from "./hints/get-pipc-curated-corpus.js"; // W4 — Validator (4계층 환각 검증) import { verifyPipaCitation } from "./validator/verify-pipa-citation.js"; export const ALL_TOOLS: Tool[] = [ // W1.5 searchLaw, getLawText, intelligentLawSearch, getRelatedLaws, getAnnexes, - Helper function `collectInfos` that recursively walks the system tree JSON to collect all '기본정보' nodes, categorizing them by parentKey as type.
function collectInfos(node: unknown, parentKey: string, out: RelatedLawItem[]): void { if (!node || typeof node !== "object") return; // 배열이면 각 요소를 동일 parentKey로 재귀 if (Array.isArray(node)) { for (const item of node) collectInfos(item, parentKey, out); return; } const obj = node as Record<string, unknown>; // 이 노드 자체에 기본정보가 있으면 항목으로 추가 if (obj.기본정보 && typeof obj.기본정보 === "object") { addInfo(obj.기본정보, parentKey || "기타", out); } // 다른 자식 노드도 walk for (const [key, value] of Object.entries(obj)) { if (key === "기본정보") continue; collectInfos(value, key, out); } } - Helper function `addInfo` that extracts name, id, mst, and effectiveDate from a '기본정보' node and pushes a RelatedLawItem to the output array.
function addInfo(info: unknown, type: string, out: RelatedLawItem[]): void { if (!info || typeof info !== "object") return; const i = info as Record<string, unknown>; const name = typeof i.법령명 === "string" ? i.법령명 : typeof i.행정규칙명 === "string" ? i.행정규칙명 : null; if (!name) return; // 기본정보 노드가 아닌 다른 객체일 수 있음 out.push({ type, name, id: typeof i.법령ID === "string" ? i.법령ID : typeof i.행정규칙ID === "string" ? i.행정규칙ID : "", mst: typeof i.법령일련번호 === "string" ? i.법령일련번호 : typeof i.행정규칙일련번호 === "string" ? i.행정규칙일련번호 : "", effectiveDate: typeof i.시행일자 === "string" ? i.시행일자 : undefined, }); }