cn-law-hub exposes 5 tools for searching Chinese legal sources. Tool naming is reasonable (search_laws, get_law_detail, query_article, preview_law, article_search all use action verbs). Descriptions are present but vary in quality. The most significant issue is that parameter schemas are incomplete or inferred from the code snippet provided. The mcp_server.py file shows @mcp.tool() decorators with docstrings, but the actual schema definitions (input/output types) are not fully visible in the source provided. Per-tool scores are computed based on what is visible: naming is consistently verb-based, descriptions are present but generic, and schemas appear to rely on Python type hints rather than explicit JSON Schema definitions visible in the code.
Search a keyword across articles of multiple laws.
Fetch the detail page of a record (metadata / full text) by its URL (or npc bbbs id).
Preview the structure of an NPC law: title, article count, numbering pattern, and the first 20 articles.
Query specific articles of a law from the NPC national database (flk.npc.gov.cn).
Search Chinese laws / regulations / policies from one official source.
Parameter schemas not explicitly visible. Code shows @mcp.tool() decorators with docstring descriptions, but JSON Schema definitions are not shown in the provided source. This violates the requirement that tools must declare input schemas with proper type information accessible to MCP clients.
Output schemas undocumented. None of the 5 tools include explicit return-type documentation. Callers and LLMs cannot predict the structure of results (field names, types, presence of pagination fields, error shapes). This forces agents to guess, leading to parsing errors and wasted tokens.
Inconsistent error handling. search_laws() returns dict with 'error' field on validation failures, but code shows try/except that also returns {'error': ...}. No guidance on which errors are retryable, which are user-fixable, or if the LLM should call recovery tools. Error messages like '{type(e).__name__}: {e}' lack actionable recovery hints.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 51 | <=2025-11-25 | v2 |
Parameter descriptions are generic and lack constraints. 'Search keyword' (query_article) and 'Keyword to search' (article_search) provide minimal guidance. No mention of length limits, special characters, language requirements (Chinese vs English?), or example queries. For search_range enum in article_search, description exists but is terse.
Dependent parameters not documented. article_search has a 'law_keyword' param (default same as keyword), the relationship and interaction are not explained in the description. category param in search_laws is REQUIRED for some sources (gov_rules, treaty) but this critical dependency is buried in one sentence and easy to miss.
No pagination or result-limiting documented behavior. article_search has max_laws=5 and offset parameters suggesting pagination, but search_laws returns records in an unstructured list with no total_count, next_cursor, or has_more fields visible. Agents cannot determine if results are complete or if more pages exist without attempting another call.
Tool coupling not explicit. query_article and preview_law both require 'bbbs_id' which comes from search_laws(source='npc'). This coupling is mentioned only in parameter descriptions ('The bbbs_id comes from search_laws...') rather than documented as a tool chain pattern. No guidance on discovery or prerequisite calls.
Ambiguous parameter 'url' in get_law_detail. Description says 'The record's detail URL, or, for source 'npc', the bbbs id.' This creates two different input types for the same parameter, forcing the LLM to track source-specific logic. Should either have separate parameters (url_or_bbbs_id with conditional handling documented) or accept both transparently and document clearly.
Missing defaults justification. article_search defaults law_keyword=None (same as keyword), search_range='title', max_laws=5, offset=0, resume=false, context=0, status_filter=null. No explanation of why these are safe defaults or when an agent should override them. E.g., why resume=false, will re-downloading waste time?