Skip to main content
Glama

get_article_detail

Retrieve precise article text from Korean laws, including specific paragraphs (hang), subparagraphs (ho), and items (mok). Provide law ID, article number, and optional subsections to get exact legal provisions.

Instructions

[법령조회] 조항호목 단위 정밀 조회. 제38조 제2항 제3호 같은 세부 단위 지정 가능. mst/lawId + jo 필수, hang/ho/mok 선택.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
mstNo법령일련번호 (search_law에서 획득)
lawIdNo법령ID (search_law에서 획득)
joYes조문 번호 (예: '제38조' 또는 '003800')
hangNo항 번호 (예: '2')
hoNo호 번호 (예: '3')
mokNo목 번호 (예: '1')
apiKeyNo법제처 Open API 인증키(OC). 사용자가 제공한 경우 전달

Implementation Reference

  • The main handler function `getArticleDetail` for the tool. It accepts a LawApiClient and GetArticleDetailInput, converts Korean article numbers to JO codes, builds API parameters, fetches data from the law.go.kr API, parses the JSON response, and formats the result including article, sub-paragraph (hang), clause (ho), and item (mok) details.
    export async function getArticleDetail(
      apiClient: LawApiClient,
      input: GetArticleDetailInput
    ): Promise<{ content: Array<{ type: string, text: string }>, isError?: boolean }> {
      try {
        // 조문 번호가 한글이면 JO 코드로 변환
        let joCode = input.jo
        if (/제\d+조/.test(joCode)) {
          joCode = buildJO(joCode)
        }
    
        const extraParams: Record<string, string> = {}
        if (input.mst) extraParams.MST = String(input.mst)
        if (input.lawId) extraParams.ID = String(input.lawId)
        extraParams.JO = String(joCode)
        if (input.hang) extraParams.HANG = String(input.hang)
        if (input.ho) extraParams.HO = String(input.ho)
        if (input.mok) extraParams.MOK = String(input.mok)
    
        const jsonText = await apiClient.fetchApi({
          endpoint: "lawService.do",
          target: "eflaw",
          type: "JSON",
          extraParams,
          apiKey: input.apiKey
        })
    
        const json = JSON.parse(jsonText)
        const lawData = json?.법령
    
        if (!lawData) {
          return {
            content: [{ type: "text", text: "법령 데이터를 찾을 수 없습니다." }],
            isError: true
          }
        }
    
        const basicInfo = lawData.기본정보 || lawData
        const lawName = basicInfo?.법령명_한글 || basicInfo?.법령명한글 || basicInfo?.법령명 || "알 수 없음"
    
        // 조회 위치 표시
        let locationLabel = `제${input.jo.replace(/^제/, "").replace(/조$/, "")}조`
        if (/^\d{4,6}$/.test(input.jo)) locationLabel = `JO=${input.jo}`
        if (input.hang) locationLabel += ` 제${input.hang}항`
        if (input.ho) locationLabel += ` 제${input.ho}호`
        if (input.mok) locationLabel += ` ${input.mok}목`
    
        let resultText = `법령명: ${lawName}\n`
        resultText += `조회 위치: ${locationLabel}\n\n`
    
        // 조문 추출
        const rawUnits = lawData.조문?.조문단위
        const articleUnits: any[] = Array.isArray(rawUnits) ? rawUnits : rawUnits ? [rawUnits] : []
    
        if (articleUnits.length === 0) {
          return {
            content: [{ type: "text", text: resultText + "해당 조문을 찾을 수 없습니다." }],
            isError: true
          }
        }
    
        for (const unit of articleUnits) {
          if (unit.조문여부 !== "조문") continue
    
          const joNum = unit.조문번호 || ""
          const joBranch = unit.조문가지번호 || ""
          const joTitle = unit.조문제목 || ""
          const displayNum = joBranch && joBranch !== "0" ? `제${joNum}조의${joBranch}` : `제${joNum}조`
    
          resultText += `${displayNum}`
          if (joTitle) resultText += ` ${joTitle}`
          resultText += `\n`
    
          // 조문내용
          if (unit.조문내용) {
            const content = typeof unit.조문내용 === "string" ? unit.조문내용 : String(unit.조문내용)
            resultText += `${content}\n`
          }
    
          // 항 내용
          if (unit.항) {
            const hangList = Array.isArray(unit.항) ? unit.항 : [unit.항]
            for (const hang of hangList) {
              const hangNum = hang.항번호 || ""
              const hangContent = hang.항내용 || ""
              if (hangContent) {
                resultText += `  ${hangNum ? `(${hangNum})` : ""} ${hangContent}\n`
              }
    
              // 호 내용
              if (hang.호) {
                const hoList = Array.isArray(hang.호) ? hang.호 : [hang.호]
                for (const ho of hoList) {
                  const hoNum = ho.호번호 || ""
                  const hoContent = ho.호내용 || ""
                  if (hoContent) {
                    resultText += `    ${hoNum}. ${hoContent}\n`
                  }
    
                  // 목 내용
                  if (ho.목) {
                    const mokList = Array.isArray(ho.목) ? ho.목 : [ho.목]
                    for (const mok of mokList) {
                      const mokNum = mok.목번호 || ""
                      const mokContent = mok.목내용 || ""
                      if (mokContent) {
                        resultText += `      ${mokNum}. ${mokContent}\n`
                      }
                    }
                  }
                }
              }
            }
          }
    
          resultText += `\n`
        }
    
        return {
          content: [{ type: "text", text: truncateResponse(resultText) }]
        }
      } catch (error) {
        return formatToolError(error, "get_article_detail")
      }
    }
  • The `GetArticleDetailSchema` Zod schema defining input parameters: mst (law serial number), lawId (law ID), jo (article number, required), hang (sub-paragraph), ho (clause), mok (item), and apiKey. Validates that at least one of mst or lawId is provided.
    export const GetArticleDetailSchema = z.object({
      mst: z.string().optional().describe("법령일련번호 (search_law에서 획득)"),
      lawId: z.string().optional().describe("법령ID (search_law에서 획득)"),
      jo: z.string().describe("조문 번호 (예: '제38조' 또는 '003800')"),
      hang: z.string().optional().describe("항 번호 (예: '2')"),
      ho: z.string().optional().describe("호 번호 (예: '3')"),
      mok: z.string().optional().describe("목 번호 (예: '1')"),
      apiKey: z.string().optional().describe("법제처 Open API 인증키(OC). 사용자가 제공한 경우 전달")
    }).refine(data => data.mst || data.lawId, {
      message: "mst 또는 lawId 중 하나는 필수입니다"
    })
  • Registration of the 'get_article_detail' tool in the allTools array. Defines the tool name, description ('조항호목 단위 정밀 조회'), assigns GetArticleDetailSchema for validation, and maps to the getArticleDetail handler function.
    {
      name: "get_article_detail",
      description: "[법령조회] 조항호목 단위 정밀 조회. 제38조 제2항 제3호 같은 세부 단위 지정 가능. mst/lawId + jo 필수, hang/ho/mok 선택.",
      schema: GetArticleDetailSchema,
      handler: getArticleDetail
    },
  • Import statement for the getArticleDetail handler and GetArticleDetailSchema from the article-detail tool module.
    import { getArticleDetail, GetArticleDetailSchema } from "./tools/article-detail.js"
  • The `buildJO` helper function called by the handler. Converts Korean article number notation (e.g., '제38조', '제10조의2') to 6-digit JO codes (e.g., '003800', '001002') for the legal API.
    export function buildJO(input: string): string {
      if (!input) return "000000"
    
      // 이미 6자리 숫자면 그대로
      const stripped = input.replace(/\s+/g, "")
      if (/^\d{6}$/.test(stripped)) return stripped
    
      const norm = normalizeArticle(input)
      const m = norm.match(/^제(\d+)조(?:의(\d+))?$/)
      if (!m) return "000000"
    
      const main = parseInt(m[1], 10)
      const branch = m[2] ? parseInt(m[2], 10) : 0
      if (Number.isNaN(main)) return "000000"
    
      return String(main).padStart(4, "0") + String(branch).padStart(2, "0")
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must fully disclose behavioral traits. It fails to mention any side effects, authorization requirements, rate limits, or return format, leaving significant gaps in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (one sentence) but contains a factual inaccuracy about required parameters. Conciseness without accuracy reduces overall effectiveness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 7 parameters, 100% schema coverage, and no output schema, the description does not add sufficient context about the return value or edge cases. The contradictory information about required fields further detracts from completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description contradicts the input schema by claiming mst/lawId are required ('필수'), while the schema lists only 'jo' as required. This is a critical error that could cause the agent to incorrectly invoke the tool without necessary parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves precise article details at the clause level (조항호목 단위 정밀 조회) and gives a concrete example (제38조 제2항 제3호). This distinguishes it among many sibling tools focused on other types of legal documents or broader searches.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies required vs optional parameters and implies usage for detailed clause lookups. However, it does not explicitly state when to avoid this tool or suggest alternatives, which would be helpful given the large sibling set.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/workbookbulb863/korean-law-alio-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server