# houki-egov-mcp

**Category:** ⚖️ Legal  
**Repository:** https://github.com/shuji-bonji/houki-egov-mcp  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/houki-egov-mcp

## Description
Check Japanese statutes before you build: laws and ordinances from e-Gov Law API v2, per article.

## Claude Desktop Quick Installation
Heuristic fallback — verify the package name and runner against the repository README before running it. Uses `npx` (confidence: low):

```json
"mcpServers": {
  "houki-egov-mcp": {
    "command": "npx",
    "args": ["-y","houki-egov-mcp"]
  }
}
```

## Documentation & README

> [!CAUTION]
> 旧リポジトリ名 `houki-hub-mcp` / 旧 npm 名 `@shuji-bonji/houki-hub-mcp` は使っていません。
> 現行は `@shuji-bonji/houki-egov-mcp` です。

# Houki e-Gov MCP Server

[![CI](https://github.com/shuji-bonji/houki-egov-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/shuji-bonji/houki-egov-mcp/actions/workflows/ci.yml)
[![npm version](https://img.shields.io/npm/v/@shuji-bonji/houki-egov-mcp.svg)](https://www.npmjs.com/package/@shuji-bonji/houki-egov-mcp)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node](https://img.shields.io/badge/Node-%3E%3D22-brightgreen)](https://nodejs.org/)

日本の法令（憲法・法律・政令・省令・規則）を **e-Gov 法令API v2** から、条・項・号の単位で、法令番号と URL を添えて返す MCP サーバ。

LLM が条文をキーワード・略称・分野で検索したり、特定の条項を Markdown / JSON で取得したり、改正履歴を引いたりできるようにする。通達・Q&A は [`@shuji-bonji/houki-nta-mcp`](https://github.com/shuji-bonji/houki-nta-mcp) が担当し、「法律で決まっている」と「通達でそうなっている」を混ぜない。

## まず試す（ローカル DB なし）

登録するだけで、9 ツールのうち 8 つはそのまま動きます。e-Gov 法令 API v2 をその場で呼ぶためで、事前の取り込みは要りません。

```json
// claude_desktop_config.json
{
  "mcpServers": {
    "houki-egov": {
      "command": "npx",
      "args": ["-y", "@shuji-bonji/houki-egov-mcp"]
    }
  }
}
```

再起動して「消費税法第 30 条第 1 項を見せて」「インボイス制度の登録要件は」のように尋ねると、`search_law` → `get_law` の順に呼ばれ、法令番号と e-Gov の URL 付きで本文が返ります。

ローカル DB が要るのは `search_fulltext`（条文本文の横断検索）だけです。DB が無いときは `search_law`（法令名の検索）に切り替わり、応答の `source` が `"api-fallback"` になります。本文の全文検索が要ると分かったら、そのとき一度だけ下記の「CLI（ローカル DB の構築）」を実行してください。全法令 zip（約 290 MB）の取得と取り込みが走ります。

| | ローカル DB なし | ローカル DB あり |
|---|---|---|
| `search_law` `get_law` `get_toc` `get_law_range` `get_law_revisions` `resolve_abbreviation` `explain_law_type` `get_related_laws` `get_article_references` `verify_citations` `list_attachments` `get_attachment` `get_law_file` | 動く（e-Gov API をその場で呼ぶ） | 同じ |
| `search_fulltext` | `search_law` に切り替わる（`source: "api-fallback"`） | 条文本文を横断検索する（`freshness` 付き） |

## 提供ツール

| Tool | 用途 |
|---|---|
| `search_law` | 法令タイトルでキーワード検索（略称→正式名解決済み） |
| `get_law` | 条/項/号レベルで本文取得（Markdown / JSON / TOC） |
| `get_toc` | 目次のみ取得（トークン節約）。本則と附則を分け、附則は改正法ごとにまとめる（v0.13.0） |
| `get_law_range` | 編・章・節・款・目のいずれか、または附則 1 本を範囲にして条を本文ごと取得。上限を超える範囲は条の単位で打ち切り、続きの条番号を返す（v0.14.0） |
| `get_law_revisions` | 改正履歴を取得（公布日・施行日・状態） |
| `search_fulltext` | 条文本文の横断全文検索（ローカル SQLite FTS5。bulk DB 未構築時は `search_law` にフォールバック） |
| `resolve_abbreviation` | 略称→正式名解決の診断 |
| `explain_law_type` | 法令種別（憲法・法律・政令・省令・通達 等）の解説 |
| `get_related_laws` | 法令名の規則で施行令・施行規則（施行令からは親の法律）を引き、e-Gov に実在するものだけを `law_id` 付きで返す（v0.10.0） |
| `get_article_references` | 条文本文が引用している他法令の条（`law_id` 付き）・同一法令内の条項号・「政令で定める」の委任先を取り出し、`get_law` の引数を `next_actions` で付ける（v0.10.0） |
| `verify_citations` | 引用のリストをまとめて実在確認し、件ごとに `found` / `not_found` / `ambiguous` を返す（v0.11.0） |
| `list_attachments` | 法令に付いた添付ファイル（別表・様式・別記の図。jpg / pdf）の一覧。各ファイルに認証なしで開ける URL と、法令の中の置き場所（「別表第一（第一条関係）」など）を付ける（v0.15.0） |
| `get_attachment` | 添付ファイル 1 件（または zip）。既定は URL とメタ情報だけ、`save: true` でサーバー側の保存先に書いて絶対パスを返す（v0.15.0） |
| `get_law_file` | 法令本文を xml / json / html / rtf / docx のファイルで。既定は URL だけ、`save: true` で保存（v0.15.0） |

`search_fulltext` は、2 文字の語（「相殺」「時効」）を渡されたときに何をして結果を出したかを `short_tokens` で返します（v0.12.0）。索引が trigram で 3 文字以上の語しか載せないため、既定では条の本文を引かず、法令名を添える形と `scan_body: true` で走査する形を `next_actions` で示します。詳しくは[2 文字の語の検索](#2-文字の語の検索v0120)をご覧ください。

`get_toc` は、本則を `toc`、附則を改正法ごとに `suppl_provisions` へ分けて返します（v0.13.0）。既定では附則は見出しと条数だけで、`suppl: "full"` で附則の中の条まで返します。詳しくは[本則と附則の分け方](#本則と附則の分け方v0130)をご覧ください。

`list_attachments` / `get_attachment` / `get_law_file` は、条文の文字列に入らないもの（別表・様式の図、Word や HTML の本文ファイル）を取る道です（v0.15.0）。ファイルの中身は応答に入れず、認証なしで開ける URL と、`save: true` のときだけ保存先の絶対パスを返します。詳しくは[添付ファイルと法令本文ファイル](#添付ファイルと法令本文ファイルv0150)をご覧ください。

`get_law_range` は、`get_law`（1 条ずつ）と `get_toc`（目次だけ）の間を埋めます（v0.14.0）。民法の「第三編第二章 契約」のように章・節を指定すると、その中の条を本文ごと返し、長い範囲は条の単位で打ち切って続きの条番号を返します。詳しくは[章・節単位の取得](#章節単位の取得v0140)をご覧ください。

略称辞書（174 エントリ・6 分野）は [`@shuji-bonji/houki-abbreviations`](https://github.com/shuji-bonji/houki-abbreviations) を内部で利用しています。

### 施行令・施行規則と条文内の参照（v0.10.0）

`get_related_laws` と `get_article_references` は、法令名の文字列規則と条文本文の正規表現で **決定論的に引ける参照だけ** を返します。同じ入力には同じ出力になり、LLM の判断は挟みません。

- `get_related_laws({ law_name: "所得税法" })` → `related[]` に所得税法施行令（`340CO0000000096`）と所得税法施行規則（`340M50000040011`）。名前の末尾に「施行令」「施行規則」を付けた候補を e-Gov に問い合わせ、`law_title` が完全一致した 1 件だけを採用します。無かった候補は `not_found[]` に残します
- `get_article_references({ law_name: "所得税法", article: "57の2", paragraph: 2 })` → `references[]` に「雇用保険法（昭和四十九年法律第百十六号）第十条第五項第一号」が `law_id` と条・項・号付きで入り、`delegations[]` に「政令で定める」×N と委任先（所得税法施行令）が入ります。「前項」「同法」は `kind: "relative"` で解決しません
- どちらの応答にも `note` / `coverage.note` が付き、抽出できた範囲だけを返していること、網羅性を保証しないことを書いています。委任の趣旨の解釈や意味的に近い条の推薦は行いません（houki-hub#8 の法令グラフの担当）

## インストール

### Claude Desktop で使う

上の「まず試す」の `claude_desktop_config.json` の例をそのまま使います。ローカル DB は無くても動きます。

### Claude Code plugin で使う

リポジトリ同梱の [`.claude-plugin/plugin.json`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/.claude-plugin/plugin.json) が MCP server として `npx -y @shuji-bonji/houki-egov-mcp@latest` を登録します。plugin として入れた場合も、下の「Claude Desktop で使う」も、起動されるのは npm に公開された同じパッケージです。

### ローカル開発

```bash
git clone git@github.com:shuji-bonji/houki-egov-mcp.git
cd houki-egov-mcp
npm install
npm run build
npm test
```

```json
// 開発中の動作確認 (.mcp.json)
{
  "mcpServers": {
    "houki-egov-local": {
      "command": "node",
      "args": ["/absolute/path/to/houki-egov-mcp/dist/index.js"]
    }
  }
}
```

## 使用例

```
# LLM への問いかけ → MCP ツール呼び出し

「消費税法30条1項を見せて」
  → get_law(law_name="消法", article="30", paragraph=1)

「消費税法第三十条第一項を見せて」（判決文や通達からの引き写し）
  → get_law(law_name="消法", article="第三十条", paragraph=1)   # 漢数字は v0.7.0 から。項は数値で

「消費税法2条1項8号の2（特定資産の譲渡等）を見せて」
  → get_law(law_name="消法", article="2", paragraph=1, item="8の2")

「労働基準法の目次を取得」
  → get_toc(law_name="労基法")

「民法の契約の章をまとめて読みたい」
  → get_law_range(law_name="民法", part=3, chapter=2)
  → 第三編 債権 第二章 契約（198 条）を上限（既定 30,000 文字）まで返し、続きは from_article で取る

「会社法の設立の章を見せて」
  → get_law_range(law_name="会社法", path="Part2/Chapter1")   # get_toc の toc[].path をそのまま渡せる

「個人情報保護法の改正履歴を最新5件」
  → get_law_revisions(law_name="個情法", latest=5)

「電帳法って正式名称なに？」
  → resolve_abbreviation(abbr="電帳法")
  → 電子計算機を使用して作成する国税関係帳簿書類の保存方法等の特例に関する法律

「政令と省令の違いは？」
  → explain_law_type(name="政令")

「民法で不法行為について定めている条文は？」（bulk DB 構築後）
  → search_fulltext(keyword="民法 不法行為")
  → law_scope=[民法] に絞って本文検索。724 条・719 条・509 条 などが snippet 付きで返る

「民法 第709条」（法令名 + 条番号だけ）
  → search_fulltext(keyword="民法 第709条")
  → 本文検索をせず、民法 709 条を直接返す
```

## CLI（ローカル DB の構築 — v0.3.1+）

ローカル DB が要るのは `search_fulltext` だけです。それ以外の 6 ツールは DB が無くても動くので、条文本文の横断検索が要ると分かってから作れば足ります（上の「まず試す」）。

全文検索用のローカル DB（SQLite FTS5）は、e-Gov の bulk ダウンロード zip から構築します。MCP server として常駐する通常起動とは別に、フラグ付きで起動すると CLI モードで動作します。

```bash
# 全法令 zip (約 290 MB) を DL して DB に取り込む (初回)
npx @shuji-bonji/houki-egov-mcp --bulk-download-everything

# 最終同期日から今日までの日次差分を取り込む (2 回目以降。v0.8.0+)
npx @shuji-bonji/houki-egov-mcp --sync

# DB の件数と鮮度 (freshness) を表示
npx @shuji-bonji/houki-egov-mcp --status
```

`--sync` は、差分が無い日（土日など）を飛ばし、途中で失敗しても成功した日までを記録して終わります。最終同期から 90 日（`HOUKI_EGOV_INCREMENTAL_LIMIT_DAYS`）を超えて空いているときは、e-Gov の日次差分の公開範囲を超えるので、何もせずに `--bulk-download-everything` を促します。1 日分は数百 KB〜30 MB、13 日分でおよそ 1〜2 分です。

DB のデフォルト配置は `${XDG_CACHE_HOME:-~/.cache}/houki-egov-mcp/laws.db`（`HOUKI_EGOV_DB_PATH` で変更可）。

### SQLite と DB の置き場所（npx / plugin 経由で使う場合）

SQLite は本パッケージが依存する `better-sqlite3` に同梱されています（SQLite 3.53 系の amalgamation。OS の sqlite3 は使いません）。`npx` や plugin で初めて起動したときに npm が `better-sqlite3` を取り込み、実行中の Node.js と OS に合ったビルド済みバイナリ（`prebuild-install`）を GitHub Releases から取得します。対応する prebuilt がない Node.js の場合は `node-gyp` でその場でコンパイルするため、Python と C++ ビルドツール（macOS なら Xcode Command Line Tools）が必要になります。Node 22 / 24 の LTS では prebuilt が用意されているので、通常はコンパイルは走りません。

DB ファイルはパッケージの中ではなく、上記のユーザーのキャッシュディレクトリに置かれます。したがって次の 3 つは **同じ 1 つの DB** を読み書きします。

| 起動方法 | 実行されるコード | 読む DB |
|---|---|---|
| `npx @shuji-bonji/houki-egov-mcp --bulk-download-everything`（CLI） | npx のキャッシュ内のパッケージ | `~/.cache/houki-egov-mcp/laws.db` |
| Claude Desktop / Claude Code plugin（`npx -y …`） | 同上（`@latest` 指定なら起動ごとにレジストリを確認） | 同上 |
| ローカル開発（`node dist/index.js`） | リポジトリの `dist` | 同上 |

このため、DB の構築は一度 CLI で行えば、plugin 経由の `search_fulltext` からもそのまま使えます。`--bulk-download-everything` のあとに MCP server を再起動する必要はありません（`search_fulltext` は呼び出しごとに DB を開いて閉じます）。書き込みは CLI だけが行い、MCP server は読むだけです（journal は WAL なので、取り込み中に検索しても壊れません）。

DB が存在しない、または条が 1 件も入っていないときは、`search_fulltext` は `source: "api-fallback"` で `search_law` の結果を返し、`next_actions` に `--bulk-download-everything` の実行を案内します。パッケージを更新しても DB は消えません（バージョン間の互換は上の注記のとおり、必要なときだけ再構築を案内します）。

DB を構築すると `search_fulltext` が条文本文を SQLite FTS5 で検索します（v0.5.0〜）。略称は正式名称に OR 展開され（`消法` → `消費税法`）、「民法 不法行為」「労基法 時間外」のように法令名と語を並べるとその法令の条に絞って本文を検索します。各ヒットに条番号・snippet・score・DB の鮮度（`freshness`）が付きます。DB が未構築のときは従来どおり `search_law`（法令名のタイトル一致）にフォールバックし、`note` でその旨を返します。

> **v0.5.0 以前に構築した DB について**: v0.5.0 で本文の正規化を投入時に行うようになり（スキーマバージョン 2、旧 DB は起動時に自動初期化）、v0.5.1 で編（Part）を持つ法令の本則が取り込まれていなかった不具合を直しました。いずれの場合も `--bulk-download-everything` を再実行してください（v0.5.1 では全件が再 ingest されます）。
>
> **検索語の制約**: 索引が trigram のため、条文本文は 3 文字以上の語で索引から引きます。2 文字の語（「相殺」「時効」等）の扱いは v0.12.0 で変わりました（下記）。「第30条」のような条番号は本文検索には使わず、該当条を上位に寄せる加点にだけ使います（漢数字は未対応）。

### 添付ファイルと法令本文ファイル（v0.15.0）

法令には、条文の文字列に入らないものが付いています。別表・様式・別記の図（e-Gov では jpg か pdf）と、法令全体を 1 つのファイルにした本文（xml / json / html / rtf / docx）です。`get_law` の Markdown には図の中身は入らず、様式の図が要る作業（届書の書式、旗の寸法図）は条文だけでは済みません。v0.15.0 の 3 ツールはそのための道です。

```
「戸籍法施行規則の出生届の様式を見たい」
  → list_attachments(law_name="戸籍法施行規則")
     attachments[] の location.title が「附録第十一号様式」の 1 件（pdf）の url を得る
  → pdf-reader-mcp の read_url(url=…)                          # URL は認証なしで開ける
  （またはディスクに置くなら）
  → get_attachment(law_name="戸籍法施行規則", src="./pict/2FH00000076885.pdf", save=true)
     → saved.path を pdf-reader-mcp の read_text に渡す

「民法の全文を Word で」
  → get_law_file(law_name="民法", file_type="docx", save=true)
     → saved.path（182 KB）。saved.law_revision_id にどの履歴の本文かが入る
```

- **中身は返しません**。バイナリを base64 にして応答に入れることはせず、URL（`https://laws.e-gov.go.jp/api/2/attachment/<law_revision_id>?src=…`、`…/law_file/<file_type>/<law_id>`）を返します。URL は認証なしで開けるので、pdf-reader-mcp の `read_url` や、利用者のブラウザーにそのまま渡せます
- **保存先はサーバー側で決めます**。`save: true` のときだけファイルを取得し、`${XDG_CACHE_HOME:-~/.cache}/houki-egov-mcp/files/<law_revision_id>/<ファイル名>` に書いて `saved.path` を返します。保存先は環境変数 `HOUKI_EGOV_FILES_DIR` で変えられますが、ツールの引数にはありません（LLM が渡した文字列をパスに使わないため）。1 ファイル 50 MB を超えるときは保存せず `INVALID_ARGUMENT` を返します
- **置き場所を付けます**。`list_attachments` は e-Gov の `attached_files_info`（src と更新日時）と本文の `Fig` 要素を `src` で突き合わせ、各ファイルに `location`（別表・様式の見出しと関係条文、条の中なら条番号、附則の中なら改正法番号）を付けます。一覧にだけあって本文に無いファイルは `location: null` です
- 添付ファイルは法令履歴ごとに付くので、`at` で時点を変えると一覧も変わります。添付が無い法令は `list_attachments` では `count: 0` の成功応答、`get_attachment` では `ATTACHMENT_NOT_FOUND` です
- `get_law_file` の `xml` / `json` は法令全体（民法で 1.6 MB）なので、条文を読むだけなら `get_law` / `get_law_range` を使ってください。`docx` / `html` / `rtf` は人が開く版です

### 章・節単位の取得（v0.14.0）

`get_law_range` は、編・章・節・款・目のいずれか、または附則 1 本を範囲にして、その中の条を本文ごと返します。`get_law` で 1 条ずつ引くと手数がかかり、法令全体を返すには長すぎる法令（民法・会社法・消費税法）のためのツールです。

範囲の指定は次の 3 通りで、同時に指定できるのは 1 つだけです。

| 指定 | 書き方 |
|---|---|
| 編・章・節・款・目の番号 | `part=3, chapter=2`（`"三"`・`"第三編"`・枝番号の `"2の2"` も可） |
| 範囲のパス | `path="Part3/Chapter2"`（`get_toc` の `toc[].path` をそのまま渡せます） |
| 附則 | `suppl_index=12`（`get_toc` の `suppl_provisions[].index`。`search_fulltext` が「附則(12) 1」と表示する番号と同じ） |

章番号は編ごとに振り直されます（民法には第一章が 5 つ、第一節が 19 あります）。`chapter` だけを指定して複数の範囲に当たったときは、候補のパスを `hint` と `next_actions` に入れた `INVALID_ARGUMENT` を返します。

大きい範囲は `max_chars`（既定 30,000 文字）で条の単位で打ち切ります。条の途中では切らないため、1 条目だけは上限を超えても返します。2026-09-20 に測った条本文のサイズは次のとおりです（UTF-8 の日本語は 1 文字 3 バイト）。

| 法令 | 章の条本文（中央値 / 最大） | 既定の上限での回数 |
|---|---|---|
| 民法 | 6.2 KB / 98.2 KB | ほとんどの章は 1 回。第三編第一章（183 条）は 2 回 |
| 会社法 | 17.9 KB / 207.6 KB | 大きい章は 2〜3 回 |
| 所得税法 | 10.8 KB / 229.1 KB | 大きい章は 2〜3 回 |
| 消費税法 | 59.5 KB / 102.4 KB | 章は 2〜4 回（編が無く章が大きい） |

打ち切ったときの応答の `range` は次の形です。

```jsonc
{
  "path": "Part3/Chapter2",
  "titles": ["第三編　債権", "第二章　契約"],
  "tag": "Chapter",
  "article_count": 198,      // 範囲が持つ条の数
  "returned_count": 186,     // 本文を返した条の数
  "skipped_count": 0,        // from_article より前で返さなかった条の数
  "first_article": "第521条",
  "last_article": "第684条",
  "truncated": true,
  "body_chars": 29911,
  "max_chars": 30000,
  "next_from_article": "685",
  "note": "範囲の条 198 件のうち 186 件を返しました（第521条〜第684条）。本文 29,911 文字（上限 30,000 文字）。上限で打ち切りました。続きは from_article: \"685\" を付けて同じ範囲を呼び直してください。"
}
```

`from_article` に `next_from_article` の値を渡すと、同じ範囲の続きから返します。条を立てず項だけで書かれた附則（「1 この法律は、公布の日から施行する。」の形）は、範囲の本文をそのまま返します。

削除された条は、e-Gov の法令データでは複数の条をまとめた範囲表記になっています（民法第534条は `Article Num="534:535"`、見出しは「第五百三十四条及び第五百三十五条」、本文は「削除」）。応答ではこれを `第534条及び第535条`（3 条以上なら `第170条から第174条まで`）と表示し、`next_from_article` にも `"534:535"` の形を返すので、そのまま `from_article` に渡せます（v0.14.1）。なお `get_law` に `article: "534"` を渡してこの条を引くことは、まだできません。

### 本則と附則の分け方（v0.13.0）

附則は改正法ごとに 1 本ずつ積み上がります（所得税法は 352 本・条 983 件）。v0.12.1 までの `get_toc` は、この附則の条を本則の章の後ろにそのまま並べていたため、いま効いている規定と、ある改正法の施行日・経過措置の区別が目次から付きませんでした。

v0.13.0 からは、本則を `toc`、附則を `suppl_provisions` に分けて返します。附則 1 本は次の形です。

```jsonc
{
  "index": 2,                                        // LawBody の中での並び順。ローカル DB の Suppl2_1 と同じ番号
  "label": "附則",
  "amend_law_num": "平成元年六月二八日法律第三九号",  // どの改正法の附則か。制定時の附則には付かない
  "extract": true,                                   // 抄（改正法の附則のうち一部だけを載せた形）
  "article_count": 1,
  "paragraph_only": false,                           // 条を立てず項だけで書かれた附則か
  "children": []                                     // suppl: "full" のときだけ中の目次が入る
}
```

`suppl` で附則をどこまで返すかを選びます。

| `suppl` | 返すもの | 所得税法の Markdown |
|---|---|---|
| `"list"`（既定） | 改正法ごとの見出しと条数だけ | 752 行 / 54.5 KB |
| `"full"` | 附則の中の条まで | 1,735 行 / 114.4 KB |
| `"none"` | 附則を返さない（本数と条数は `suppl.count` / `suppl.article_count` に入る） | 395 行 / 24.6 KB |

既定を `"list"` にしているのは、附則の条が目次の大半を占めるためです（所得税法は本則 388 ノードに対し附則の条 983 件）。何を返したかは `suppl.note` に書きます。

`with_amend_titles: true` を付けると、改正法の題名も付けます。附則の属性には法令番号しか無いため、改正履歴（`get_law_revisions` と同じ e-Gov の応答）を 1 回引き、法令番号で照合します。2 つの表記は違うので（附則は `令和七年六月二〇日法律第七四号`、改正履歴は `令和七年法律第七十四号`）、公布の月日と漢数字の書き方を落とした「元号 + 年 + 種別 + 号数」で突き合わせます。e-Gov の改正履歴は近年の改正が中心なので、それより古い改正法には題名が付きません（消費税法は附則 167 本のうち 28 本に付き、改正履歴は 65 件）。付いた本数と付かなかった本数は `suppl.amend_law_titles` に入ります。

`get_law` の `format: "toc"` でも本則と附則を分け、附則は見出しだけを返します。

### 2 文字の語の検索（v0.12.0）

「相殺」「時効」「善意」のような 2 文字の法律用語は、条本文の索引 `articles_fts`（trigram）に載りません。v0.12.0 からは、そのときに何をして結果を出したかを応答の `short_tokens` で返します。

| クエリ | `body_search` | 何をするか |
|---|---|---|
| `適格請求書 保存` | `fts_then_filter` | 3 文字以上の語で索引を引き、その条の本文に 2 文字語が含まれるかで絞る |
| `労基法 協定` | `like_in_law_scope` | 法令名で対象法令を絞り、その範囲の条の本文を引く |
| `相殺` | `not_searched` | 条の本文は引かず、法令名・略称・番号の照合だけを返す（既定） |
| `相殺` + `scan_body: true` | `like_all_articles` | 索引を使わず、全法令の条の本文を端から照合する |

`short_tokens.hits_by_match_type` に `article`（条本文由来）と `law_meta`（法令名・略称・番号由来）の件数が入ります。v0.11.0 までは「相殺」で「相殺関税に関する政令」だけが返り、条の本文が引かれなかったことが応答から分かりませんでした。

既定で `not_searched` にしているのは、全法令の走査に時間がかかるためです。2026-09-20 に実データ（条 1,434,710 件・本文 587,926,852 バイト）で測ったところ、ヒットが多く上限 150 件で打ち切れる語で 5.4 秒、該当が少なく全表を走り切る語で 22 秒かかりました。`LIKE` を `instr` や `GLOB` に変えても、JOIN を外しても同じ時間です。588 MB を読んで照合する分そのものなので、書き方では縮みません。

そのため `not_searched` の `next_actions` は 2 つの道を示します。

1. `{ keyword: "民法 相殺" }` — 法令名を添えると、その法令の条に絞って索引で引けます（速く、並び順も関連度順）
2. `{ keyword: "相殺", scan_body: true }` — 法令名が分からないときの最後の手段です。5〜20 秒かかり、並び順は関連度順になりません。上限（150 件）で打ち切ったときは `truncated: true` になります

3 文字以上の語を含むクエリでは索引を引くので、`scan_body` は効きません。

### 引用の実在確認（v0.11.0）

`verify_citations` は、回答に添える引用のリストを送り出す前に、**その条（指定があれば項・号）が e-Gov の法令にあるか** を 1 回の呼び出しでまとめて確かめます。存在しない引用が混ざっていてもツール全体はエラーにならず、件ごとに判定が返ります。

```jsonc
{
  "citations": [
    { "law_name": "所法", "article": "9", "paragraph": 1, "item": 1, "label": "所法9①一" },
    { "law_name": "電子帳簿保存法", "article": "7" },
    { "law_name": "所得税法", "article": "9999" }
  ]
}
```

- 上の 3 件は順に `found`（条見出し「（非課税所得）」付き）、`found`（`resolved_by: "exact_title"` で `410AC0000000025`）、`not_found`（`code: "ARTICLE_NOT_FOUND"`）になります
- `summary` に件数の内訳と `all_found` が入るので、「全部実在した」と書いてよいかを 1 つの値で判断できます
- 法令名が e-Gov の法令名と完全一致しなければ `ambiguous` にし、部分一致の候補を `candidates[]` に最大 5 件返します（例: 「所得税法施行」→ 所得税法施行令・所得税法施行規則）。項が複数ある条で項を書かずに号だけを指定した件も `ambiguous` です
- 通達など houki-egov の管轄外の引用は `OUT_OF_SCOPE` にし、`next_actions` で `houki-nta` を指します
- 確かめるのは条文が実在するかどうかだけです。引用した条文が主張を支えるかどうかは判定しません
- e-Gov に問い合わせられなかったときは、件ごとの判定を返さずツール全体を `SOURCE_*` エラーにします。「聞けなかった」を「存在しない」と書かないためです

## 状態

**v0.15.0 (2026-09-20)**

- [x] e-Gov 法令API v2 クライアント（`searchLaws` / `getLawData` / `getLawRevisions` / `getAttachment` / `getLawFile`）
- [x] 法令ツリー走査（条/項/号、目次抽出）+ LRU cache
- [x] 14 ツール本実装
- [x] 略称辞書を [`@shuji-bonji/houki-abbreviations`](https://github.com/shuji-bonji/houki-abbreviations) ^0.4.1 に分離
- [x] 法令階層ナレッジ（憲法・法律・政令・省令・規則・条例・告示・訓令・通達・通知 の10種別）
- [x] houki-hub family 共通の error contract（`SOURCE_*` / `OUT_OF_SCOPE`）に準拠
- [x] Phase 2 基盤：bulk DL → SQLite FTS5 の取り込みパイプライン（schema / CSV・XML parser / zip fetcher / ingester / freshness / CLI）
- [x] Phase 2-7: `search_fulltext` の FTS5 本実装（略称 OR 展開 / revision 重複排除 / relevance scoring / freshness）
- [x] MCP SDK v2（`@modelcontextprotocol/server`）/ Node 22・24 / TypeScript 7 / Biome
- [x] Trusted Publisher (OIDC) で publish
- [x] `get_law` の `item` で枝番号の号（`"8の2"`・`"第8号の2"`）を指定（v0.6.0）
- [x] ツールの引数の型を inputSchema から導き（json-schema-to-ts の `FromSchema`）、未知の引数は `INVALID_ARGUMENT`（v0.6.0）
- [x] `get_law` の `article` / `item` で漢数字（`"第三十条の二"`・`"八の二"`）と全角数字を受け付ける（v0.7.0）
- [x] `--sync` で最終同期日から今日までの日次差分を取り込む。差分が無い日は飛ばし、途中で失敗しても成功した日までを記録（v0.8.0）
- [x] `get_related_laws` / `get_article_references`: 施行令・施行規則の関連付けと条文内の参照抽出（v0.10.0、Issue #20）
- [x] `verify_citations`: 引用リストの実在確認（v0.11.0、Issue #18）
- [x] `search_fulltext` の 2 文字語（「相殺」「時効」）の扱いを `short_tokens` で明示し、`scan_body` で全走査を選べるようにした（v0.12.0、Issue #23）
- [x] `get_toc` で本則と附則を分け、附則を改正法ごとにまとめた（v0.13.0、Issue #24）
- [x] `get_law_range`: 編・章・節（または附則 1 本）を範囲にした条文の取得（v0.14.0、Issue #22）
- [x] `list_attachments` / `get_attachment` / `get_law_file`: 添付ファイル（別表・様式の図）と xml / html / rtf / docx の本文ファイル（v0.15.0、Issue #19）
- [x] テストスイート（**456 tests**）

### 計画中

- [x] Phase 2-8: 差分同期（`--sync`）— v0.8.0
- [ ] Phase 2-13: API enrichment（`category` / 改正履歴 / 廃止ステータスの精緻化）
- [x] 漢数字対応（「第三十条」を 30 に変換）— v0.7.0 で `get_law` の `article` / `item` に対応。`search_fulltext` のキーワード中の「第三十条」は未対応
- [x] 大規模法令の応答サイズ対策（民法・会社法）— v0.14.0 の `get_law_range` で章・節単位の取得に対応

## houki-hub MCP family

houki-egov-mcp は **単体で利用可能**ですが、houki-hub MCP family の一員でもあります。同じ family 内の他 MCP と組み合わせると、通達・判例等まで横断的に扱えます。

| パッケージ | 役割 | 状態 |
|---|---|---|
| [`@shuji-bonji/houki-abbreviations`](https://github.com/shuji-bonji/houki-abbreviations) | 略称辞書・正規化・freshness 判定（共有ライブラリ） | ✅ v0.5.0 |
| **`@shuji-bonji/houki-egov-mcp`** | **e-Gov 法令API クライアント + ローカル全文検索（このリポジトリ）** | ✅ v0.5.1 |
| [`@shuji-bonji/houki-nta-mcp`](https://github.com/shuji-bonji/houki-nta-mcp) | 国税庁通達・Q&A・タックスアンサー・文書回答事例 | ✅ v0.9.5 |
| [`houki-research-skill`](https://github.com/shuji-bonji/houki-research-skill) | family を横断する Claude Skill（error contract の正典） | ✅ |
| `@shuji-bonji/houki-mhlw-mcp` | 厚労省通達・通知 | 計画中 |
| `@shuji-bonji/houki-court-mcp` | 判例（裁判所サイト） | 構想中 |
| `@shuji-bonji/houki-saiketsu-mcp` | 国税不服審判所裁決 | 構想中 |

family 全体の設計思想・想定利用シーン・業法との関係は [`docs/DESIGN.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/docs/DESIGN.md) を参照。

## エラー応答 (houki-hub family contract)

**v0.3.0** より、本 MCP のエラー応答は **houki-hub family 共通契約**に完全準拠します。`code` 文字列は family 全体で統一された語彙を使用するため、複数の MCP を併用しても LLM・Skill 層は一貫したロジックで解釈できます。

- [`docs/ERROR-CODES.md`](https://github.com/shuji-bonji/houki-research-skill/blob/main/docs/ERROR-CODES.md) — 共通エラーコード語彙の正典 (houki-research-skill)
- [`docs/ERROR-HANDLING.md`](https://github.com/shuji-bonji/houki-research-skill/blob/main/docs/ERROR-HANDLING.md) — 解釈ポリシー / next_actions テンプレ

houki-egov-mcp の [`src/errors.ts`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/src/errors.ts) は family 全体の **リファレンス実装**として位置付けられています。他 MCP は同じ `code` 語彙を共有しつつ、共通パッケージへの依存は持たずに独立実装します。

```json
{
  "error": "法令『消費税法』第3000条は存在しません",
  "code": "ARTICLE_NOT_FOUND",
  "hint": "条番号を get_toc で確認してください",
  "next_actions": [
    { "action": "get_toc", "reason": "目次で正しい条番号を特定", "example": { "law_name": "消費税法" } }
  ],
  "retryable": false
}
```

### 本 MCP で使用するコード

| code | 用途 | retryable |
|---|---|---|
| `INVALID_ARGUMENT` | 引数が `tools/list` の `inputSchema` に合わない（型・必須・enum・inputSchema に無い引数。`detail.issues[]` に内訳）、キーワード未指定、`get_law` で項が複数ある条に `paragraph` なしで `item` を指定した、`get_law_range` で範囲の指定が無い・2 通り同時・複数の章に当たった、`get_attachment` / `get_law_file` の保存でファイルが 50 MB を超えた 等 | `false` |
| `INVALID_ARTICLE_NUM` | 条番号・号番号のフォーマットが不正 (例: "30-2"、位ごとに並べた "三〇") | `false` |
| `OUT_OF_SCOPE` | 通達名で `get_law` を呼んだ等、別 MCP の管轄リソースが要求された | `false` |
| `LAW_NOT_FOUND` | 略称解決・検索のいずれでも法令が見つからない | `false` |
| `ARTICLE_NOT_FOUND` | 指定された条/項/号が見つからない（`get_law_range` の `from_article` がその範囲に無い場合を含む） | `false` |
| `RANGE_NOT_FOUND` | `get_law_range` で指定された編・章・節（または附則の番号）が見つからない | `false` |
| `ATTACHMENT_NOT_FOUND` | `get_attachment` で指定された `src` がその法令履歴の添付に無い、添付が 1 件も無い、または e-Gov の `/attachment` が「存在しない」（code 404003）を返した | `false` |
| `SOURCE_API_ERROR` | e-Gov API がエラー応答 (4xx/5xx) | 状況による |
| `SOURCE_TIMEOUT` | e-Gov API がタイムアウト | `true` |
| `SOURCE_RATE_LIMITED` | e-Gov API がレート制限 (HTTP 429) | `true` |
| `SOURCE_UNAVAILABLE` | DNS 失敗 / ECONNREFUSED 等で e-Gov に到達不能 | `true` |
| `INTERNAL_ERROR` | 内部エラー (バグ・予期せぬ例外) | `false` |
| `UNKNOWN_TOOL` | 存在しない tool 名が呼ばれた | `false` |

### `verify_citations` の code は件ごとに付きます（v0.11.0）

`verify_citations` は、存在しない引用が混ざっていてもツール全体を `isError` にしません。上の表の `code` は `results[]` の 1 件ごとに付き、`LAW_NOT_FOUND` / `ARTICLE_NOT_FOUND` / `INVALID_ARTICLE_NUM` / `OUT_OF_SCOPE` / `INVALID_ARGUMENT` のいずれかです。法令名が完全一致せず候補が複数あった件は `status: "ambiguous"` と `candidates[]` だけを返し、`code` は付きません。

ツール全体がエラーになるのは、引数の形が壊れているとき（`INVALID_ARGUMENT`）と、e-Gov に問い合わせられなかったとき（`SOURCE_*`）だけです。後者で件ごとの判定を返さないのは、「聞けなかった」を「存在しない」と書かないためです。

### Migration (v0.2.x → v0.3.0)

- v0.2.x までは `EGOV_API_ERROR` / `EGOV_TIMEOUT` / `EGOV_RATE_LIMITED` を返していました。v0.3.0 からは family 共通の `SOURCE_API_ERROR` / `SOURCE_TIMEOUT` / `SOURCE_RATE_LIMITED` に切替。
- `EGOV_*` は `LawErrorCode` の型としては残置していますが、本 MCP からはもう発行しません。次のメジャー (v1.0.0) で削除予定。
- 構造化エラーの形 (`{ error, code, hint?, next_actions?, retryable?, detail? }`) は不変。クライアント側で `code` 文字列の比較をしている場合は `SOURCE_*` を受け付けるよう更新してください。
- `OUT_OF_SCOPE` を新たに受け取る可能性があります。例えば「消基通」(消費税法基本通達 / 国税庁の通達) を `get_law` の `law_name` に渡すと、`next_actions[0].example.mcp = "houki-nta"` を含む `OUT_OF_SCOPE` が返されるので、Skill 層は houki-nta-mcp に切り替えてください。

## ドキュメント

- [`docs/LAW-HIERARCHY.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/docs/LAW-HIERARCHY.md) — 法令種別の階層リファレンス（専門家でない利用者向け）
- [`docs/USE-CASES.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/docs/USE-CASES.md) — プロダクト開発の典型ユースケース（電帳法・電子契約・個情法・e-KYC）
- [`docs/DESIGN.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/docs/DESIGN.md) — 設計原則・houki-hub family のロードマップ・業法との関係
- [`DISCLAIMER.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/DISCLAIMER.md) — 利用上の注意（業法との関係）
- [`CONTRIBUTING.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/CONTRIBUTING.md) — 貢献方法
- [`CHANGELOG.md`](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/CHANGELOG.md) — リリースノート

## 業法との関係

本MCPは **一次情報の取得・提示のみ** を担います。分析は LLM、判断は利用者（または有資格者）の責任です。**業としての法律事務・税務業務への利用は想定外**です — 詳細は [DISCLAIMER.md](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/DISCLAIMER.md) 参照。

## デジタル庁公式 MCP との関係

デジタル庁は 2025年12月〜2026年3月の「法令×デジタル」ハッカソンで法令API / MCP のプロトタイプを試行提供した。将来一般公開された場合は、本 MCP のコアを公式 MCP に委譲し、houki-hub family 全体は **公式が手を出さないレイヤ（通達・裁決・判例の横断インデックス、業法対応 Skill 等）** に注力する方針。

## ライセンス

MIT — 個人利用・学習用途のフォーク・改変・再配布を自由に許可します。

ただし、**業としての使用（弁護士法72条・税理士法52条・社労士法27条が定める独占業務）** については想定外であり、作者は一切の責任を負いません。[DISCLAIMER.md](https://github.com/shuji-bonji/houki-egov-mcp/blob/HEAD/DISCLAIMER.md) を必ずご確認ください。

