Skip to main content
Glama

advanced_search

Search Korean laws with filters for law type, department, and enforcement date. Combine multiple keywords using AND/OR operators to refine results.

Instructions

[고급검색] 법령종류/부처/시행일 필터 검색. 복합 조건 시.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYes검색 키워드
searchTypeYes검색 대상: law (법령), admin_rule (행정규칙), ordinance (자치법규), all (전체)law
fromDateNo제정일 시작 (YYYYMMDD)
toDateNo제정일 종료 (YYYYMMDD)
orgNo소관부처코드
operatorYes키워드 결합 연산자AND
displayYes최대 결과 개수
apiKeyNo법제처 Open API 인증키(OC). 사용자가 제공한 경우 전달

Implementation Reference

  • Zod schema for advanced_search tool: defines query, searchType (law/admin_rule/ordinance/all), fromDate, toDate, org, operator (AND/OR), display count, and optional apiKey.
    /**
     * advanced_search Tool - 고급 검색 (기간, 부처, 복합 검색)
     */
    
    import { z } from "zod"
    import { DOMParser } from "@xmldom/xmldom"
    import type { LawApiClient } from "../lib/api-client.js"
    import { formatToolError } from "../lib/errors.js"
    
    export const AdvancedSearchSchema = z.object({
      query: z.string().describe("검색 키워드"),
      searchType: z.enum(["law", "admin_rule", "ordinance", "all"]).optional().default("law").describe(
        "검색 대상: law (법령), admin_rule (행정규칙), ordinance (자치법규), all (전체)"
      ),
      fromDate: z.string().optional().describe("제정일 시작 (YYYYMMDD)"),
      toDate: z.string().optional().describe("제정일 종료 (YYYYMMDD)"),
      org: z.string().optional().describe("소관부처코드"),
      operator: z.enum(["AND", "OR"]).optional().default("AND").describe("키워드 결합 연산자"),
      display: z.number().optional().default(20).describe("최대 결과 개수"),
      apiKey: z.string().optional().describe("법제처 Open API 인증키(OC). 사용자가 제공한 경우 전달")
    })
  • Main handler function advancedSearch() - splits keywords, runs parallel searches across selected types (law, admin_rule, ordinance), applies AND/OR operator filtering, date range filtering, slices to display count, and formats results text.
    export async function advancedSearch(
      apiClient: LawApiClient,
      input: AdvancedSearchInput
    ): Promise<{ content: Array<{ type: string, text: string }>, isError?: boolean }> {
      try {
        // 키워드 분리 (공백 기준)
        const keywords = input.query.split(/\s+/).filter(k => k.length > 0)
    
        let results: Array<{ name: string, id: string, type: string, date: string }> = []
    
        // 검색 대상별로 실행 (병렬)
        const searchTargets = input.searchType === "all"
          ? ["law", "admin_rule", "ordinance"]
          : [input.searchType]
    
        const targetResults = await Promise.all(
          searchTargets.map(target => searchByType(apiClient, target, keywords, input, input.apiKey))
        )
        results = targetResults.flat()
    
        // AND/OR 연산 적용
        if (input.operator === "AND" && keywords.length > 1) {
          results = filterByAnd(results, keywords)
        }
    
        // 기간 필터링
        if (input.fromDate || input.toDate) {
          results = filterByDate(results, input.fromDate, input.toDate)
        }
    
        // 상위 N개만
        results = results.slice(0, input.display)
    
        // 결과 포맷
        let resultText = `🔍 고급 검색 결과 (${results.length}건)\n\n`
        resultText += `검색어: ${input.query}\n`
        resultText += `연산자: ${input.operator}\n`
        if (input.fromDate || input.toDate) {
          resultText += `기간: ${input.fromDate || "시작"} ~ ${input.toDate || "종료"}\n`
        }
        resultText += `\n`
    
        results.forEach((result, idx) => {
          resultText += `${idx + 1}. ${result.name}\n`
          resultText += `   - ID: ${result.id}\n`
          resultText += `   - 유형: ${result.type}\n`
          resultText += `   - 날짜: ${result.date}\n\n`
        })
    
        return {
          content: [{
            type: "text",
            text: resultText
          }]
        }
      } catch (error) {
        return formatToolError(error, "advanced_search")
      }
    }
  • Helper function searchByType() - calls the appropriate API client method based on type, parses XML response, extracts name/ID/date from type-specific XML tags.
    /**
     * 검색 대상별 검색 실행
     */
    async function searchByType(
      apiClient: LawApiClient,
      type: string,
      keywords: string[],
      input: AdvancedSearchInput,
      apiKey?: string
    ): Promise<Array<{ name: string, id: string, type: string, date: string }>> {
      const query = keywords.join(" ")
      const results: Array<{ name: string, id: string, type: string, date: string }> = []
    
      try {
        let xmlText = ""
    
        if (type === "law") {
          xmlText = await apiClient.searchLaw(query, apiKey)
        } else if (type === "admin_rule") {
          xmlText = await apiClient.searchAdminRule({ query, apiKey })
        } else if (type === "ordinance") {
          xmlText = await apiClient.searchOrdinance({ query, display: 100, apiKey })
        }
    
        const parser = new DOMParser()
        const doc = parser.parseFromString(xmlText, "text/xml")
    
        // 검색 대상별 XML 태그명 매핑
        const tagMap: Record<string, string> = { law: "law", admin_rule: "admrul", ordinance: "ordin" }
        const tagName = tagMap[type] || "law"
        const items = doc.getElementsByTagName(tagName)
    
        for (let i = 0; i < items.length; i++) {
          const item = items[i]
    
          // 검색 대상별 필드명 매핑
          const name = item.getElementsByTagName("법령명한글")[0]?.textContent ||
            item.getElementsByTagName("행정규칙명")[0]?.textContent ||
            item.getElementsByTagName("자치법규명")[0]?.textContent ||
            "알 수 없음"
    
          const id = item.getElementsByTagName("법령ID")[0]?.textContent ||
            item.getElementsByTagName("행정규칙일련번호")[0]?.textContent ||
            item.getElementsByTagName("자치법규ID")[0]?.textContent ||
            ""
    
          const date = item.getElementsByTagName("공포일자")[0]?.textContent ||
            item.getElementsByTagName("시행일자")[0]?.textContent ||
            item.getElementsByTagName("제정일자")[0]?.textContent ||
            ""
    
          results.push({ name, id, type, date })
        }
      } catch {
        // 검색 실패 시 빈 배열 반환
      }
    
      return results
    }
  • Helper function filterByAnd() - filters results to only include those whose name contains ALL keywords.
    /**
     * AND 연산 필터링 (모든 키워드 포함 여부)
     */
    function filterByAnd(
      results: Array<{ name: string, id: string, type: string, date: string }>,
      keywords: string[]
    ): Array<{ name: string, id: string, type: string, date: string }> {
      // 안전: includes() 사용 (regex가 아님) → injection 위험 없음
      return results.filter(result => {
        const name = (result.name || "").toLowerCase()
        return keywords.every(keyword => name.includes(keyword.toLowerCase()))
      })
    }
  • Helper function filterByDate() - filters results within a fromDate/toDate range.
    /**
     * 날짜 필터링
     */
    function filterByDate(
      results: Array<{ name: string, id: string, type: string, date: string }>,
      fromDate?: string,
      toDate?: string
    ): Array<{ name: string, id: string, type: string, date: string }> {
      return results.filter(result => {
        if (!result.date) return false
    
        const dateStr = result.date.replace(/-/g, "")
    
        if (fromDate && dateStr < fromDate) return false
        if (toDate && dateStr > toDate) return false
    
        return true
      })
    }
Behavior2/5

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

No annotations provided. Description only mentions 'filter search' and 'complex conditions' but does not disclose behavior such as authentication requirements (apiKey is described in schema but not in description), rate limits, or result format. The burden falls entirely on the description, which is insufficient.

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?

Description is very short (one line), which is concise but risks being under-informative. It lacks structure and front-loads only a brief purpose. Could benefit from more detail without being verbose.

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?

Given 8 parameters, no output schema, and no annotations, the description is incomplete. It does not explain return values, pagination, error handling, or how to use the apiKey. The tool is complex, so more detail is necessary.

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

Parameters3/5

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

Schema coverage is 100% with descriptions for each parameter. The tool description mentions filters (law type, department, date) which map to parameters, but adds little extra meaning. With full schema coverage, baseline is 3, and description does not significantly add beyond the schema.

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

Purpose4/5

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

Description states it's for advanced search with filters on law type, department, and enforcement date, matching the name and distinguishing it from simpler search tools among siblings. However, it does not explicitly differentiate from sibling tools, and the phrasing '복합 조건 시' is vague.

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

Usage Guidelines2/5

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

No guidance on when to use this tool versus other search tools (e.g., search_law, search_ordinance). It does not provide explicit when-to-use or alternatives, leaving the agent to infer based on the name.

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