building-standards-act-mcp 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -15,7 +15,7 @@ AI の建築法規回答に含まれるハルシネーションを、条文原
15
15
  - **法令検索** — キーワードで法令を横断検索
16
16
  - **法令全文取得** — 法令全体のテキストを取得
17
17
  - **告示取得** — 建築基準法が技術基準を委任している告示を国土交通省の告示データベース(PDF)から取得
18
- - **主要法令プリセット** — 建築基準法・消防法・都市計画法ほか 115 法令の law_id をプリセット(全 11 章カバー)
18
+ - **主要法令プリセット** — 建築基準法・消防法・都市計画法ほか 115 法令の law_id をプリセット登録済み
19
19
  - **プリセット検証** — `validate_presets` ツールでプリセットの有効性をランタイム検証
20
20
  - **略称対応** — 「建基法」「都計法」「消防法」等の略称で指定可能
21
21
  - **キャッシュ** — 検索 30 分・法令データ 24 時間の TTL キャッシュ
@@ -73,14 +73,18 @@ npm run build
73
73
 
74
74
  ## MCP ツール
75
75
 
76
- | ツール | 説明 |
77
- | ------------------- | ------------------------------------------------------------------------------- |
78
- | `get_law` | 条番号を指定して法令の条文を取得する。略称・正式名称のいずれでも指定可能 |
79
- | `get_full_law` | 法令の全文を取得する。条番号を指定せず法令全体のテキストを返す |
80
- | `search_law` | キーワードで建築関連法令を横断検索する。プリセット法令と e-Gov API の両方を検索 |
81
- | `get_kokuji` | 建築基準法が技術基準を委任している告示の全文を取得する |
82
- | `validate_presets` | プリセット法令の law_id が e-Gov API で有効かを一括検証する |
83
- | `check_law_updates` | 法令の改正状況を e-Gov API で確認する(単体/バッチ/改正履歴表示に対応) |
76
+ | ツール | 説明 |
77
+ | ------------------- | -------------------------------------------------------------------------------- |
78
+ | `get_law` | 条番号を指定して法令の条文を取得する。略称・正式名称のいずれでも指定可能 |
79
+ | `get_full_law` | 法令の全文を取得する。条番号を指定せず法令全体のテキストを返す |
80
+ | `search_law` | キーワードで建築関連法令を横断検索する。プリセット法令と e-Gov API の両方を検索 |
81
+ | `get_kokuji` | 建築基準法が技術基準を委任している告示の全文を取得する |
82
+ | `validate_presets` | プリセット法令の law_id が e-Gov API で有効かを一括検証する |
83
+ | `check_law_updates` | 法令の改正状況を e-Gov API で確認する(単体/バッチ/改正履歴表示に対応) |
84
+ | `get_laws_batch` | 複数の法令・条文を一括取得する(最大20件、同一法令は1回のAPI呼び出しで効率処理) |
85
+ | `verify_citation` | AIの回答に含まれる法令引用を検証する(条文存在確認・テキスト照合、最大10件) |
86
+ | `suggest_related` | 指定した条文の関連法令・委任先・同法令内参照を自動抽出して提案する |
87
+ | `analyze_article` | 条文の構造解析メタデータ(項数・号数・参照統計・プレビュー)をJSON形式で返す |
84
88
 
85
89
  ### パラメータ
86
90
 
@@ -124,6 +128,32 @@ npm run build
124
128
  | `group` | 章グループ(バッチチェック、省略時は全章) | `1章` |
125
129
  | `show_history` | 改正履歴の詳細を表示(`law_name` 指定時) | `true` |
126
130
 
131
+ #### `get_laws_batch`
132
+
133
+ | パラメータ | 説明 | 例 |
134
+ | ---------- | ---------------------------------------------------------------------- | --- |
135
+ | `requests` | 取得対象の配列。各要素に `law_name`, `article_number`, `format` を指定 | — |
136
+
137
+ #### `verify_citation`
138
+
139
+ | パラメータ | 説明 | 例 |
140
+ | ----------- | ------------------------------------------------------------------------------- | --- |
141
+ | `citations` | 検証対象の配列。各要素に `law_name`, `article_number`, `claimed_text`(省略可) | — |
142
+
143
+ #### `suggest_related`
144
+
145
+ | パラメータ | 説明 | 例 |
146
+ | ---------------- | ---------------------------- | ------------ |
147
+ | `law_name` | 法令名(正式名称または略称) | `建築基準法` |
148
+ | `article_number` | 条文番号 | `第20条` |
149
+
150
+ #### `analyze_article`
151
+
152
+ | パラメータ | 説明 | 例 |
153
+ | ---------------- | ---------------------------- | ------------ |
154
+ | `law_name` | 法令名(正式名称または略称) | `建築基準法` |
155
+ | `article_number` | 条文番号 | `第20条` |
156
+
127
157
  ## 使用例
128
158
 
129
159
  ### 条文取得
@@ -172,7 +202,7 @@ npm run build
172
202
 
173
203
  ## 対応法令一覧(115 法令)
174
204
 
175
- ### 第1章 総則(4 法令)
205
+ ### 総則(4 法令)
176
206
 
177
207
  | 法令名 | 略称 |
178
208
  | ------------------ | -------------------- |
@@ -181,7 +211,7 @@ npm run build
181
211
  | 建築基準法施行規則 | 建基規則 |
182
212
  | 民法 | — |
183
213
 
184
- ### 第2章 手続関連規定(6 法令)
214
+ ### 手続関連規定(6 法令)
185
215
 
186
216
  | 法令名 | 略称 |
187
217
  | ---------------- | ------------ |
@@ -192,7 +222,7 @@ npm run build
192
222
  | 建設業法施行令 | — |
193
223
  | 建設業法施行規則 | — |
194
224
 
195
- ### 第3章 集団規定・街づくり規定(13 法令)
225
+ ### 集団規定・街づくり(13 法令)
196
226
 
197
227
  | 法令名 | 略称 |
198
228
  | -------------------------------------------------- | ---------------------- |
@@ -210,7 +240,7 @@ npm run build
210
240
  | 国土利用計画法 | 国土利用計画法, 国土法 |
211
241
  | 都市計画法施行規則 | 都計規則 |
212
242
 
213
- ### 第4章 防火規定・耐火規定(4 法令)
243
+ ### 防火・耐火規定(4 法令)
214
244
 
215
245
  | 法令名 | 略称 |
216
246
  | ------------------------ | ---------- |
@@ -219,7 +249,7 @@ npm run build
219
249
  | 消防法施行規則 | 消防規則 |
220
250
  | 危険物の規制に関する規則 | 危険物規則 |
221
251
 
222
- ### 第5章 構造規定(7 法令)
252
+ ### 構造規定(7 法令)
223
253
 
224
254
  | 法令名 | 略称 |
225
255
  | ------------------------------------------ | ---------------------- |
@@ -231,7 +261,7 @@ npm run build
231
261
  | 建築物の耐震改修の促進に関する法律施行令 | 耐震改修促進法施行令 |
232
262
  | 建築物の耐震改修の促進に関する法律施行規則 | 耐震改修促進法施行規則 |
233
263
 
234
- ### 第6章 建築材料(3 法令)
264
+ ### 建築材料(3 法令)
235
265
 
236
266
  | 法令名 | 略称 |
237
267
  | ---------------- | ---------------------- |
@@ -239,7 +269,7 @@ npm run build
239
269
  | 製造物責任法 | PL法, 製造物責任法 |
240
270
  | 石綿障害予防規則 | 石綿則, アスベスト規則 |
241
271
 
242
- ### 第7章 設備関連規定(5 法令)
272
+ ### 設備関連規定(5 法令)
243
273
 
244
274
  | 法令名 | 略称 |
245
275
  | -------------------------- | ---------------- |
@@ -249,7 +279,7 @@ npm run build
249
279
  | 浄化槽法施行令 | — |
250
280
  | 環境省関係浄化槽法施行規則 | 浄化槽法施行規則 |
251
281
 
252
- ### 第8章 その他(5 法令)
282
+ ### その他(5 法令)
253
283
 
254
284
  | 法令名 | 略称 |
255
285
  | ---------------------------------------------- | ------------------ |
@@ -259,7 +289,7 @@ npm run build
259
289
  | 不動産の鑑定評価に関する法律 | 不動産鑑定法 |
260
290
  | 住宅宿泊事業法 | 民泊新法 |
261
291
 
262
- ### 第9章 建築基準関係規定・建築関連法令(52 法令)
292
+ ### 建築基準関係規定・建築関連法令(52 法令)
263
293
 
264
294
  <details>
265
295
  <summary>法令一覧を表示</summary>
@@ -321,7 +351,7 @@ npm run build
321
351
 
322
352
  </details>
323
353
 
324
- ### 第10章 省エネ法・住宅関連法(13 法令)
354
+ ### 省エネ・住宅関連法(13 法令)
325
355
 
326
356
  | 法令名 | 略称 |
327
357
  | ------------------------------------------------------------------ | ---------------------- |
@@ -339,7 +369,7 @@ npm run build
339
369
  | 長期優良住宅の普及の促進に関する法律施行規則 | 長期優良住宅法施行規則 |
340
370
  | 建築物のエネルギー消費性能の向上等に関する法律施行規則 | 建築物省エネ法施行規則 |
341
371
 
342
- ### 第11章 既存建築物関連(3 法令)
372
+ ### 既存建築物関連(3 法令)
343
373
 
344
374
  | 法令名 | 略称 |
345
375
  | ------------------------------------------ | ---------------- |
@@ -0,0 +1,5 @@
1
+ import type { ArticleAnalysis } from "./types.js";
2
+ /**
3
+ * Analyze a single article and return structured metadata.
4
+ */
5
+ export declare function analyzeArticle(lawName: string, articleNumber: string): Promise<ArticleAnalysis>;
@@ -0,0 +1,106 @@
1
+ import { getLawData } from "./egov-client.js";
2
+ import { parseArticleStructured } from "./egov-parser.js";
3
+ import { LawRegistry } from "./law-registry.js";
4
+ const registry = new LawRegistry();
5
+ const PREVIEW_LENGTH = 100;
6
+ /**
7
+ * Remove parentheses from caption text.
8
+ * "(構造耐力)" → "構造耐力"
9
+ */
10
+ function stripParentheses(caption) {
11
+ return caption.replace(/^[((]/, "").replace(/[))]$/, "");
12
+ }
13
+ /**
14
+ * Count total characters in a structured article.
15
+ */
16
+ function countCharacters(article) {
17
+ let count = 0;
18
+ for (const para of article.paragraphs) {
19
+ count += para.paragraph_sentence.length;
20
+ for (const item of para.items) {
21
+ count += item.item_sentence.length;
22
+ for (const sub of item.subitems) {
23
+ count += countSubitemChars(sub);
24
+ }
25
+ }
26
+ }
27
+ return count;
28
+ }
29
+ function countSubitemChars(sub) {
30
+ let count = sub.subitem_sentence.length;
31
+ for (const child of sub.subitems) {
32
+ count += countSubitemChars(child);
33
+ }
34
+ return count;
35
+ }
36
+ /**
37
+ * Count total subitems recursively.
38
+ */
39
+ function countSubitems(article) {
40
+ let count = 0;
41
+ for (const para of article.paragraphs) {
42
+ for (const item of para.items) {
43
+ count += countSubitemsRecursive(item.subitems);
44
+ }
45
+ }
46
+ return count;
47
+ }
48
+ function countSubitemsRecursive(subs) {
49
+ let count = subs.length;
50
+ for (const sub of subs) {
51
+ count += countSubitemsRecursive(sub.subitems);
52
+ }
53
+ return count;
54
+ }
55
+ /**
56
+ * Analyze a single article and return structured metadata.
57
+ */
58
+ export async function analyzeArticle(lawName, articleNumber) {
59
+ const preset = registry.findByName(lawName);
60
+ if (!preset) {
61
+ throw new Error(`法令「${lawName}」がプリセットに見つかりませんでした。`);
62
+ }
63
+ const lawData = await getLawData(preset.law_id);
64
+ const article = parseArticleStructured(lawData.law_full_text, articleNumber);
65
+ if (!article) {
66
+ throw new Error(`${preset.title}に第${articleNumber}条が見つかりませんでした。`);
67
+ }
68
+ const itemCount = article.paragraphs.reduce((sum, p) => sum + p.items.length, 0);
69
+ const refs = article.references ?? [];
70
+ const crossLawRefs = refs.filter((r) => r.ref_type === "cross_law");
71
+ const referencedLaws = [
72
+ ...new Set(crossLawRefs
73
+ .map((r) => r.target_law)
74
+ .filter((l) => l !== undefined)),
75
+ ];
76
+ return {
77
+ law_name: preset.title,
78
+ law_num: preset.law_num,
79
+ article_num: article.article_num,
80
+ article_title: article.article_title,
81
+ caption: stripParentheses(article.article_caption),
82
+ structure: {
83
+ paragraph_count: article.paragraphs.length,
84
+ item_count: itemCount,
85
+ subitem_count: countSubitems(article),
86
+ total_characters: countCharacters(article),
87
+ },
88
+ paragraph_summaries: article.paragraphs.map((p) => ({
89
+ paragraph_num: p.paragraph_num,
90
+ preview: p.paragraph_sentence.length > PREVIEW_LENGTH
91
+ ? p.paragraph_sentence.slice(0, PREVIEW_LENGTH) + "…"
92
+ : p.paragraph_sentence,
93
+ item_count: p.items.length,
94
+ })),
95
+ reference_summary: {
96
+ total: refs.length,
97
+ cross_law: crossLawRefs.length,
98
+ same_law: refs.filter((r) => r.ref_type === "same_law").length,
99
+ relative: refs.filter((r) => r.ref_type === "relative").length,
100
+ delegation: refs.filter((r) => r.ref_type === "delegation").length,
101
+ referenced_laws: referencedLaws,
102
+ },
103
+ structured_data: article,
104
+ };
105
+ }
106
+ //# sourceMappingURL=article-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"article-analyzer.js","sourceRoot":"","sources":["../../src/lib/article-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CitationVerification } from "./types.js";
2
+ /**
3
+ * Normalize text for comparison: collapse whitespace, remove formatting artifacts.
4
+ */
5
+ export declare function normalizeText(text: string): string;
6
+ /**
7
+ * Calculate match score between claimed text and actual text.
8
+ * Returns a value between 0.0 and 1.0.
9
+ */
10
+ export declare function calculateMatchScore(claimed: string, actual: string): number;
11
+ /**
12
+ * Verify a single citation against the actual law text.
13
+ */
14
+ export declare function verifyCitation(lawName: string, articleNumber: string, claimedText?: string): Promise<CitationVerification>;
@@ -0,0 +1,139 @@
1
+ import { getLawData } from "./egov-client.js";
2
+ import { parseArticle } from "./egov-parser.js";
3
+ import { LawRegistry } from "./law-registry.js";
4
+ const registry = new LawRegistry();
5
+ const MAX_PREVIEW_LENGTH = 200;
6
+ /**
7
+ * Normalize text for comparison: collapse whitespace, remove formatting artifacts.
8
+ */
9
+ export function normalizeText(text) {
10
+ return text
11
+ .replace(/\s+/g, "")
12
+ .replace(/[、。,.・]/g, "")
13
+ .replace(/[()()「」『』【】]/g, "");
14
+ }
15
+ /**
16
+ * Calculate match score between claimed text and actual text.
17
+ * Returns a value between 0.0 and 1.0.
18
+ */
19
+ export function calculateMatchScore(claimed, actual) {
20
+ const normClaimed = normalizeText(claimed);
21
+ const normActual = normalizeText(actual);
22
+ if (normClaimed.length === 0 || normActual.length === 0) {
23
+ return 0;
24
+ }
25
+ // Check if claimed text is contained in actual text
26
+ if (normActual.includes(normClaimed)) {
27
+ return 1.0;
28
+ }
29
+ // Check if actual text is contained in claimed text
30
+ if (normClaimed.includes(normActual)) {
31
+ return 1.0;
32
+ }
33
+ // Calculate longest common substring ratio
34
+ const lcsLength = longestCommonSubstringLength(normClaimed, normActual);
35
+ const maxLen = Math.max(normClaimed.length, normActual.length);
36
+ return lcsLength / maxLen;
37
+ }
38
+ /**
39
+ * Find the length of the longest common substring.
40
+ * Uses a space-optimized DP approach.
41
+ */
42
+ function longestCommonSubstringLength(a, b) {
43
+ // Limit input size to avoid excessive memory usage
44
+ const maxLen = 500;
45
+ const sa = a.length > maxLen ? a.slice(0, maxLen) : a;
46
+ const sb = b.length > maxLen ? b.slice(0, maxLen) : b;
47
+ let maxFound = 0;
48
+ const prev = new Uint16Array(sb.length + 1);
49
+ const curr = new Uint16Array(sb.length + 1);
50
+ for (let i = 1; i <= sa.length; i++) {
51
+ for (let j = 1; j <= sb.length; j++) {
52
+ if (sa[i - 1] === sb[j - 1]) {
53
+ curr[j] = prev[j - 1] + 1;
54
+ if (curr[j] > maxFound) {
55
+ maxFound = curr[j];
56
+ }
57
+ }
58
+ else {
59
+ curr[j] = 0;
60
+ }
61
+ }
62
+ prev.set(curr);
63
+ curr.fill(0);
64
+ }
65
+ return maxFound;
66
+ }
67
+ /**
68
+ * Truncate text for preview, adding ellipsis if needed.
69
+ */
70
+ function truncate(text, maxLen) {
71
+ if (text.length <= maxLen)
72
+ return text;
73
+ return text.slice(0, maxLen) + "…";
74
+ }
75
+ /**
76
+ * Verify a single citation against the actual law text.
77
+ */
78
+ export async function verifyCitation(lawName, articleNumber, claimedText) {
79
+ try {
80
+ const preset = registry.findByName(lawName);
81
+ if (!preset) {
82
+ return {
83
+ law_name: lawName,
84
+ article_number: articleNumber,
85
+ status: "law_not_found",
86
+ error_message: `法令「${lawName}」がプリセットに見つかりませんでした。`,
87
+ };
88
+ }
89
+ const lawData = await getLawData(preset.law_id);
90
+ const article = parseArticle(lawData.law_full_text, articleNumber);
91
+ if (!article) {
92
+ return {
93
+ law_name: preset.title,
94
+ article_number: articleNumber,
95
+ status: "article_not_found",
96
+ error_message: `${preset.title}に第${articleNumber}条が見つかりませんでした。`,
97
+ };
98
+ }
99
+ // If no claimed text, just verify existence
100
+ if (!claimedText || claimedText.trim() === "") {
101
+ return {
102
+ law_name: preset.title,
103
+ article_number: articleNumber,
104
+ status: "verified",
105
+ actual_text: truncate(article.text, MAX_PREVIEW_LENGTH),
106
+ };
107
+ }
108
+ // Compare claimed text against actual text
109
+ const score = calculateMatchScore(claimedText, article.text);
110
+ if (score >= 0.8) {
111
+ return {
112
+ law_name: preset.title,
113
+ article_number: articleNumber,
114
+ status: "verified",
115
+ match_score: Math.round(score * 100) / 100,
116
+ actual_text: truncate(article.text, MAX_PREVIEW_LENGTH),
117
+ };
118
+ }
119
+ return {
120
+ law_name: preset.title,
121
+ article_number: articleNumber,
122
+ status: "mismatch",
123
+ match_score: Math.round(score * 100) / 100,
124
+ actual_text: truncate(article.text, MAX_PREVIEW_LENGTH),
125
+ mismatch_detail: score < 0.3
126
+ ? "主張されたテキストと実際の条文に大きな相違があります。"
127
+ : "主張されたテキストと実際の条文に部分的な相違があります。",
128
+ };
129
+ }
130
+ catch (error) {
131
+ return {
132
+ law_name: lawName,
133
+ article_number: articleNumber,
134
+ status: "error",
135
+ error_message: error instanceof Error ? error.message : String(error),
136
+ };
137
+ }
138
+ }
139
+ //# sourceMappingURL=citation-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"citation-verifier.js","sourceRoot":"","sources":["../../src/lib/citation-verifier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { RelatedLawSuggestion } from "./types.js";
2
+ /**
3
+ * Find related laws for a given article by analyzing its cross-references.
4
+ */
5
+ export declare function findRelatedLaws(lawName: string, articleNumber: string): Promise<RelatedLawSuggestion>;
@@ -0,0 +1,103 @@
1
+ import { getLawData } from "./egov-client.js";
2
+ import { parseArticle } from "./egov-parser.js";
3
+ import { LawRegistry } from "./law-registry.js";
4
+ const registry = new LawRegistry();
5
+ /**
6
+ * Infer delegation target type from raw reference text.
7
+ */
8
+ function inferDelegationType(rawText) {
9
+ if (rawText.includes("政令"))
10
+ return "政令";
11
+ if (rawText.includes("省令"))
12
+ return "省令";
13
+ if (rawText.includes("国土交通大臣"))
14
+ return "告示";
15
+ if (rawText.includes("条例"))
16
+ return "条例";
17
+ return "その他";
18
+ }
19
+ /**
20
+ * Find related laws for a given article by analyzing its cross-references.
21
+ */
22
+ export async function findRelatedLaws(lawName, articleNumber) {
23
+ const preset = registry.findByName(lawName);
24
+ if (!preset) {
25
+ throw new Error(`法令「${lawName}」がプリセットに見つかりませんでした。`);
26
+ }
27
+ const lawData = await getLawData(preset.law_id);
28
+ const article = parseArticle(lawData.law_full_text, articleNumber);
29
+ if (!article) {
30
+ throw new Error(`${preset.title}に第${articleNumber}条が見つかりませんでした。`);
31
+ }
32
+ const refs = article.references ?? [];
33
+ // Categorize references
34
+ const directlyReferenced = extractCrossLawRefs(refs);
35
+ const delegatedTo = extractDelegationRefs(refs);
36
+ const sameLawRefs = extractSameLawRefs(refs);
37
+ // Get same-group laws (excluding the source law itself)
38
+ const sameGroupLaws = registry
39
+ .getByGroup(preset.group)
40
+ .filter((p) => p.law_id !== preset.law_id)
41
+ .map((p) => ({ law_name: p.title, law_id: p.law_id }));
42
+ return {
43
+ source_law: preset.title,
44
+ source_article: articleNumber,
45
+ directly_referenced: directlyReferenced,
46
+ delegated_to: delegatedTo,
47
+ same_law_references: sameLawRefs,
48
+ same_group_laws: sameGroupLaws,
49
+ };
50
+ }
51
+ function extractCrossLawRefs(refs) {
52
+ const seen = new Set();
53
+ const results = [];
54
+ for (const ref of refs) {
55
+ if (ref.ref_type !== "cross_law" || !ref.target_law)
56
+ continue;
57
+ const key = `${ref.target_law}:${ref.target_article ?? ""}`;
58
+ if (seen.has(key))
59
+ continue;
60
+ seen.add(key);
61
+ const preset = registry.findByName(ref.target_law);
62
+ results.push({
63
+ law_name: ref.target_law,
64
+ article: ref.target_article,
65
+ raw_text: ref.raw_text,
66
+ preset_available: preset !== null,
67
+ });
68
+ }
69
+ return results;
70
+ }
71
+ function extractDelegationRefs(refs) {
72
+ const seen = new Set();
73
+ const results = [];
74
+ for (const ref of refs) {
75
+ if (ref.ref_type !== "delegation")
76
+ continue;
77
+ if (seen.has(ref.raw_text))
78
+ continue;
79
+ seen.add(ref.raw_text);
80
+ results.push({
81
+ raw_text: ref.raw_text,
82
+ target_type: inferDelegationType(ref.raw_text),
83
+ });
84
+ }
85
+ return results;
86
+ }
87
+ function extractSameLawRefs(refs) {
88
+ const seen = new Set();
89
+ const results = [];
90
+ for (const ref of refs) {
91
+ if (ref.ref_type !== "same_law" || !ref.target_article)
92
+ continue;
93
+ if (seen.has(ref.target_article))
94
+ continue;
95
+ seen.add(ref.target_article);
96
+ results.push({
97
+ article: ref.target_article,
98
+ raw_text: ref.raw_text,
99
+ });
100
+ }
101
+ return results;
102
+ }
103
+ //# sourceMappingURL=related-law-finder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"related-law-finder.js","sourceRoot":"","sources":["../../src/lib/related-law-finder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC;AAEnC;;GAEG;AACH,SAAS,mBAAmB,CAAC,OAAe;IAC1C,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAe,EACf,aAAqB;IAErB,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;IAEnE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,GAAG,MAAM,CAAC,KAAK,KAAK,aAAa,eAAe,CACjD,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;IAEtC,wBAAwB;IACxB,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,IAAI,CAAC,CAAC;IACrD,MAAM,WAAW,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAE7C,wDAAwD;IACxD,MAAM,aAAa,GAAG,QAAQ;SAC3B,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC;SACxB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC;SACzC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAEzD,OAAO;QACL,UAAU,EAAE,MAAM,CAAC,KAAK;QACxB,cAAc,EAAE,aAAa;QAC7B,mBAAmB,EAAE,kBAAkB;QACvC,YAAY,EAAE,WAAW;QACzB,mBAAmB,EAAE,WAAW;QAChC,eAAe,EAAE,aAAa;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,IAAwB;IAExB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAgD,EAAE,CAAC;IAEhE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,CAAC,GAAG,CAAC,UAAU;YAAE,SAAS;QAE9D,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,cAAc,IAAI,EAAE,EAAE,CAAC;QAC5D,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEd,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACnD,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ,EAAE,GAAG,CAAC,UAAU;YACxB,OAAO,EAAE,GAAG,CAAC,cAAc;YAC3B,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,gBAAgB,EAAE,MAAM,KAAK,IAAI;SAClC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAC5B,IAAwB;IAExB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAyC,EAAE,CAAC;IAEzD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY;YAAE,SAAS;QAC5C,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,SAAS;QACrC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAEvB,OAAO,CAAC,IAAI,CAAC;YACX,QAAQ,EAAE,GAAG,CAAC,QAAQ;YACtB,WAAW,EAAE,mBAAmB,CAAC,GAAG,CAAC,QAAQ,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,kBAAkB,CACzB,IAAwB;IAExB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAgD,EAAE,CAAC;IAEhE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,GAAG,CAAC,cAAc;YAAE,SAAS;QAEjE,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC;YAAE,SAAS;QAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAE7B,OAAO,CAAC,IAAI,CAAC;YACX,OAAO,EAAE,GAAG,CAAC,cAAc;YAC3B,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -110,6 +110,78 @@ export interface LawPreset {
110
110
  tier: "Act" | "CabinetOrder" | "MinisterialOrdinance" | "Other";
111
111
  verified_at: string;
112
112
  }
113
+ export interface BatchFetchItem {
114
+ law_name: string;
115
+ article_number: string;
116
+ status: "success" | "law_not_found" | "article_not_found" | "error";
117
+ text?: string;
118
+ structured?: StructuredArticle;
119
+ error_message?: string;
120
+ }
121
+ export interface BatchFetchResult {
122
+ total: number;
123
+ success: number;
124
+ failed: number;
125
+ results: BatchFetchItem[];
126
+ }
127
+ export interface CitationVerification {
128
+ law_name: string;
129
+ article_number: string;
130
+ status: "verified" | "mismatch" | "article_not_found" | "law_not_found" | "error";
131
+ actual_text?: string;
132
+ match_score?: number;
133
+ mismatch_detail?: string;
134
+ error_message?: string;
135
+ }
136
+ export interface RelatedLawSuggestion {
137
+ source_law: string;
138
+ source_article: string;
139
+ directly_referenced: Array<{
140
+ law_name: string;
141
+ article?: string;
142
+ raw_text: string;
143
+ preset_available: boolean;
144
+ }>;
145
+ delegated_to: Array<{
146
+ raw_text: string;
147
+ target_type: string;
148
+ }>;
149
+ same_law_references: Array<{
150
+ article: string;
151
+ raw_text: string;
152
+ }>;
153
+ same_group_laws: Array<{
154
+ law_name: string;
155
+ law_id: string;
156
+ }>;
157
+ }
158
+ export interface ArticleAnalysis {
159
+ law_name: string;
160
+ law_num: string;
161
+ article_num: string;
162
+ article_title: string;
163
+ caption: string;
164
+ structure: {
165
+ paragraph_count: number;
166
+ item_count: number;
167
+ subitem_count: number;
168
+ total_characters: number;
169
+ };
170
+ paragraph_summaries: Array<{
171
+ paragraph_num: string;
172
+ preview: string;
173
+ item_count: number;
174
+ }>;
175
+ reference_summary: {
176
+ total: number;
177
+ cross_law: number;
178
+ same_law: number;
179
+ relative: number;
180
+ delegation: number;
181
+ referenced_laws: string[];
182
+ };
183
+ structured_data: StructuredArticle;
184
+ }
113
185
  export interface KokujiPreset {
114
186
  law_id: string;
115
187
  law_num: string;
package/dist/server.js CHANGED
@@ -5,8 +5,12 @@ import { registerSearchLawTool } from "./tools/search-law.js";
5
5
  import { registerGetKokujiTool } from "./tools/get-kokuji.js";
6
6
  import { registerValidatePresetsTool } from "./tools/validate-presets.js";
7
7
  import { registerCheckLawUpdatesTool } from "./tools/check-law-updates.js";
8
+ import { registerGetLawsBatchTool } from "./tools/get-laws-batch.js";
9
+ import { registerVerifyCitationTool } from "./tools/verify-citation.js";
10
+ import { registerSuggestRelatedTool } from "./tools/suggest-related.js";
11
+ import { registerAnalyzeArticleTool } from "./tools/analyze-article.js";
8
12
  const SERVER_NAME = "building-law-mcp";
9
- const SERVER_VERSION = "0.2.0";
13
+ const SERVER_VERSION = "0.3.0";
10
14
  const INSTRUCTIONS = `あなたは建築確認申請の法規照合アシスタントです。
11
15
 
12
16
  ## 利用可能なツール
@@ -16,6 +20,10 @@ const INSTRUCTIONS = `あなたは建築確認申請の法規照合アシスタ
16
20
  - get_kokuji: 告示の全文を取得(例: 耐火構造の構造方法を定める件)※国土交通省の告示データベース(PDF)から取得
17
21
  - validate_presets: 法令プリセットがe-Gov APIに存在するか検証する(グループ指定で章ごとの検証も可能)
18
22
  - check_law_updates: 法令の改正状況を確認する(法令名指定で単体チェック、グループ指定でバッチチェック、show_historyで改正履歴表示)
23
+ - get_laws_batch: 複数の法令・条文を一括取得する(最大20件、同一法令は1回のAPI呼び出しで効率処理)
24
+ - verify_citation: AIの回答に含まれる法令引用を検証する(条文存在確認・テキスト照合、最大10件)
25
+ - suggest_related: 指定した条文の関連法令・委任先・同法令内参照を自動抽出して提案する
26
+ - analyze_article: 条文の構造解析メタデータ(項数・号数・参照統計・プレビュー)をJSON形式で返す
19
27
 
20
28
  ## 回答ルール
21
29
  1. まず質問に対する仮回答を生成する
@@ -43,6 +51,10 @@ export function createServer() {
43
51
  registerGetKokujiTool(server);
44
52
  registerValidatePresetsTool(server);
45
53
  registerCheckLawUpdatesTool(server);
54
+ registerGetLawsBatchTool(server);
55
+ registerVerifyCitationTool(server);
56
+ registerSuggestRelatedTool(server);
57
+ registerAnalyzeArticleTool(server);
46
58
  return server;
47
59
  }
48
60
  //# sourceMappingURL=server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAE3E,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;8CAsByB,CAAC;AAE/C,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;KACxB,EACD;QACE,YAAY,EAAE,YAAY;KAC3B,CACF,CAAC;IAEF,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAEpC,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAExE,MAAM,WAAW,GAAG,kBAAkB,CAAC;AACvC,MAAM,cAAc,GAAG,OAAO,CAAC;AAE/B,MAAM,YAAY,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;8CA0ByB,CAAC;AAE/C,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,cAAc;KACxB,EACD;QACE,YAAY,EAAE,YAAY;KAC3B,CACF,CAAC;IAEF,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,2BAA2B,CAAC,MAAM,CAAC,CAAC;IACpC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACjC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IACnC,0BAA0B,CAAC,MAAM,CAAC,CAAC;IAEnC,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerAnalyzeArticleTool(server: McpServer): void;
@@ -0,0 +1,31 @@
1
+ import { z } from "zod";
2
+ import { analyzeArticle } from "../lib/article-analyzer.js";
3
+ const schema = {
4
+ law_name: z
5
+ .string()
6
+ .describe("法令名(正式名称または略称。例: 建築基準法、建基法)"),
7
+ article_number: z.string().describe("条文番号(例: 第20条、20)"),
8
+ };
9
+ export function registerAnalyzeArticleTool(server) {
10
+ server.tool("analyze_article", "条文の構造を解析し、項数・号数・参照統計・プレビューなどのメタデータをJSON形式で返す。AIが要約・解説を生成する際の素材データとして活用。", schema, async ({ law_name, article_number }) => {
11
+ try {
12
+ const analysis = await analyzeArticle(law_name, article_number);
13
+ return {
14
+ content: [
15
+ {
16
+ type: "text",
17
+ text: JSON.stringify(analysis, null, 2),
18
+ },
19
+ ],
20
+ };
21
+ }
22
+ catch (error) {
23
+ const message = error instanceof Error ? error.message : String(error);
24
+ return {
25
+ content: [{ type: "text", text: `エラー: ${message}` }],
26
+ isError: true,
27
+ };
28
+ }
29
+ });
30
+ }
31
+ //# sourceMappingURL=analyze-article.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze-article.js","sourceRoot":"","sources":["../../src/tools/analyze-article.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,MAAM,GAAG;IACb,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,CAAC,6BAA6B,CAAC;IAC1C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;CACxD,CAAC;AAEF,MAAM,UAAU,0BAA0B,CAAC,MAAiB;IAC1D,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,yEAAyE,EACzE,MAAM,EACN,KAAK,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,EAAE;QACrC,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;YAEhE,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAe;wBACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;qBACxC;iBACF;aACF,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,QAAQ,OAAO,EAAE,EAAE,CAAC;gBAC7D,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerGetLawsBatchTool(server: McpServer): void;
@@ -0,0 +1,165 @@
1
+ import { z } from "zod";
2
+ import { LawRegistry } from "../lib/law-registry.js";
3
+ import { getLawData } from "../lib/egov-client.js";
4
+ import { parseArticle, parseArticleStructured } from "../lib/egov-parser.js";
5
+ const registry = new LawRegistry();
6
+ const MAX_REQUESTS = 20;
7
+ const schema = {
8
+ requests: z
9
+ .array(z.object({
10
+ law_name: z.string().describe("法令名(正式名称または略称)"),
11
+ article_number: z.string().describe("条文番号(例: 第20条、20)"),
12
+ format: z
13
+ .enum(["text", "structured"])
14
+ .default("text")
15
+ .describe("出力形式"),
16
+ }))
17
+ .describe("取得対象の条文リスト(最大20件)"),
18
+ };
19
+ export function registerGetLawsBatchTool(server) {
20
+ server.tool("get_laws_batch", "複数の法令・条文を一括取得する。同一法令の複数条文はAPI呼び出し1回で効率的に処理。最大20件。", schema, async ({ requests }) => {
21
+ try {
22
+ if (requests.length > MAX_REQUESTS) {
23
+ return {
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: `エラー: リクエスト数が上限(${MAX_REQUESTS}件)を超えています(${requests.length}件)。`,
28
+ },
29
+ ],
30
+ isError: true,
31
+ };
32
+ }
33
+ if (requests.length === 0) {
34
+ return {
35
+ content: [
36
+ {
37
+ type: "text",
38
+ text: "エラー: リクエストが空です。",
39
+ },
40
+ ],
41
+ isError: true,
42
+ };
43
+ }
44
+ // Group requests by law_name to minimize API calls
45
+ const lawDataMap = new Map();
46
+ const presetMap = new Map();
47
+ for (const req of requests) {
48
+ if (lawDataMap.has(req.law_name))
49
+ continue;
50
+ const preset = registry.findByName(req.law_name);
51
+ if (!preset) {
52
+ lawDataMap.set(req.law_name, null);
53
+ presetMap.set(req.law_name, null);
54
+ continue;
55
+ }
56
+ presetMap.set(req.law_name, {
57
+ title: preset.title,
58
+ law_num: preset.law_num,
59
+ });
60
+ try {
61
+ const data = await getLawData(preset.law_id);
62
+ lawDataMap.set(req.law_name, data);
63
+ }
64
+ catch {
65
+ lawDataMap.set(req.law_name, null);
66
+ }
67
+ }
68
+ // Process each request
69
+ const results = [];
70
+ for (const req of requests) {
71
+ const preset = presetMap.get(req.law_name);
72
+ if (!preset) {
73
+ results.push({
74
+ law_name: req.law_name,
75
+ article_number: req.article_number,
76
+ status: "law_not_found",
77
+ error_message: `法令「${req.law_name}」がプリセットに見つかりませんでした。`,
78
+ });
79
+ continue;
80
+ }
81
+ const lawData = lawDataMap.get(req.law_name);
82
+ if (!lawData) {
83
+ results.push({
84
+ law_name: req.law_name,
85
+ article_number: req.article_number,
86
+ status: "error",
87
+ error_message: `法令「${req.law_name}」のデータ取得に失敗しました。`,
88
+ });
89
+ continue;
90
+ }
91
+ try {
92
+ if (req.format === "structured") {
93
+ const structured = parseArticleStructured(lawData.law_full_text, req.article_number);
94
+ if (!structured) {
95
+ results.push({
96
+ law_name: preset.title,
97
+ article_number: req.article_number,
98
+ status: "article_not_found",
99
+ error_message: `${preset.title}に第${req.article_number}条が見つかりませんでした。`,
100
+ });
101
+ }
102
+ else {
103
+ results.push({
104
+ law_name: preset.title,
105
+ article_number: req.article_number,
106
+ status: "success",
107
+ structured,
108
+ });
109
+ }
110
+ }
111
+ else {
112
+ const article = parseArticle(lawData.law_full_text, req.article_number);
113
+ if (!article) {
114
+ results.push({
115
+ law_name: preset.title,
116
+ article_number: req.article_number,
117
+ status: "article_not_found",
118
+ error_message: `${preset.title}に第${req.article_number}条が見つかりませんでした。`,
119
+ });
120
+ }
121
+ else {
122
+ results.push({
123
+ law_name: preset.title,
124
+ article_number: req.article_number,
125
+ status: "success",
126
+ text: article.text,
127
+ });
128
+ }
129
+ }
130
+ }
131
+ catch (error) {
132
+ results.push({
133
+ law_name: preset.title,
134
+ article_number: req.article_number,
135
+ status: "error",
136
+ error_message: error instanceof Error ? error.message : String(error),
137
+ });
138
+ }
139
+ }
140
+ const successCount = results.filter((r) => r.status === "success").length;
141
+ const response = {
142
+ total: results.length,
143
+ success: successCount,
144
+ failed: results.length - successCount,
145
+ results,
146
+ };
147
+ return {
148
+ content: [
149
+ {
150
+ type: "text",
151
+ text: JSON.stringify(response, null, 2),
152
+ },
153
+ ],
154
+ };
155
+ }
156
+ catch (error) {
157
+ const message = error instanceof Error ? error.message : String(error);
158
+ return {
159
+ content: [{ type: "text", text: `エラー: ${message}` }],
160
+ isError: true,
161
+ };
162
+ }
163
+ });
164
+ }
165
+ //# sourceMappingURL=get-laws-batch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-laws-batch.js","sourceRoot":"","sources":["../../src/tools/get-laws-batch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerSuggestRelatedTool(server: McpServer): void;
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+ import { findRelatedLaws } from "../lib/related-law-finder.js";
3
+ const schema = {
4
+ law_name: z
5
+ .string()
6
+ .describe("法令名(正式名称または略称。例: 建築基準法、建基法)"),
7
+ article_number: z.string().describe("条文番号(例: 第20条、20)"),
8
+ };
9
+ function formatSuggestion(result) {
10
+ const lines = [];
11
+ lines.push(`## ${result.source_law} 第${result.source_article}条 の関連法令\n`);
12
+ if (result.directly_referenced.length > 0) {
13
+ lines.push("### 直接参照されている法令\n");
14
+ for (const ref of result.directly_referenced) {
15
+ const available = ref.preset_available ? "" : "(プリセット未登録)";
16
+ const article = ref.article ? ` 第${ref.article}条` : "";
17
+ lines.push(`- **${ref.law_name}**${article}${available}`);
18
+ lines.push(` - 原文: ${ref.raw_text}`);
19
+ }
20
+ }
21
+ if (result.delegated_to.length > 0) {
22
+ lines.push("\n### 委任先\n");
23
+ for (const del of result.delegated_to) {
24
+ lines.push(`- [${del.target_type}] ${del.raw_text}`);
25
+ }
26
+ }
27
+ if (result.same_law_references.length > 0) {
28
+ lines.push("\n### 同法令内の参照条文\n");
29
+ for (const ref of result.same_law_references) {
30
+ lines.push(`- 第${ref.article}条 — ${ref.raw_text}`);
31
+ }
32
+ }
33
+ if (result.same_group_laws.length > 0) {
34
+ lines.push("\n### 同カテゴリの法令\n");
35
+ for (const law of result.same_group_laws) {
36
+ lines.push(`- ${law.law_name}`);
37
+ }
38
+ }
39
+ if (result.directly_referenced.length === 0 &&
40
+ result.delegated_to.length === 0 &&
41
+ result.same_law_references.length === 0) {
42
+ lines.push("この条文には他法令への参照が検出されませんでした。");
43
+ }
44
+ return lines.join("\n");
45
+ }
46
+ export function registerSuggestRelatedTool(server) {
47
+ server.tool("suggest_related", "指定した条文が参照している関連法令・委任先・同法令内参照を自動抽出して提案する。", schema, async ({ law_name, article_number }) => {
48
+ try {
49
+ const result = await findRelatedLaws(law_name, article_number);
50
+ const text = formatSuggestion(result);
51
+ return { content: [{ type: "text", text }] };
52
+ }
53
+ catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error);
55
+ return {
56
+ content: [{ type: "text", text: `エラー: ${message}` }],
57
+ isError: true,
58
+ };
59
+ }
60
+ });
61
+ }
62
+ //# sourceMappingURL=suggest-related.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suggest-related.js","sourceRoot":"","sources":["../../src/tools/suggest-related.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ export declare function registerVerifyCitationTool(server: McpServer): void;
@@ -0,0 +1,98 @@
1
+ import { z } from "zod";
2
+ import { verifyCitation } from "../lib/citation-verifier.js";
3
+ const MAX_CITATIONS = 10;
4
+ const schema = {
5
+ citations: z
6
+ .array(z.object({
7
+ law_name: z.string().describe("法令名(正式名称または略称)"),
8
+ article_number: z.string().describe("条文番号(例: 第20条、20)"),
9
+ claimed_text: z
10
+ .string()
11
+ .optional()
12
+ .describe("AIが主張する条文テキスト。省略時は条文の存在確認のみ。"),
13
+ }))
14
+ .describe("検証対象の引用リスト(最大10件)"),
15
+ };
16
+ function formatResults(results) {
17
+ const verified = results.filter((r) => r.status === "verified");
18
+ const mismatched = results.filter((r) => r.status === "mismatch");
19
+ const notFound = results.filter((r) => r.status === "article_not_found" || r.status === "law_not_found");
20
+ const errors = results.filter((r) => r.status === "error");
21
+ const lines = [];
22
+ lines.push("## 引用検証結果\n");
23
+ lines.push(`- 検証対象: ${results.length}件`);
24
+ lines.push(`- 正確: ${verified.length}件`);
25
+ if (mismatched.length > 0)
26
+ lines.push(`- **不一致: ${mismatched.length}件**`);
27
+ if (notFound.length > 0)
28
+ lines.push(`- 未発見: ${notFound.length}件`);
29
+ if (errors.length > 0)
30
+ lines.push(`- エラー: ${errors.length}件`);
31
+ for (const r of results) {
32
+ lines.push("");
33
+ const icon = r.status === "verified"
34
+ ? "OK"
35
+ : r.status === "mismatch"
36
+ ? "NG"
37
+ : r.status === "error"
38
+ ? "ERR"
39
+ : "N/A";
40
+ lines.push(`### [${icon}] ${r.law_name} 第${r.article_number}条`);
41
+ if (r.match_score !== undefined) {
42
+ lines.push(`- 一致度: ${(r.match_score * 100).toFixed(0)}%`);
43
+ }
44
+ if (r.mismatch_detail) {
45
+ lines.push(`- ${r.mismatch_detail}`);
46
+ }
47
+ if (r.error_message) {
48
+ lines.push(`- ${r.error_message}`);
49
+ }
50
+ if (r.actual_text) {
51
+ lines.push(`- 実際の条文: ${r.actual_text}`);
52
+ }
53
+ }
54
+ return lines.join("\n");
55
+ }
56
+ export function registerVerifyCitationTool(server) {
57
+ server.tool("verify_citation", "AIの回答に含まれる法令引用を検証する。条文の存在確認、テキスト照合による正確性チェックが可能。最大10件。", schema, async ({ citations }) => {
58
+ try {
59
+ if (citations.length === 0) {
60
+ return {
61
+ content: [
62
+ {
63
+ type: "text",
64
+ text: "エラー: 検証対象が空です。",
65
+ },
66
+ ],
67
+ isError: true,
68
+ };
69
+ }
70
+ if (citations.length > MAX_CITATIONS) {
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text",
75
+ text: `エラー: 検証対象が上限(${MAX_CITATIONS}件)を超えています(${citations.length}件)。`,
76
+ },
77
+ ],
78
+ isError: true,
79
+ };
80
+ }
81
+ const results = [];
82
+ for (const citation of citations) {
83
+ const result = await verifyCitation(citation.law_name, citation.article_number, citation.claimed_text);
84
+ results.push(result);
85
+ }
86
+ const text = formatResults(results);
87
+ return { content: [{ type: "text", text }] };
88
+ }
89
+ catch (error) {
90
+ const message = error instanceof Error ? error.message : String(error);
91
+ return {
92
+ content: [{ type: "text", text: `エラー: ${message}` }],
93
+ isError: true,
94
+ };
95
+ }
96
+ });
97
+ }
98
+ //# sourceMappingURL=verify-citation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-citation.js","sourceRoot":"","sources":["../../src/tools/verify-citation.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "building-standards-act-mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server for Japanese building regulations — fetches law text from e-Gov API v2 to prevent AI hallucination in building permit reviews",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",