building-standards-act-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +301 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +14 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/cache.d.ts +11 -0
  7. package/dist/lib/cache.js +44 -0
  8. package/dist/lib/cache.js.map +1 -0
  9. package/dist/lib/egov-client.d.ts +11 -0
  10. package/dist/lib/egov-client.js +67 -0
  11. package/dist/lib/egov-client.js.map +1 -0
  12. package/dist/lib/egov-parser.d.ts +35 -0
  13. package/dist/lib/egov-parser.js +498 -0
  14. package/dist/lib/egov-parser.js.map +1 -0
  15. package/dist/lib/errors.d.ts +18 -0
  16. package/dist/lib/errors.js +37 -0
  17. package/dist/lib/errors.js.map +1 -0
  18. package/dist/lib/kokuji-registry.d.ts +19 -0
  19. package/dist/lib/kokuji-registry.js +63 -0
  20. package/dist/lib/kokuji-registry.js.map +1 -0
  21. package/dist/lib/law-registry.d.ts +27 -0
  22. package/dist/lib/law-registry.js +623 -0
  23. package/dist/lib/law-registry.js.map +1 -0
  24. package/dist/lib/types.d.ts +70 -0
  25. package/dist/lib/types.js +3 -0
  26. package/dist/lib/types.js.map +1 -0
  27. package/dist/server.d.ts +2 -0
  28. package/dist/server.js +42 -0
  29. package/dist/server.js.map +1 -0
  30. package/dist/tools/get-full-law.d.ts +2 -0
  31. package/dist/tools/get-full-law.js +40 -0
  32. package/dist/tools/get-full-law.js.map +1 -0
  33. package/dist/tools/get-kokuji.d.ts +2 -0
  34. package/dist/tools/get-kokuji.js +79 -0
  35. package/dist/tools/get-kokuji.js.map +1 -0
  36. package/dist/tools/get-law.d.ts +2 -0
  37. package/dist/tools/get-law.js +46 -0
  38. package/dist/tools/get-law.js.map +1 -0
  39. package/dist/tools/search-law.d.ts +2 -0
  40. package/dist/tools/search-law.js +54 -0
  41. package/dist/tools/search-law.js.map +1 -0
  42. package/package.json +42 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sora-bluesky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,301 @@
1
+ # building-law-mcp
2
+
3
+ 建築確認申請に必要な法令・告示を e-Gov 法令 API からリアルタイム取得する MCP サーバー。
4
+
5
+ AI の建築法規回答に含まれるハルシネーションを、条文原文との照合によって防ぐ。
6
+
7
+ ## 特徴
8
+
9
+ - **法令取得** — e-Gov 法令 API v2 から条文を Markdown 形式で取得
10
+ - **法令検索** — キーワードで法令を横断検索
11
+ - **法令全文取得** — 法令全体のテキストを取得
12
+ - **告示取得** — 建築基準法が技術基準を委任している告示を取得(e-Gov API 検索)
13
+ - **主要法令プリセット** — 建築基準法・消防法・都市計画法ほか 70 法令の law_id をハードコード
14
+ - **略称対応** — 「建基法」「都計法」「消防法」等の略称で指定可能
15
+ - **キャッシュ** — 検索 30 分・法令データ 24 時間の TTL キャッシュ
16
+
17
+ ## セットアップ
18
+
19
+ ### npx(推奨)
20
+
21
+ インストール不要で実行できます。
22
+
23
+ ```bash
24
+ npx -y building-law-mcp
25
+ ```
26
+
27
+ ### Claude Desktop
28
+
29
+ `claude_desktop_config.json` に以下を追加してください。
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "building-law": {
35
+ "command": "npx",
36
+ "args": ["-y", "building-law-mcp"]
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ ### Claude Code
43
+
44
+ ```bash
45
+ claude mcp add building-law -- npx -y building-law-mcp
46
+ ```
47
+
48
+ ### ローカル(ソースから)
49
+
50
+ ```bash
51
+ git clone https://github.com/Sora-bluesky/building-standards-act-mcp.git
52
+ cd building-standards-act-mcp
53
+ npm install
54
+ npm run build
55
+ ```
56
+
57
+ ```json
58
+ {
59
+ "mcpServers": {
60
+ "building-law": {
61
+ "command": "node",
62
+ "args": ["/path/to/building-standards-act-mcp/dist/index.js"]
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ ## MCP ツール
69
+
70
+ | ツール | 説明 |
71
+ | -------------- | ------------------------------------------------------------------------------- |
72
+ | `get_law` | 条番号を指定して法令の条文を取得する。略称・正式名称のいずれでも指定可能 |
73
+ | `get_full_law` | 法令の全文を取得する。条番号を指定せず法令全体のテキストを返す |
74
+ | `search_law` | キーワードで建築関連法令を横断検索する。プリセット法令と e-Gov API の両方を検索 |
75
+ | `get_kokuji` | 建築基準法が技術基準を委任している告示の全文を取得する |
76
+
77
+ ### パラメータ
78
+
79
+ #### `get_law`
80
+
81
+ | パラメータ | 説明 | 例 |
82
+ | ---------------- | ---------------------------- | -------------------------- |
83
+ | `law_name` | 法令名(正式名称または略称) | `建築基準法`, `建基法` |
84
+ | `article_number` | 条文番号 | `第20条`, `20`, `第6条の2` |
85
+
86
+ #### `get_full_law`
87
+
88
+ | パラメータ | 説明 | 例 |
89
+ | ---------- | ---------------------------- | ---------------------------- |
90
+ | `law_name` | 法令名(正式名称または略称) | `建築基準法施行令`, `建基令` |
91
+
92
+ #### `search_law`
93
+
94
+ | パラメータ | 説明 | 例 |
95
+ | ---------- | -------------- | ---------------------- |
96
+ | `keyword` | 検索キーワード | `耐火構造`, `用途変更` |
97
+
98
+ #### `get_kokuji`
99
+
100
+ | パラメータ | 説明 | 例 |
101
+ | ------------- | ------ | ------------------------------ |
102
+ | `kokuji_name` | 告示名 | `耐火構造の構造方法を定める件` |
103
+
104
+ ## 使用例
105
+
106
+ ### 条文取得
107
+
108
+ ```
109
+ 建築基準法第20条を取得して
110
+ → get_law(law_name="建築基準法", article_number="20")
111
+ ```
112
+
113
+ ### 略称使用
114
+
115
+ ```
116
+ 建基法第6条の2を取得して
117
+ → get_law(law_name="建基法", article_number="第6条の2")
118
+ ```
119
+
120
+ ### 法令検索
121
+
122
+ ```
123
+ 耐火構造に関する法令を検索して
124
+ → search_law(keyword="耐火構造")
125
+ ```
126
+
127
+ ### 全文取得
128
+
129
+ ```
130
+ 建築基準法施行令の全文を取得して
131
+ → get_full_law(law_name="建築基準法施行令")
132
+ ```
133
+
134
+ ### 告示取得
135
+
136
+ ```
137
+ 耐火構造の構造方法を定める件を取得して
138
+ → get_kokuji(kokuji_name="耐火構造の構造方法を定める件")
139
+ ```
140
+
141
+ ## ハルシネーション防止ワークフロー
142
+
143
+ 本ツールを使って AI の建築法規回答の正確性を担保するワークフローです。
144
+
145
+ 1. Claude が建築法規の質問に仮回答を作成
146
+ 2. 引用した条文・告示番号を `get_law` / `get_kokuji` で取得
147
+ 3. 実際の原文と仮回答を照合し、誤りがあれば修正
148
+ 4. 2〜3 を収束するまで繰り返す(最大 4 ラウンド)
149
+
150
+ ## 対応法令一覧(70 法令)
151
+
152
+ ### 第1章 総則(4 法令)
153
+
154
+ | 法令名 | 略称 |
155
+ | ------------------ | -------------------- |
156
+ | 建築基準法 | 建基法, 基準法 |
157
+ | 建築基準法施行令 | 建基令, 基準法施行令 |
158
+ | 建築基準法施行規則 | 建基規則 |
159
+ | 民法 | — |
160
+
161
+ ### 第2章 手続関連規定(5 法令)
162
+
163
+ | 法令名 | 略称 |
164
+ | ---------------- | ------------ |
165
+ | 建築士法 | 士法 |
166
+ | 建築士法施行令 | 士法施行令 |
167
+ | 建築士法施行規則 | 士法施行規則 |
168
+ | 建設業法 | — |
169
+ | 建設業法施行令 | — |
170
+
171
+ ### 第3章 集団規定・街づくり規定(8 法令)
172
+
173
+ | 法令名 | 略称 |
174
+ | -------------------------------------------------- | -------- |
175
+ | 都市計画法 | 都計法 |
176
+ | 都市計画法施行令 | 都計令 |
177
+ | 都市再開発法 | 再開発法 |
178
+ | 景観法 | — |
179
+ | 密集市街地における防災街区の整備の促進に関する法律 | 密集法 |
180
+ | 都市の低炭素化の促進に関する法律 | 低炭素法 |
181
+ | 屋外広告物法 | — |
182
+ | 文化財保護法 | — |
183
+
184
+ ### 第4章 防火規定・耐火規定(2 法令)
185
+
186
+ | 法令名 | 略称 |
187
+ | ------------ | ------ |
188
+ | 消防法 | — |
189
+ | 消防法施行令 | 消防令 |
190
+
191
+ ### 第7章 設備関連規定(1 法令)
192
+
193
+ | 法令名 | 略称 |
194
+ | -------- | ---- |
195
+ | 浄化槽法 | — |
196
+
197
+ ### 第9章 建築基準関係規定・建築関連法令(42 法令)
198
+
199
+ <details>
200
+ <summary>法令一覧を表示</summary>
201
+
202
+ | 法令名 | 略称 |
203
+ | ------------------------------------------------------------ | -------------------- |
204
+ | 旅館業法 | — |
205
+ | 食品衛生法 | — |
206
+ | 風俗営業等の規制及び業務の適正化等に関する法律 | 風営法, 風適法 |
207
+ | 興行場法 | — |
208
+ | 公衆浴場法 | — |
209
+ | 医療法 | — |
210
+ | 児童福祉法 | — |
211
+ | 社会福祉法 | — |
212
+ | 老人福祉法 | — |
213
+ | 学校教育法 | — |
214
+ | 駐車場法 | — |
215
+ | 火薬類取締法 | — |
216
+ | 高圧ガス保安法 | — |
217
+ | 液化石油ガスの保安の確保及び取引の適正化に関する法律 | 液石法, LPガス法 |
218
+ | ガス事業法 | — |
219
+ | 電気事業法 | — |
220
+ | 宅地造成及び特定盛土等規制法 | 盛土規制法, 宅造法 |
221
+ | 宅地建物取引業法 | 宅建業法 |
222
+ | 道路法 | — |
223
+ | 土地収用法 | — |
224
+ | 農地法 | — |
225
+ | 森林法 | — |
226
+ | 河川法 | — |
227
+ | 港湾法 | — |
228
+ | 地すべり等防止法 | — |
229
+ | 急傾斜地の崩壊による災害の防止に関する法律 | 急傾斜地法 |
230
+ | 土砂災害警戒区域等における土砂災害防止対策の推進に関する法律 | 土砂災害防止法 |
231
+ | 危険物の規制に関する政令 | 危険物政令 |
232
+ | 水道法 | — |
233
+ | 下水道法 | — |
234
+ | 廃棄物の処理及び清掃に関する法律 | 廃棄物処理法, 廃掃法 |
235
+ | 土壌汚染対策法 | — |
236
+ | 労働安全衛生法 | 安衛法, 労安法 |
237
+ | 建設工事に係る資材の再資源化等に関する法律 | 建設リサイクル法 |
238
+ | 大気汚染防止法 | — |
239
+ | 水質汚濁防止法 | — |
240
+ | 騒音規制法 | — |
241
+ | 振動規制法 | — |
242
+ | 悪臭防止法 | — |
243
+ | 高齢者、障害者等の移動等の円滑化の促進に関する法律 | バリアフリー法 |
244
+ | 高齢者、障害者等の移動等の円滑化の促進に関する法律施行令 | バリアフリー法施行令 |
245
+
246
+ </details>
247
+
248
+ ### 第10章 省エネ法・住宅関連法(8 法令)
249
+
250
+ | 法令名 | 略称 |
251
+ | ------------------------------------------------------------------ | ---------------------- |
252
+ | 建築物のエネルギー消費性能の向上等に関する法律 | 建築物省エネ法 |
253
+ | 建築物のエネルギー消費性能の向上等に関する法律施行令 | 建築物省エネ法施行令 |
254
+ | エネルギーの使用の合理化及び非化石エネルギーへの転換等に関する法律 | 省エネ法 |
255
+ | 住宅の品質確保の促進等に関する法律 | 品確法, 住宅品質確保法 |
256
+ | 長期優良住宅の普及の促進に関する法律 | 長期優良住宅法 |
257
+ | マンションの管理の適正化の推進に関する法律 | マンション管理適正化法 |
258
+ | マンションの建替え等の円滑化に関する法律 | マンション建替え法 |
259
+ | 建物の区分所有等に関する法律 | 区分所有法 |
260
+
261
+ ### 第11章 既存建築物関連(1 法令)
262
+
263
+ | 法令名 | 略称 |
264
+ | ---------------------------------- | -------------- |
265
+ | 建築物の耐震改修の促進に関する法律 | 耐震改修促進法 |
266
+
267
+ ## 対応告示(7 件)
268
+
269
+ e-Gov API は告示を収録していないため、`get_kokuji` は e-Gov API をキーワード検索するフォールバック動作となります。
270
+
271
+ | 告示名 |
272
+ | ------------------------------------------ |
273
+ | 耐火構造の構造方法を定める件 |
274
+ | 準耐火構造の構造方法を定める件 |
275
+ | 防火構造の構造方法を定める件 |
276
+ | 不燃材料を定める件 |
277
+ | 採光に有効な部分の面積の算定方法を定める件 |
278
+ | 避難安全検証法に関する算出方法等を定める件 |
279
+ | 許容応力度計算等の方法を定める件 |
280
+
281
+ ## 技術仕様
282
+
283
+ | 項目 | 値 |
284
+ | ------------------------ | -------------------------------- |
285
+ | e-Gov API ベース URL | `https://laws.e-gov.go.jp/api/2` |
286
+ | 検索キャッシュ TTL | 30 分 |
287
+ | 法令データキャッシュ TTL | 24 時間 |
288
+ | リクエストタイムアウト | 30 秒 |
289
+ | Node.js | >= 18.0.0 |
290
+
291
+ ## データソース
292
+
293
+ - 法令: [e-Gov 法令検索](https://laws.e-gov.go.jp/)(デジタル庁)
294
+
295
+ ## 謝辞
296
+
297
+ 本プロジェクトは [tax-law-mcp](https://github.com/kentaroajisaka/tax-law-mcp)(MIT License, Copyright (c) 2026 Kentaro Ajisaka)のアーキテクチャおよびコードを参考に開発しました。
298
+
299
+ ## ライセンス
300
+
301
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { createServer } from "./server.js";
4
+ const server = createServer();
5
+ async function main() {
6
+ const transport = new StdioServerTransport();
7
+ await server.connect(transport);
8
+ console.error("building-law-mcp Server running on stdio");
9
+ }
10
+ main().catch((error) => {
11
+ console.error("Fatal error:", error);
12
+ process.exit(1);
13
+ });
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;AAE9B,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,11 @@
1
+ export declare class TTLCache<T> {
2
+ private readonly store;
3
+ private readonly default_ttl_ms;
4
+ constructor(default_ttl_ms?: number);
5
+ get(key: string): T | undefined;
6
+ set(key: string, value: T, ttl_ms?: number): void;
7
+ has(key: string): boolean;
8
+ delete(key: string): boolean;
9
+ clear(): void;
10
+ get size(): number;
11
+ }
@@ -0,0 +1,44 @@
1
+ export class TTLCache {
2
+ store = new Map();
3
+ default_ttl_ms;
4
+ constructor(default_ttl_ms = 30 * 60 * 1000) {
5
+ this.default_ttl_ms = default_ttl_ms;
6
+ }
7
+ get(key) {
8
+ const entry = this.store.get(key);
9
+ if (!entry) {
10
+ return undefined;
11
+ }
12
+ if (Date.now() > entry.expires_at) {
13
+ this.store.delete(key);
14
+ return undefined;
15
+ }
16
+ return entry.value;
17
+ }
18
+ set(key, value, ttl_ms) {
19
+ const ttl = ttl_ms ?? this.default_ttl_ms;
20
+ this.store.set(key, {
21
+ value,
22
+ expires_at: Date.now() + ttl,
23
+ });
24
+ }
25
+ has(key) {
26
+ return this.get(key) !== undefined;
27
+ }
28
+ delete(key) {
29
+ return this.store.delete(key);
30
+ }
31
+ clear() {
32
+ this.store.clear();
33
+ }
34
+ get size() {
35
+ // Clean expired entries first
36
+ for (const [key, entry] of this.store) {
37
+ if (Date.now() > entry.expires_at) {
38
+ this.store.delete(key);
39
+ }
40
+ }
41
+ return this.store.size;
42
+ }
43
+ }
44
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/lib/cache.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,QAAQ;IACF,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IACzC,cAAc,CAAS;IAExC,YAAY,iBAAyB,EAAE,GAAG,EAAE,GAAG,IAAI;QACjD,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;IACvC,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;YAClC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,KAAK,CAAC,KAAK,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,KAAQ,EAAE,MAAe;QACxC,MAAM,GAAG,GAAG,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC;QAC1C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YAClB,KAAK;YACL,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC;IACrC,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,8BAA8B;QAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtC,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC;gBAClC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import type { EgovLawSearchResponse, EgovLawDataResponse } from "./types.js";
2
+ /**
3
+ * Search laws by title keyword.
4
+ * Uses GET /api/2/laws?law_title={keyword}
5
+ */
6
+ export declare function searchLaws(lawTitle: string): Promise<EgovLawSearchResponse>;
7
+ /**
8
+ * Get full law data by lawId.
9
+ * Uses GET /api/2/law_data/{lawId}
10
+ */
11
+ export declare function getLawData(lawId: string): Promise<EgovLawDataResponse>;
@@ -0,0 +1,67 @@
1
+ import { TTLCache } from "./cache.js";
2
+ import { EgovApiError } from "./errors.js";
3
+ const BASE_URL = "https://laws.e-gov.go.jp/api/2";
4
+ const SEARCH_CACHE_TTL = 30 * 60 * 1000; // 30 minutes
5
+ const LAW_DATA_CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours
6
+ const REQUEST_TIMEOUT = 30_000; // 30 seconds
7
+ const searchCache = new TTLCache(SEARCH_CACHE_TTL);
8
+ const lawDataCache = new TTLCache(LAW_DATA_CACHE_TTL);
9
+ async function fetchJson(url) {
10
+ const controller = new AbortController();
11
+ const timeout = setTimeout(() => controller.abort(), REQUEST_TIMEOUT);
12
+ try {
13
+ const response = await fetch(url, {
14
+ signal: controller.signal,
15
+ headers: {
16
+ Accept: "application/json",
17
+ },
18
+ });
19
+ if (!response.ok) {
20
+ throw new EgovApiError(`e-Gov API returned ${response.status}: ${response.statusText}`, response.status, url);
21
+ }
22
+ return (await response.json());
23
+ }
24
+ catch (error) {
25
+ if (error instanceof EgovApiError) {
26
+ throw error;
27
+ }
28
+ if (error instanceof Error && error.name === "AbortError") {
29
+ throw new EgovApiError("e-Gov API request timed out", undefined, url);
30
+ }
31
+ throw new EgovApiError(`e-Gov API request failed: ${error instanceof Error ? error.message : String(error)}`, undefined, url);
32
+ }
33
+ finally {
34
+ clearTimeout(timeout);
35
+ }
36
+ }
37
+ /**
38
+ * Search laws by title keyword.
39
+ * Uses GET /api/2/laws?law_title={keyword}
40
+ */
41
+ export async function searchLaws(lawTitle) {
42
+ const cacheKey = `search:${lawTitle}`;
43
+ const cached = searchCache.get(cacheKey);
44
+ if (cached) {
45
+ return cached;
46
+ }
47
+ const url = `${BASE_URL}/laws?law_title=${encodeURIComponent(lawTitle)}`;
48
+ const result = await fetchJson(url);
49
+ searchCache.set(cacheKey, result);
50
+ return result;
51
+ }
52
+ /**
53
+ * Get full law data by lawId.
54
+ * Uses GET /api/2/law_data/{lawId}
55
+ */
56
+ export async function getLawData(lawId) {
57
+ const cacheKey = `law:${lawId}`;
58
+ const cached = lawDataCache.get(cacheKey);
59
+ if (cached) {
60
+ return cached;
61
+ }
62
+ const url = `${BASE_URL}/law_data/${encodeURIComponent(lawId)}`;
63
+ const result = await fetchJson(url);
64
+ lawDataCache.set(cacheKey, result);
65
+ return result;
66
+ }
67
+ //# sourceMappingURL=egov-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"egov-client.js","sourceRoot":"","sources":["../../src/lib/egov-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { LawNode, ParsedArticle } from "./types.js";
2
+ /**
3
+ * Extract a specific article from the law tree.
4
+ *
5
+ * `articleNumber` can be in any of these formats:
6
+ * "20", "第20条", "20条", "6条の2", "第6条の2", "第百条"
7
+ *
8
+ * Returns null if the article is not found.
9
+ */
10
+ export declare function parseArticle(root: LawNode, articleNumber: string): ParsedArticle | null;
11
+ /**
12
+ * Extract ALL articles from the law tree.
13
+ */
14
+ export declare function parseAllArticles(root: LawNode): ParsedArticle[];
15
+ /**
16
+ * Convert entire law tree to formatted plain text.
17
+ * Used by the `get_full_law` tool.
18
+ *
19
+ * Output format:
20
+ * ```
21
+ * {LawTitle}
22
+ * {LawNum}
23
+ *
24
+ * {ChapterTitle}
25
+ *
26
+ * {ArticleCaption}
27
+ * {ArticleTitle}
28
+ * {paragraph text}
29
+ * ...
30
+ *
31
+ * 附則
32
+ * {supplement text}
33
+ * ```
34
+ */
35
+ export declare function parseFullLaw(root: LawNode): string;