Skip to main content
MCP-grounded Taiwan (ROC) legal research over 司法院 judgments, 全國法規資料庫 regulations, and 憲法法庭 interpretations. Every answer is backed by a live tool call against an official Taiwan government source.

Code

Create bindu_agent.py with the code below, or save it directly from your editor.
The Bindu wrapper imports the agent and MCP launch params from agent.py. Create agent.py alongside bindu_agent.py:
The Windsurf-style XML-tagged prompt lives in prompts.py:
The shipped prompts.py is longer (full <user_information>, <legal_research_method>, <handling_uncertainty>, <communication_style> sections plus a tool-selection cheat sheet). Read it in the source repo for the exact text.

How It Works

MCP-first grounding rule
  • The system prompt enforces a hard constraint: every authoritative answer must be backed by a live tool call against an official Taiwan source — never the model’s training memory
  • General procedural questions (“what is a 釋字?”) may be answered without a tool call; anything that names a specific statute, judgment, or interpretation must hit the MCP
  • The 8-tool MCP surface (mcp-taiwan-legal-db) is enumerated inside <available_tools> so the model can’t drift to a fabricated tool name
MCP integration (stdio transport, kept warm)
  • The mcp-taiwan-legal-db server is launched as a stdio subprocess via StdioServerParameters
  • bindu_agent.py opens the MCP connection ONCE on module import and keeps it alive across every A2A request — no fork-per-request overhead
  • Bindu’s handler contract is sync, but agno + MCPTools are async-only. A daemon thread runs a dedicated asyncio loop; the sync handler hops onto it with run_coroutine_threadsafe(...) and waits for the result
  • atexit closes the MCP session cleanly on shutdown
  • Backed by 司法院 (judgments), 全國法規資料庫 (regulations), and 憲法法庭 (constitutional court) — proxied through httpx, with an optional Playwright fallback for 司法院’s F5 WAF
Citation discipline
  • Judgments cite the JID (e.g. 最高法院 114 年度台上字第 3753 號民事判決 (2025-11-12))
  • Regulations cite 法規名稱 + 條 (e.g. 《民法》第 184 條第 1 項前段)
  • Constitutional interpretations cite 釋字 / 憲判字 number + date (e.g. 司法院釋字第 748 號解釋)
  • Quote Chinese using 「」 quotation marks; long quotes go on a new line
  • Every answer ends with a ### Sources section listing each tool-call-derived source with citation, relevance, and a permalink when one was returned
Tool-selection heuristics
  • Known 案號 (case_word + case_number + year) → search_judgments with structured filters (fast HTTP GET), then get_judgment(jid)
  • Known 法規名稱 → get_pcode first, then query_regulation(pcode, article_no) — beats search_regulations keyword sweep
  • Constitutional questions → search_interpretations then get_interpretation, with get_citations for doctrinal lineage
  • Default research order: pull the controlling statute first, then leading case law, then any 釋字 / 憲判字 that touches constitutional rights
  • Cross-check 修法沿革 against any case decided under an older version of the statute
Persistent agent state
  • agno.db.sqlite.SqliteDb at tmp/lex_taiwan.db provides session memory
  • update_memory_on_run, enable_session_summaries, and add_history_to_context with num_history_runs=3 give multi-turn continuity
  • add_datetime_to_context lets the model reason about freshness (“cases from 2024 onwards”)

Dependencies

The MCP server mcp-taiwan-legal-db is published on PyPI — installing it provides the mcp-taiwan-legal-db entry-point binary that _mcp_server_params() launches over stdio. Optional (only needed if 司法院’s F5 WAF starts blocking):

Environment Setup

Create .env file:

Run

Try:
  • “民法第 184 條的現行條文是什麼?”
  • “釋字 748 的解釋文核心是什麼?列出至少一個被它引用的更早釋字。”
  • “Find Supreme Court cases about 預售屋 遲延交屋 from 2024 onwards.”
  • “釋字 748 的解釋日期?一句話。“

Example API Calls

Frontend Setup

Open http://localhost:5173 and try to chat with the Taiwan legal research agent.