Skip to main content
Glama

chain_document_review

Analyze contracts and terms to automatically identify risks, search applicable laws, and find relevant precedents in a single chain of actions.

Instructions

[⛓체인] 문서 종합검토. 리스크분석→법령검색→판례검색 자동 연쇄. 계약서/약관 검토 시 1회에 리스크+근거법령+관련판례 제공.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
textYes분석할 계약서/약관 전문 텍스트
maxClausesYes분석할 최대 조항 수 (기본:15)
apiKeyNo

Implementation Reference

  • Registration of the chain_document_review MCP tool with its name, description, schema, and handler.
    {
      name: "chain_document_review",
      description: "[⛓체인] 문서 종합검토. 리스크분석→법령검색→판례검색 자동 연쇄. 계약서/약관 검토 시 1회에 리스크+근거법령+관련판례 제공.",
      schema: chainDocumentReviewSchema,
      handler: chainDocumentReview
    },
  • Zod schema for chain_document_review: text (string), maxClauses (number, default 15), apiKey (optional string).
    export const chainDocumentReviewSchema = z.object({
      text: z.string().describe("분석할 계약서/약관 전문 텍스트"),
      maxClauses: z.number().min(1).max(30).default(15).describe("분석할 최대 조항 수 (기본:15)"),
      apiKey: z.string().optional(),
    })
  • Main handler function: runs analyze_document for risk analysis, extracts search hints, then parallel searches precedents (via searchPrecedents) and AI law search (via searchAiLaw). Returns combined sections: risk analysis, related precedents, and relevant laws.
    export async function chainDocumentReview(
      apiClient: LawApiClient,
      input: z.infer<typeof chainDocumentReviewSchema>
    ): Promise<ToolResponse> {
      try {
        const parts = [`═══ 문서 종합 검토 ═══`]
    
        // Step 1: analyze_document 로 리스크 분석
        const analysisResult = await callTool(analyzeDocument, apiClient, {
          text: input.text,
          maxClauses: input.maxClauses,
        })
    
        if (analysisResult.isError) {
          return { content: [{ type: "text", text: analysisResult.text }], isError: true }
        }
    
        parts.push(sec("문서 리스크 분석", analysisResult.text))
    
        // Step 2: 분석 결과에서 searchHints 추출 → 병렬로 법령+판례 검색
        const searchHints = extractSearchHints(analysisResult.text)
    
        if (searchHints.length === 0) {
          parts.push("\n▶ 추가 법령/판례 검색\n특별한 리스크가 없어 추가 검색을 생략합니다.\n")
          return wrapResult(parts.join("\n"))
        }
    
        // 중복 제거 후 최대 5개 힌트로 제한
        const uniqueHints = [...new Set(searchHints)].slice(0, 5)
    
        const searchPromises: Promise<CallResult>[] = []
        for (const hint of uniqueHints) {
          searchPromises.push(
            callTool(searchPrecedents, apiClient, { query: hint, display: 3, apiKey: input.apiKey })
          )
        }
        // AI 법령 검색도 상위 3개 힌트로 병렬 실행
        const lawHints = uniqueHints.slice(0, 3)
        for (const hint of lawHints) {
          searchPromises.push(
            callTool(searchAiLaw, apiClient, { query: hint, display: 3, apiKey: input.apiKey })
          )
        }
    
        const searchResults = await Promise.all(searchPromises)
    
        // 판례 결과 합산
        const precTexts: string[] = []
        for (let i = 0; i < uniqueHints.length; i++) {
          const r = searchResults[i]
          if (!r.isError && r.text.trim()) {
            precTexts.push(`[${uniqueHints[i]}]\n${r.text}`)
          }
        }
        if (precTexts.length > 0) {
          parts.push(sec("관련 판례", precTexts.join("\n\n")))
        }
    
        // 법령 결과 합산
        const lawTexts: string[] = []
        for (let i = 0; i < lawHints.length; i++) {
          const r = searchResults[uniqueHints.length + i]
          if (!r.isError && r.text.trim()) {
            lawTexts.push(`[${lawHints[i]}]\n${r.text}`)
          }
        }
        if (lawTexts.length > 0) {
          parts.push(sec("근거 법령", lawTexts.join("\n\n")))
        }
    
        return wrapResult(parts.join("\n"))
      } catch (error) {
        return wrapError(error)
      }
    }
  • Helper function extractSearchHints: parses the analyze_document output for lines starting with '검색:' to extract search keywords (split by '/') for subsequent law/precedent search.
    /** analyze_document 결과 텍스트에서 "검색: ..." 라인의 힌트를 추출 */
    function extractSearchHints(analysisText: string): string[] {
      const hints: string[] = []
      const lines = analysisText.split("\n")
      for (const line of lines) {
        const m = line.match(/^\s*검색:\s*(.+)$/)
        if (m) {
          const hintParts = m[1].split(/\s*\/\s*/)
          for (const p of hintParts) {
            const trimmed = p.trim()
            if (trimmed) hints.push(trimmed)
          }
        }
      }
      return hints
    }
Behavior3/5

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

The description discloses the chained behavior (risk analysis → law search → precedent search) and the output (risk, relevant laws, precedents). However, no annotations exist, and the description lacks details on safety (read-only?), authentication needs (apiKey is a param but not mentioned), rate limits, or side effects. The disclosure is adequate but not comprehensive.

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

Conciseness5/5

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

The description is extremely concise, using two sentences with clear structure and front-loaded key terms (emoji, chain description). Every part adds value without redundancy.

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

Completeness3/5

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

The description explains the tool's purpose and chained process, which is useful for a complex tool. However, without an output schema, it lacks details on the return format or limitations (e.g., text length, timeout). The description is adequate for basic use but incomplete for advanced agent reasoning.

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 67% with text and maxClauses described; apiKey lacks description. The tool description adds overall context but does not enhance parameter understanding beyond the schema. Given moderate coverage, the description does not sufficiently compensate, resulting in a baseline score.

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 performs a comprehensive document review with an automatic chain of risk analysis, law search, and precedent search. It specifies the use case for contract/terms review, distinguishing it from sibling chain tools like chain_action_basis or chain_law_system.

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 explicitly indicates usage for reviewing contracts/terms ('계약서/약관 검토 시'), providing clear context. However, it does not include explicit exclusions or when-not-to-use scenarios, though the specificity implies proper usage.

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