Skip to main content
Glama
scvcoder

korean-privacy-law-mcp

by scvcoder

get_pipc_decision_text

Retrieve the full text of a PIPC decision by ID, including structured fields like case name, key points, order, and reasoning, with automatic summarization and attachment links.

Instructions

PIPC 결정문 전문 (법제처 lawService · target=ppc). 안건명·결정요지·주문·이유·배경 등 구조화 필드 추출. 별지(첨부 이미지·PDF) 링크 자동 추출. 긴 본문은 자동 축약. 다음: search_pipc_decisions로 유사 사례 검색 비교, get_law_text로 인용 조문 확인.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesPIPC 결정문일련번호 (search_pipc_decisions 결과의 [id=N])

Implementation Reference

  • The Tool object export containing the handler function for 'get_pipc_decision_text'. The handler fetches PIPC decision text from the lawService API, parses the JSON response, extracts structured fields (안건명, 결정요지, 주문, 이유, 배경 등), builds formatted text output with attachment links and suggestions, and returns the result.
    export const getPipcDecisionText: Tool<typeof inputSchema> = {
      name: "get_pipc_decision_text",
      description:
        "PIPC 결정문 전문 (법제처 lawService · target=ppc). 안건명·결정요지·주문·이유·배경 등 구조화 필드 추출. " +
        "별지(첨부 이미지·PDF) 링크 자동 추출. 긴 본문은 자동 축약. " +
        "다음: search_pipc_decisions로 유사 사례 검색 비교, get_law_text로 인용 조문 확인.",
      inputSchema,
    
      async handler(args, client) {
        try {
          const jsonText = await client.fetchApi({
            endpoint: "lawService.do",
            target: "ppc",
            type: "JSON",
            extraParams: { ID: args.id },
          });
    
          let parsed: { PpcService?: { 의결서?: PipcDecisionData }; Law?: string };
          try {
            parsed = JSON.parse(jsonText);
          } catch {
            return notFoundResponse(`PIPC 결정문 응답 파싱 실패 (id=${args.id})`, [
              `search_pipc_decisions(query="...") — 유효한 id 확인`,
            ]);
          }
    
          // admrul과 동일한 실패 응답 패턴
          if (typeof parsed.Law === "string") {
            return notFoundResponse(`PIPC 결정문 없음: ${parsed.Law}`, [
              `search_pipc_decisions(query="...") — 유효한 id 확인`,
            ]);
          }
    
          const decision = parsed.PpcService?.의결서;
          if (!decision) {
            return notFoundResponse(`PIPC 결정문 데이터 없음 (id=${args.id})`, [
              `search_pipc_decisions(query="...") — 유효한 id 확인`,
            ]);
          }
    
          const title = decision.안건명 ?? "(안건명 없음)";
          const date = decision.의결연월일 ?? decision.의결일자 ?? "";
    
          let text = `=== ${title} ===\n`;
          if (decision.안건번호) text += `안건번호: ${decision.안건번호}\n`;
          if (decision.결정문일련번호) text += `결정문ID: ${decision.결정문일련번호}\n`;
          if (date) text += `의결일: ${date}\n`;
          if (decision.회의종류) text += `회의: ${decision.회의종류}\n`;
          if (decision.신청인) text += `신청인: ${decision.신청인}\n`;
          if (decision.결정) text += `결정: ${decision.결정}\n`;
    
          // 핵심 본문 필드 — 우선순위 순서 (요지 → 주문 → 이유 → 배경 → 주요내용)
          text += formatField("결정요지", decision.결정요지);
          text += formatField("주문", decision.주문);
          text += formatField("이유", decision.이유);
          text += formatField("배경", decision.배경);
          text += formatField("주요내용", decision.주요내용);
    
          // 별지 (이미지·PDF 첨부 링크)
          const attachments = extractAttachmentLinks(decision.별지 ?? "");
          if (attachments.length > 0) {
            text += `\n[첨부] ${attachments.length}건\n`;
            for (const link of attachments) text += `  - ${link}\n`;
          }
    
          if (decision.위원서명) {
            const signatures = decision.위원서명.replace(/\s+/g, " ").trim();
            text += `\n[위원서명] ${signatures}\n`;
          }
          if (decision.이의제기방법및기간) {
            text += `\n[이의제기] ${decision.이의제기방법및기간}\n`;
          }
    
          text = appendSuggestions(text, [
            {
              tool: "search_pipc_decisions",
              args: { query: title.slice(0, 20) },
              reason: "유사 결정문 검색 (위반유형·과징금 비교)",
            },
          ]);
          text += `\n📎 출처: 개인정보보호위원회 결정문 (id=${args.id}) — ${pipcDecisionUrl(args.id)}`;
    
          return { content: [{ type: "text", text }] };
        } catch (err) {
          return formatToolError(err, "get_pipc_decision_text");
        }
      },
    };
  • Zod input schema for the tool: requires a single 'id' field (string, min length 1) described as 'PIPC 결정문일련번호 (search_pipc_decisions 결과의 [id=N])'.
    const inputSchema = z.object({
      id: z
        .string()
        .min(1)
        .describe(
          "PIPC 결정문일련번호 (search_pipc_decisions 결과의 [id=N])"
        ),
    });
  • Import of getPipcDecisionText from the implementation file into the tools registry.
    import { getPipcDecisionText } from "./primitives/get-pipc-decision-text.js";
  • Registration of getPipcDecisionText in the ALL_TOOLS array, making it available to the MCP server.
    getPipcDecisionText,
  • The PipcDecisionData TypeScript interface defining all possible fields returned from the PIPC API (안건명, 결정요지, 주문, 이유, 배경, 별지, etc.) used to type the parsed response.
    interface PipcDecisionData {
      안건명?: string;
      안건번호?: string;
      결정문일련번호?: string;
      의결연월일?: string;
      의결일자?: string;
      회의종류?: string;
      신청인?: string;
      결정?: string;
      결정요지?: string;
      주문?: string;
      이유?: string;
      배경?: string;
      별지?: string;
      위원서명?: string;
      기관명?: string;
      이의제기방법및기간?: string;
      주요내용?: string;
    }
  • Helper function extractAttachmentLinks that parses HTML img tags in the '별지' field to extract attachment URLs (images/PDFs).
    function extractAttachmentLinks(annexHtml: string): string[] {
      if (!annexHtml) return [];
      const links: string[] = [];
      const re = /<img[^>]*src="([^"]+)"[^>]*alt="([^"]*)"/gi;
      let m: RegExpExecArray | null;
      while ((m = re.exec(annexHtml)) !== null) {
        const src = m[1] ?? "";
        const alt = m[2] ?? "";
        const url = src.startsWith("/") ? `${LAW_GO_KR}${src}` : src;
        links.push(`${alt || "별지"}: ${url}`);
      }
      return links;
    }
  • Helper function formatField that cleans HTML tags from a field value and optionally compacts long text using compactBody.
    function formatField(label: string, value: string | undefined): string {
      if (!value) return "";
      const cleaned = stripHtmlTags(value);
      if (!cleaned) return "";
      const compacted =
        cleaned.length > FIELD_COMPACT_THRESHOLD
          ? compactBody(cleaned, { headLimit: 1500, tailLimit: 800, minLength: FIELD_COMPACT_THRESHOLD })
          : cleaned;
      return `\n[${label}]\n${compacted}\n`;
    }
Behavior5/5

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

Despite no annotations, the description fully discloses behaviors: automatic extraction of structured fields, attachment links, and auto-summarization of long texts. No hidden behaviors or contradictions.

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

Conciseness4/5

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

Description is a single, information-dense paragraph. It is concise but could be slightly more structured (e.g., list features). Still efficient and earns its place.

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

Completeness5/5

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

For a simple tool with one parameter and no output schema, the description covers purpose, usage, features, and related tools. It provides a complete picture for an AI agent.

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

Parameters4/5

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

Single parameter 'id' is already described in schema, but the description adds context that it comes from search_pipc_decisions results and what output to expect. Schema coverage is 100%, so baseline is 3; description adds enough to warrant a 4.

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?

Description clearly states the tool retrieves the full text of PIPC decisions, extracts structured fields (case name, summary, order, etc.), attachments, and auto-summarizes. It distinguishes from siblings like search_pipc_decisions and get_law_text.

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

Usage Guidelines5/5

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

Explicitly recommends using search_pipc_decisions to get the ID first, and suggests get_law_text for cited statutes. Provides clear when-to-use guidance and alternatives.

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/scvcoder/korean-privacy-law-mcp'

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