e-Gov法令XMLをMCP用JSONへ:1条の抽出をPythonで再現する
e-Gov法令XMLから本則または指定した附則の1条をJSONへ変換。Python標準ライブラリの配布コードと架空fixtureで、条・項・号、ルビ、出典・履歴IDを保持する処理を再現できます。
e-Govの法令XMLをMCPで使う前に、必要な1条を、取得した版と出典が分かるJSONへ変換するところから確認します。本則と附則の同じ条番号を混ぜず、項・号・細目やルビを残せれば、AIの回答から原文へ戻れます。
この記事では、実行可能なPythonスクリプトと架空の入力データを配布しています。まず通信なしで試し、その後に実APIから保存したJSONへ入力を置き換えます。2026年9月26日にWindows / Python 3.10.11で検証しました。
まず通信なしで1条を変換する
同じフォルダーへ、Pythonスクリプトと架空の入力JSONを保存してください。Python 3.10以降があれば、外部パッケージは不要です。
python --versionpython egov-law-api-v2.py --out results excerpt egov-law-example-fixture.json --article 1表示される結果です。保存名の日時だけは実行ごとに変わります。
article: main 1revision: 000AC0000000001_20260101_FIXTUREsaved: results\excerpt-実行日時.json入力は実在しない法令を使ったテストデータです。FIXTUREを含む履歴IDやexample.invalidの取得URLは、実APIの取得を証明するものではありません。
excerptは保存済みJSONからBase64の本文を復号し、XMLを解析します。APIへの再取得は行いません。 同じ入力ファイルを手元に残すことで、APIの更新や接続状態と切り離して変換を確認できます。
JSONに残すのは要素・属性・順序
出力は独自形式egov-article/1です。articleに選んだArticle全体を入れ、sourceに取得条件を添えます。e-Gov公式APIのJSON形式や、MCPの通信メッセージそのものではありません。
| フィールド | 入るもの |
|---|---|
schema_version | この配布コードの出力契約egov-article/1 |
scope | mainまたはsupplementary |
article_number | XMLのArticle Num。枝番号も文字列 |
article | 要素名・属性・子要素とテキストの配列 |
provision_attributes | 本則/附則の属性。改正附則のAmendLawNumなど |
source | 法令ID、履歴ID、指定日、取得日時、URL、XMLハッシュ、抽出位置 |
各XML要素は次の3フィールドへ機械的に写します。
type XmlNode = { element: string; attributes: Record<string, string>; content: Array<string | XmlNode>;};fixtureの第1文に対応する部分は、次のJSONになります。
{ "element": "Sentence", "attributes": { "Num": "1", "Function": "main" }, "content": ["これは変換確認用の架空の本文です。"]}項・号は、それぞれParagraph、Itemの子要素として残ります。Sentence Function="proviso"も属性をそのまま保持します。本文を1本の文字列に連結せず、文字列と要素を出現順に同じ配列へ置くため、文章途中のルビや、その後に続く文章の位置を失いません。
配布コードの変換核です。
def xml_node(node): content = [] if node.text is not None: content.append(node.text) for item in node: content.append(xml_node(item)) if item.tail is not None: content.append(item.tail) return { "element": node.tag, "attributes": dict(node.attrib), "content": content, }この方法は表や未個別対応の要素も保持します。ただし、表を読みやすいセル配列へ変える、ルビの読みと本文を使い分けるといった意味上の整形は行いません。XMLの字下げ用空白も残るので、表示用の整形は出典用データと分けて追加します。
本則と附則を別々に選ぶ
公式のXML構造解説では、本則はMainProvision、附則はSupplProvisionに分かれます。同じ「第一条」が両方に存在するため、全体からArticleを一括で探すと誤引用につながります。
配布コードは、既定では本則の中のPart、Chapter、Section、Subsection、Divisionだけをたどります。改正文の内部などに入れ子で現れる別のArticleを無条件に集めません。
附則を取り出すには、入力XMLでLawBody直下のSupplProvisionを確認し、1始まりの位置を指定します。
python egov-law-api-v2.py --out results excerpt egov-law-example-fixture.json --article 1 --supplement 1このfixtureではarticle: supplementary 1と表示され、附則にだけある文を取得します。複数の改正附則を持つ法令では「1番目=最新」とは限りません。属性のAmendLawNumやラベルを原文で確認してから指定してください。
枝番号は、XMLの値を文字列のまま渡します。たとえばArticle Num="21_2"は--article 21_2です。数値へ変換して21に縮めたり、条の位置から番号を推測したりしません。
実APIの保存データへ置き換える
実法令を扱うときは、同じスクリプトのgetでAPI応答とXMLを保存します。
python egov-law-api-v2.py --out results get 331AC0000000120 --asof 2026-01-01表示されたget-実行日時.jsonを入力にします。
python egov-law-api-v2.py --out results excerpt results/get-実行日時.json --article 12026年9月26日には、同じ法令の2時点比較で保存したafter.jsonを入力にし、本則第1条を抽出できました。応答の履歴IDは331AC0000000120_20260101_507AC0000000041です。実測記録には、指定日と元XMLのハッシュを含めています。
source.xml_sha256は入力に含まれていた原文XMLのSHA-256です。抽出位置だけでなく、どの原文から作ったかも照合できます。ハッシュは取得元の真正性を証明する署名ではなく、手元の原文と対応づけるための値です。
法令IDを探す段階はPythonで法令検索・本文保存する記事を参照してください。入力URLを確認するだけなら、APIリクエスト作成ツールでも法令IDと日付を指定できます。
MCPのツールへ接続する際の境界
このCLIはMCPサーバーを起動しません。保存JSONを確認した後、ツール実装側で戻り値をstructuredContentに載せ、互換性のため同じJSONをテキストにも含める設計ができます。MCPのTools仕様で、構造化出力とツール実行エラーの扱いを確認してください。
指定した条が見つからないときは、CLIではARTICLE_NOT_FOUNDを含むメッセージと終了コード1で止まります。MCPへ接続する場合も、この失敗を「空の本文」という成功値に置き換えず、isError: trueと識別できるエラー情報へ変換します。
取得した版の確認、JSONへの変換、MCPクライアントでの表示は別々に検証します。この配布コードの動作確認だけで、特定のMCPパッケージへの組み込みや接続が済んだことにはなりません。
失敗時の確認と復旧
| メッセージ・症状 | 確認すること |
|---|---|
ARTICLE_NOT_FOUND | その版に条番号があるか、本則と附則を取り違えていないか |
SUPPLEMENT_NOT_FOUND | 直下の附則の数と、1始まりの番号 |
AMBIGUOUS_ARTICLE | 選んだ範囲でNumが重複している。XML構造を確認して処理を拡張 |
| 出典メタデータの欠落 | 本文XMLだけでなく、get/compareが保存したJSONを入力にする |
| Base64/XMLエラー | 外側JSONと本文XMLの形式、ファイルの破損 |
| 12 MiB超過 | このサンプルの入力上限。必要な範囲の設計を先に見直す |
存在しない条を試す場合は、fixtureに対して--article 999を指定できます。エラーで終了し、成功を示すJSONを新規作成しないことを確認してください。
検証記録と対応範囲
実APIで確認したのは上記の本則第1条です。それに加え、架空fixtureの回帰テストで、枝番号、本則/附則の分離、号・細目、ただし書、ルビを含む混在テキスト、表の保持、存在しない条、出典欠落、通信しない抽出を確認しました。
選んだArticleの外にある別表・様式・添付ファイルはこの出力に含めません。附則の項建てのようにArticleがない構造も、無理に条へ変換しません。全法令の完全変換ではなく、対象の原文を残したまま1条を渡すための成果物です。READMEとライセンスを添えて保存できます。
よくある質問
この変換にAPIキーやMCPサーバーは必要ですか?
不要です。excerptコマンドは保存済みJSONだけを読み、ネットワークへアクセスしません。Python 3.10以降の標準ライブラリだけで、同梱の架空fixtureから試せます。
本則と附則の第一条が混ざることはありませんか?
既定ではMainProvisionの中だけを探します。附則は—supplementで1始まりの番号を指定します。全子孫のArticleを一括検索せず、章・節など決められた構造だけをたどります。
このコードは公開中のegov-law-mcpへ組み込まれていますか?
この成果物は独立した変換用CLIです。公開MCPパッケージへの組み込みや、MCPクライアントとの接続は行っていません。JSONを確認してから、別途ツールの出力契約へ接続します。
この記事の情報・検証メモ
- mcp
- egov
- python
- japanese-law
- xml
- json
- legal-tech
- 公開日
- 情報確認
- 参考リンク
- 4件
- 更新性
- 定期更新
仕様・料金・提供範囲が変わりやすいテーマは、公開日・更新日・情報確認日を分けて管理します。 導入前には必ず記事末尾の一次情報と公式ドキュメントで最新状況を確認してください。
一次情報・参考リンク
- e-Gov法令API v2 OpenAPI仕様 https://laws.e-gov.go.jp/api/2/swagger-ui/lawapi-v2.yaml
- 法令の条文構造と法令XML https://laws.e-gov.go.jp/docs/law-data-basic/8ebd8bc-law-structure-and-xml/
- 法令標準XMLスキーマ v3 https://laws.e-gov.go.jp/file/XMLSchemaForJapaneseLaw_v3.xsd
- MCP Tools: structuredContent・isError https://modelcontextprotocol.io/specification/2025-06-18/server/tools