poker-mcp 1.5.0 → 1.8.2

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
@@ -4,13 +4,161 @@ YAML-based input file management tool for radiation-shielding calculation code P
4
4
 
5
5
  ## 📋 クイック情報
6
6
 
7
- - **バージョン**: 1.5.0
7
+ - **バージョン**: 1.6.0
8
8
  - **プロトコル**: MCP (Model Context Protocol) 1.0.0 完全準拠
9
9
  - **メインサーバー**: `src/mcp_server_stdio_v4.js`
10
10
  - **データ保存**: `~/.poker-mcp/`(`POKER_MCP_HOME`環境変数で変更可)
11
11
  - **核種データ**: `${POKER_INSTALL_PATH}/LIB/ICRP-07.NDX` を直接参照
12
12
  - **実行方式**: STDIO通信(MCPプロトコル標準)
13
13
 
14
+ ## 🆕 バージョン1.8.0〜1.8.1の新機能
15
+
16
+ ### 📐 CAD連携が MCP だけで完結
17
+ 従来、CAD からの経路抽出は MCP を経由せず、FreeCAD を手で起動する必要が
18
+ ありました。`spec.json` を手書きし、`poker_cui -p` を叩き、`freecadcmd` に
19
+ スクリプトを渡す。3 手順すべてが手作業でした。
20
+
21
+ ```javascript
22
+ poker_generatePaths({ fcstd: "C:/path/to/model.FCStd" })
23
+ poker_executeCalculation({ yaml_file: "poker.yaml", path_input: "poker.paths" })
24
+ ```
25
+
26
+ CAD ファイルを指定するだけになりました。分割点の取得、グリッド検出器の展開、
27
+ ビルドアップ等価材料の解決(`Source_Dry` → `Tungsten` など)は自動です。
28
+
29
+ ### 🔍 FREECAD_PATH
30
+ FreeCAD の場所を、環境変数 → PATH → 既定のインストール先の順で解決します。
31
+ `POKER_INSTALL_PATH` のように固定の既定値を持てないのは、インストール先が
32
+ バージョン番号を含むためです(FreeCAD 1.1, 1.0 …)。
33
+
34
+ ```json
35
+ "env": {
36
+ "POKER_INSTALL_PATH": "C:\\Poker",
37
+ "FREECAD_PATH": "C:\\Program Files\\FreeCAD 1.1"
38
+ }
39
+ ```
40
+
41
+ ### 🐛 相対パスの解決を修正
42
+ `tasks/` 配下のファイル名指定が、プロセスのカレントディレクトリを基準に
43
+ 解決されていました。MCP サーバの起動場所によっては別の場所を指します。
44
+
45
+
46
+ ## 🆕 バージョン1.7.0〜1.7.2の新機能
47
+
48
+ ### 📉 サマリー出力量の制御(ThinnedIndices 操作系 3メソッド)
49
+ `thinnedindices` ノードを MCP から設定できます。`.paths` の生成では全ての
50
+ 線源分割点と検出器評価点が必要ですが、既定では間引かれるため手で書き足す
51
+ 必要がありました。
52
+
53
+ ```javascript
54
+ poker_updateThinnedIndices({ fit_for_paths: true })
55
+ // → 入力の分割定義と検出器グリッドから必要数を計算して設定
56
+ ```
57
+
58
+ 既定値は poker_mcp 側で持ちません。省略しても `.summary` には全 7 キーが
59
+ 値付きで出力されるので、そちらを正とします。
60
+
61
+ ### 🔄 保留中の変更が `get` で見えるように
62
+ `propose` の直後に `get` を呼ぶと変更が見えず、「反映されていない」と誤解する
63
+ 余地がありました。確定値とは別に `pending` として示します。
64
+
65
+ ```javascript
66
+ poker_proposeThinnedIndices({ sourcepoint: 100 })
67
+ poker_getThinnedIndices()
68
+ // → { thinnedindices: null, pending: { sourcepoint: 100 }, pending_count: 1 }
69
+ ```
70
+
71
+ ### 🛡️ `.paths` の座標照合
72
+ 件数だけでなく座標も YAML と突き合わせます。検出器を動かして `.paths` を
73
+ 再生成し忘れると、件数は変わらないため従来は通り抜け、**静かに誤った線量**が
74
+ 出ていました。
75
+
76
+
77
+ ## 🆕 バージョン1.6.0の新機能
78
+
79
+ ### 🧱 カスタム材料をライブラリ追加だけで使えるように
80
+ 材料の一覧・密度範囲・ビルドアップ可用性をコード側に持たず、すべて
81
+ `%POKER_INSTALL_PATH%/LIB/` から読み込むようにしました。**カスタム材料を
82
+ `lib_material.dat` に追記すれば、コード変更なしにサーバ再起動だけで
83
+ ゾーン定義・密度検証・等価材料の自動選定すべてに反映されます。**
84
+
85
+ 標準材料を追加する場合は `lib_material.dat` と `lib_setting.dat` の
86
+ `buildup_material` の両方に登録します(片方だけなら警告が出ます)。
87
+
88
+ ### 🔀 ビルドアップ等価材料の選定を実データ方式へ
89
+ 従来の光子実効Z最近傍は暫定実装でした。ビルドアップを支配するのは散乱と吸収の
90
+ 競合であることから、POKER の減衰係数ファイルから
91
+ `μ_incoherent / (μ_total − μ_incoherent)` を求め、0.1〜3 MeV の11点で
92
+ 最も一致する標準材料を選びます。
93
+
94
+ 一致度スコアを応答に付けるようにしました。0.30 を超える場合は「標準材料に
95
+ 近いものが無い」ことを意味し、候補上位3件とともに警告を出します。黙って粗い
96
+ 代用材を当てるより、どの程度粗いかを見せる方が判断材料になります。
97
+
98
+ この変更で `Source_Dry` の等価材料は `Lead` から `Tungsten` に変わります。
99
+
100
+ ### 🐛 `poker_updateBuildupFactor` が equivalent を更新できない問題を修正
101
+ ツールスキーマと `DataManager` の双方に `equivalent` が無く、`TaskManager`
102
+ だけが素通しする三層不整合でした。変更・解除(空文字指定)に対応し、
103
+ 標準材料への指定や非標準材料の指定を拒否する検証も追加しています。
104
+
105
+ ### 📡 CAD連携レイトレース
106
+ FreeCAD のソリッドモデルを、STEP のような中間フォーマットを介さず、CSG で
107
+ 表現し直す作業も無しに遮蔽体系として扱えます。**MCP の 2 呼び出しで完結**します。
108
+
109
+ ```javascript
110
+ poker_generatePaths({ fcstd: "C:/path/to/model.FCStd" })
111
+ poker_executeCalculation({ yaml_file: "poker.yaml", path_input: "poker.paths" })
112
+ ```
113
+
114
+ 線源点→検出器の直線を FreeCAD 側で追跡し、通過した材質と厚さを `.paths` に
115
+ 記録して POKER に渡します。分割点の取得、グリッド検出器の展開、ビルドアップ
116
+ 等価材料の解決はすべて自動です。
117
+
118
+ CSG 経由と一致することを平板・円筒・球の 5 体系で確認済みです。フィレットや
119
+ 自由曲面のように CSG で表現できない形状も扱えます。**複数線源・グリッド検出器・
120
+ スラント補正に対応**。
121
+
122
+ 他の CAD で作ったモデルも、STEP で FreeCAD に読み込めば同じパイプラインに
123
+ 乗ります。副産物として、POKER の改造なしで使える**簡易化の監査ツール**
124
+ (ある形状を省略してよいかを定量化する)もあります。
125
+
126
+ FreeCAD の場所は環境変数 `FREECAD_PATH` で指定します(未設定なら既定の
127
+ インストール先を探索)。
128
+
129
+ #### 必要なもの
130
+
131
+ | | 入手 | 環境変数 |
132
+ |---|---|---|
133
+ | poker-mcp | `npm install poker-mcp` | — |
134
+ | **POKER 本体** | 別途入手 | `POKER_INSTALL_PATH` |
135
+ | **FreeCAD** | [freecad.org](https://www.freecad.org/)(無償) | `FREECAD_PATH` |
136
+
137
+ numpy はレイトレーサが使いますが、FreeCAD に同梱されているので追加の
138
+ インストールは不要です。
139
+
140
+ ```json
141
+ "env": {
142
+ "POKER_MCP_HOME": "C:\\Users\\yoshi\\poker_mcp_workspace",
143
+ "POKER_INSTALL_PATH": "C:\\Poker",
144
+ "FREECAD_PATH": "C:\\Program Files\\FreeCAD 1.1"
145
+ }
146
+ ```
147
+
148
+ `FREECAD_PATH` は既定の場所にインストールされていれば省略できます。
149
+
150
+ #### モデル側の約束
151
+
152
+ **ソリッドに `PokerMaterial` プロパティで材質名を設定**しておく必要があります
153
+ (`Iron`、`Concrete` など、POKER の材料ライブラリの名前)。密度を上書きする場合は
154
+ `PokerDensity` も設定します。
155
+
156
+ 他の CAD で作ったモデルを STEP で読み込んだ場合、材質情報は失われるので
157
+ FreeCAD 上で設定してください。一度設定すれば `.FCStd` に保存されます。
158
+
159
+ 詳細は [CAD_RAYTRACE.md](./docs/manuals/CAD_RAYTRACE.md)、フォーマットは
160
+ [PATHS_FORMAT.md](./docs/manuals/PATHS_FORMAT.md)。
161
+
14
162
  ## 🆕 バージョン1.5.0の新機能
15
163
 
16
164
  ### 🖥️ POKER GUI を閉じずに表示を切り替え
@@ -33,8 +181,6 @@ YAML-based input file management tool for radiation-shielding calculation code P
33
181
  乱数で「正常」を出力する監視スクリプトなど、実態と乖離した記述を削除し、
34
182
  検証可能な手順のみに整理しています。
35
183
 
36
- 詳細は [CHANGELOG.md](./CHANGELOG.md) を参照。
37
-
38
184
  ## 🆕 バージョン1.4.0の新機能
39
185
 
40
186
  ### ☢️ 子孫核種の自動管理
@@ -255,7 +401,7 @@ Claude Desktopで以下のようにテストできます:
255
401
  ## 🏆 主要機能
256
402
 
257
403
  ### ✅ **MCP完全対応**
258
- - **30メソッド完全実装**: 全ての放射線遮蔽計算入力管理機能
404
+ - **34メソッド完全実装**: 全ての放射線遮蔽計算入力管理機能
259
405
  - **JSON-RPC 2.0準拠**: 標準プロトコル完全対応
260
406
  - **STDIO通信**: MCPクライアントとの標準通信方式
261
407
  - **自動バックアップ・ロールバック**: 企業品質のデータ保護
@@ -274,7 +420,7 @@ Claude Desktopで以下のようにテストできます:
274
420
 
275
421
  ## 🎯 API構成
276
422
 
277
- ### 🔧 **30メソッド完全実装**
423
+ ### 🔧 **34メソッド完全実装**
278
424
 
279
425
  | **カテゴリ** | **メソッド数** | **機能** | **主要操作** |
280
426
  |-------------|---------------|----------|-------------|
@@ -287,7 +433,7 @@ Claude Desktopで以下のようにテストできます:
287
433
  | **📏 Unit** | 5個 | 単位設定管理 | propose・get・update・validateIntegrity・analyzeConversion |
288
434
  | **⚙️ System** | 6個 | システム制御 | applyChanges・executeCalculation・resetYaml・confirmDaughterNuclides・openGui・各種検証 |
289
435
 
290
- ### 📋 **全30メソッド一覧**
436
+ ### 📋 **全34メソッド一覧**
291
437
  ```
292
438
  Body系 (3): poker_proposeBody, poker_updateBody, poker_deleteBody
293
439
  Zone系 (3): poker_proposeZone, poker_updateZone, poker_deleteZone
package/package.json CHANGED
@@ -1,55 +1,61 @@
1
- {
2
- "name": "poker-mcp",
3
- "version": "1.5.0",
4
- "description": "YAML-based input file management tool for radiation shielding calculation code POKER with MCP support - Enhanced with collision detection, daughter nuclide auto-completion, and environment variable support",
5
- "main": "src/mcp_server_stdio_v4.js",
6
- "type": "module",
7
- "bin": {
8
- "poker-mcp": "src/mcp_server_stdio_v4.js"
9
- },
10
- "scripts": {
11
- "start": "node src/mcp_server_stdio_v4.js",
12
- "dev": "nodemon src/mcp_server_stdio_v4.js",
13
- "prepare": "echo 'NPX ready: npx poker-mcp'",
14
- "check:manifest": "node scripts/check-manifest-sync.mjs"
15
- },
16
- "keywords": [
17
- "mcp",
18
- "model-context-protocol",
19
- "yaml",
20
- "radiation",
21
- "shielding",
22
- "nuclear",
23
- "radioisotope",
24
- "medical",
25
- "accelerator",
26
- "POKER",
27
- "physics",
28
- "validation",
29
- "npx",
30
- "point-kernel",
31
- "collision-detection",
32
- "daughter-nuclide"
33
- ],
34
- "author": "Yoshihiro Hirao <tora@pointkernel.com>",
35
- "license": "ISC",
36
- "repository": {
37
- "type": "git",
38
- "url": "git+https://github.com/Hirao-Y/poker_mcp.git"
39
- },
40
- "homepage": "https://github.com/Hirao-Y/poker_mcp#readme",
41
- "engines": {
42
- "node": ">=18.0.0"
43
- },
44
- "dependencies": {
45
- "@modelcontextprotocol/sdk": "^1.29.0",
46
- "js-yaml": "^4.1.0",
47
- "winston": "^3.17.0",
48
- "zod": "^3.24.2"
49
- },
50
- "files": [
51
- "src/",
52
- "README.md",
53
- ".mcp.json"
54
- ]
55
- }
1
+ {
2
+ "name": "poker-mcp",
3
+ "version": "1.8.2",
4
+ "description": "YAML-based input file management tool for radiation shielding calculation code POKER with MCP support - Enhanced with collision detection, daughter nuclide auto-completion, and environment variable support",
5
+ "main": "src/mcp_server_stdio_v4.js",
6
+ "type": "module",
7
+ "bin": {
8
+ "poker-mcp": "src/mcp_server_stdio_v4.js"
9
+ },
10
+ "scripts": {
11
+ "start": "node src/mcp_server_stdio_v4.js",
12
+ "dev": "nodemon src/mcp_server_stdio_v4.js",
13
+ "prepare": "echo 'NPX ready: npx poker-mcp'",
14
+ "check:manifest": "node scripts/check-manifest-sync.mjs",
15
+ "test:pending": "node tests/pending-view.test.mjs"
16
+ },
17
+ "keywords": [
18
+ "mcp",
19
+ "model-context-protocol",
20
+ "yaml",
21
+ "radiation",
22
+ "shielding",
23
+ "nuclear",
24
+ "radioisotope",
25
+ "medical",
26
+ "accelerator",
27
+ "POKER",
28
+ "physics",
29
+ "validation",
30
+ "npx",
31
+ "point-kernel",
32
+ "collision-detection",
33
+ "daughter-nuclide"
34
+ ],
35
+ "author": "Yoshihiro Hirao <tora@pointkernel.com>",
36
+ "license": "ISC",
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/Hirao-Y/poker_mcp.git"
40
+ },
41
+ "homepage": "https://github.com/Hirao-Y/poker_mcp#readme",
42
+ "engines": {
43
+ "node": ">=18.0.0"
44
+ },
45
+ "dependencies": {
46
+ "@modelcontextprotocol/sdk": "^1.29.0",
47
+ "js-yaml": "^4.1.0",
48
+ "winston": "^3.17.0",
49
+ "zod": "^3.24.2"
50
+ },
51
+ "files": [
52
+ "src/",
53
+ "tools/gen_paths.py",
54
+ "tools/ray_trace_tri.py",
55
+ "tools/poker_lib.py",
56
+ "tools/audit_mfp.py",
57
+ "tools/compare_poker_trace.py",
58
+ "README.md",
59
+ ".mcp.json"
60
+ ]
61
+ }
@@ -0,0 +1,187 @@
1
+ // mcp/handlers/cadHandlers.js
2
+ //
3
+ // CAD 連携レイトレース。従来は次の 3 手順を手で行う必要があった。
4
+ // 1. spec.json を手書き(絶対パスを 4 箇所)
5
+ // 2. poker_cui -p で分割点と評価点を出す
6
+ // 3. freecadcmd を起動して gen_paths.py を走らせる
7
+ // このハンドラがまとめて行う。
8
+
9
+ import { spawn } from 'child_process';
10
+ import fs from 'fs/promises';
11
+ import fssync from 'fs';
12
+ import path from 'path';
13
+ import { FREECAD_CMD, CAD_TOOLS_DIR, POKER_INSTALL_DIR, TASKS_DIR, YAML_FILE }
14
+ from '../../utils/paths.js';
15
+ import { logger } from '../../utils/logger.js';
16
+ import { MaterialCatalog } from '../../utils/MaterialCatalog.js';
17
+
18
+ function run(cmd, args, opts = {}) {
19
+ return new Promise((resolve) => {
20
+ const p = spawn(cmd, args, { ...opts, stdio: ['ignore', 'pipe', 'pipe'] });
21
+ let out = '', err = '';
22
+ p.stdout.on('data', d => out += d);
23
+ p.stderr.on('data', d => err += d);
24
+ p.on('error', e => resolve({ code: -1, out, err: e.message }));
25
+ p.on('close', code => resolve({ code, out, err }));
26
+ });
27
+ }
28
+
29
+ export function createCadHandlers(taskManager) {
30
+ return {
31
+ async generatePaths(args) {
32
+ const fail = (msg, hint) => ({
33
+ content: [{
34
+ type: 'text',
35
+ text: JSON.stringify({ success: false, error: msg, hint }, null, 2)
36
+ }],
37
+ isError: true
38
+ });
39
+
40
+ // --- FreeCAD の所在 ---
41
+ if (!FREECAD_CMD) {
42
+ return fail(
43
+ 'FreeCAD が見つかりません',
44
+ '環境変数 FREECAD_PATH に freecadcmd の場所を設定してください。' +
45
+ '実行ファイル(C:/Program Files/FreeCAD 1.1/bin/freecadcmd.exe)でも、' +
46
+ 'インストールフォルダ(C:/Program Files/FreeCAD 1.1)でも指定できます。' +
47
+ 'claude_desktop_config.json の env に追加します。');
48
+ }
49
+ if (!args || !args.fcstd) return fail('fcstd を指定してください');
50
+ if (!fssync.existsSync(args.fcstd))
51
+ return fail('CAD ファイルが見つかりません: ' + args.fcstd);
52
+
53
+ const yamlFile = YAML_FILE;
54
+ if (!fssync.existsSync(yamlFile))
55
+ return fail('入力 YAML がありません: ' + yamlFile,
56
+ 'applyChanges で入力を確定してから実行してください。');
57
+
58
+ // --- 1. poker_cui -p で分割点と評価点を出す ---
59
+ // .paths には全点が必要。間引かれていると gen_paths.py がエラーにする。
60
+ const exe = path.join(POKER_INSTALL_DIR, 'poker_cui.EXE');
61
+ if (!fssync.existsSync(exe))
62
+ return fail('poker_cui が見つかりません: ' + exe,
63
+ '環境変数 POKER_INSTALL_PATH を確認してください。');
64
+
65
+ const summary = yamlFile + '.summary';
66
+ const r1 = await run(exe, [yamlFile, '-p', '-t'], { cwd: TASKS_DIR });
67
+ if (r1.code !== 0 || !fssync.existsSync(summary)) {
68
+ return fail('poker_cui -p の実行に失敗しました(終了コード ' + r1.code + ')',
69
+ (r1.err || r1.out || '').slice(-400));
70
+ }
71
+
72
+ // --- 2. spec を組み立てる ---
73
+ const out = args.output || path.join(TASKS_DIR, 'poker.paths');
74
+ const spec = {
75
+ fcstd: args.fcstd.replace(/\\/g, '/'),
76
+ out: out.replace(/\\/g, '/'),
77
+ poker_summary: summary.replace(/\\/g, '/'),
78
+ detectors_from_summary: true,
79
+ deviation: args.deviation ?? 0.5,
80
+ unit_scale: args.unit_scale ?? 0.1,
81
+ poker_dir: POKER_INSTALL_DIR.replace(/\\/g, '/'),
82
+ mu_energy: args.mu_energy ?? 1.25,
83
+ };
84
+ if (args.source_name) spec.source_name = args.source_name;
85
+ if (args.buildup_exclude) spec.buildup_exclude = args.buildup_exclude;
86
+ if (args.chunk) spec.chunk = args.chunk;
87
+
88
+ // カスタム材料のビルドアップ等価材料を自動で解決する。
89
+ // gen_paths.py は層の縮約先を決める際、単層ビルドアップデータの有無を
90
+ // 材料名で照合する。Source_Dry のようなカスタム材料は標準材料に
91
+ // 読み替える必要があり、従来は spec.equivalent に手で書いていた。
92
+ // MaterialCatalog が lib_equivalent.dat と実データから解決できるので
93
+ // ここで埋める(POKER 側も同じ表を見るので食い違わない)。
94
+ try {
95
+ const data = taskManager.data || {};
96
+ const equiv = {};
97
+ for (const z of (data.zone || [])) {
98
+ const m = z.material;
99
+ if (!m || m === 'VOID' || equiv[m]) continue;
100
+ if (MaterialCatalog.isStandard && MaterialCatalog.isStandard(m)) continue;
101
+ const e = MaterialCatalog.nearestBuildupEquivalent(m);
102
+ const name = (e && typeof e === 'object') ? e.equivalent : e;
103
+ if (name) equiv[m] = name;
104
+ }
105
+ if (Object.keys(equiv).length) {
106
+ spec.equivalent = equiv;
107
+ logger.info('ビルドアップ等価材料を自動設定しました', { equivalent: equiv });
108
+ }
109
+ } catch (e) {
110
+ logger.warn('等価材料の自動解決に失敗(spec.equivalent なしで続行)',
111
+ { error: e.message });
112
+ }
113
+
114
+ const specFile = path.join(TASKS_DIR, '.generate_paths_spec.json');
115
+ await fs.writeFile(specFile, JSON.stringify(spec, null, 2), 'utf8');
116
+
117
+ // --- 3. FreeCAD をヘッドレスで起動してトレース ---
118
+ // GUI の MCP ブリッジ経由では、数万レイのトレースが GUI スレッドを
119
+ // 占有してブリッジが壊れる。freecadcmd を使う。
120
+ const script =
121
+ 'import sys, json, traceback\n' +
122
+ 'sys.path.insert(0, r"' + CAD_TOOLS_DIR + '")\n' +
123
+ 'try:\n' +
124
+ ' import gen_paths\n' +
125
+ ' gen_paths.main(r"' + specFile + '")\n' +
126
+ ' print("GEN_PATHS_OK")\n' +
127
+ 'except BaseException:\n' +
128
+ ' print("GEN_PATHS_ERROR")\n' +
129
+ ' traceback.print_exc()\n';
130
+
131
+ const scriptFile = path.join(TASKS_DIR, '.generate_paths.py');
132
+ await fs.writeFile(scriptFile, script, 'utf8');
133
+
134
+ const r2 = await run(FREECAD_CMD, [scriptFile], { cwd: TASKS_DIR });
135
+ const log = (r2.out || '') + (r2.err || '');
136
+
137
+ if (!log.includes('GEN_PATHS_OK') || !fssync.existsSync(out)) {
138
+ // Python のトレースバックから要点を抜く
139
+ const m = log.match(/(?:SystemExit|Error|Exception)[^\n]*(?:\n[^\n]*){0,3}/);
140
+ return fail('経路の生成に失敗しました',
141
+ m ? m[0].trim() : log.slice(-500));
142
+ }
143
+
144
+ // --- 4. 生成結果を要約する ---
145
+ const text = await fs.readFile(out, 'utf8');
146
+ const info = {};
147
+ for (const key of ['n_sources', 'n_source_points', 'n_detectors', 'n_materials',
148
+ 'format_version', 'deviation_mm']) {
149
+ const m = text.match(new RegExp('^\\s*' + key + ':\\s*(.+)$', 'm'));
150
+ if (m) info[key] = m[1].trim();
151
+ }
152
+ const nPaths = (text.split('paths: |')[1] || '').trim().split('\n').length;
153
+
154
+ logger.info('経路ファイルを生成しました', { out, ...info });
155
+
156
+ return {
157
+ content: [{
158
+ type: 'text',
159
+ text: JSON.stringify({
160
+ success: true,
161
+ message: '経路ファイルを生成しました',
162
+ output: out,
163
+ summary: {
164
+ 経路数: nPaths,
165
+ 線源数: info.n_sources,
166
+ 線源点数: info.n_source_points,
167
+ 検出器評価点数: info.n_detectors,
168
+ 材質数: info.n_materials,
169
+ テッセレーション偏差_mm: info.deviation_mm,
170
+ format_version: info.format_version
171
+ },
172
+ spec_used: {
173
+ deviation: spec.deviation,
174
+ unit_scale: spec.unit_scale,
175
+ mu_energy: spec.mu_energy,
176
+ buildup_exclude: spec.buildup_exclude ?? ['VOID', 'Air'],
177
+ equivalent: spec.equivalent ?? {},
178
+ freecad: FREECAD_CMD,
179
+ poker_dir: spec.poker_dir
180
+ },
181
+ next: 'poker_cui "' + yamlFile + '" --path-input "' + out + '" -t で計算できます'
182
+ }, null, 2)
183
+ }]
184
+ };
185
+ }
186
+ };
187
+ }
@@ -115,7 +115,8 @@ export function createCalculationHandlers(taskManager) {
115
115
  summaryOptions,
116
116
  resolvedOutputFiles,
117
117
  undefined,
118
- taskManager.dataManager
118
+ taskManager.dataManager,
119
+ args.path_input || null
119
120
  );
120
121
 
121
122
  // 事前検証で重大エラーが検出された場合の処理
@@ -5,7 +5,9 @@ import { createTransformHandlers } from './transformHandlers.js';
5
5
  import { createBuildupFactorHandlers } from './buildupFactorHandlers.js';
6
6
  import { createSourceHandlers } from './sourceHandlers.js';
7
7
  import { createDetectorHandlers } from './detectorHandlers.js';
8
- import { createUnitHandlers } from './unitHandlers.js';
8
+ import { createUnitHandlers } from './unitHandlers.js';
9
+ import { createThinnedIndicesHandlers } from './thinnedIndicesHandlers.js';
10
+ import { createCadHandlers } from './cadHandlers.js';
9
11
  import { createCalculationHandlers } from './calculationHandlers.js';
10
12
  import { resetHandlers } from './resetHandlers.js';
11
13
  import { createDaughterNuclideHandler } from './daughterNuclideHandler.js';
@@ -32,7 +34,9 @@ export function createAllHandlers(taskManager) {
32
34
  ...createDetectorHandlers(taskManager),
33
35
 
34
36
  // 単位操作
35
- ...createUnitHandlers(taskManager),
37
+ ...createUnitHandlers(taskManager),
38
+ ...createThinnedIndicesHandlers(taskManager),
39
+ ...createCadHandlers(taskManager),
36
40
 
37
41
  // 計算操作
38
42
  ...createCalculationHandlers(taskManager),
@@ -1,6 +1,7 @@
1
1
  // handlers/resetHandlers.js - YAML初期化ハンドラー
2
2
  import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
3
3
  import { logger } from '../../utils/logger.js';
4
+ import { MaterialCatalog } from '../../utils/MaterialCatalog.js';
4
5
 
5
6
  /**
6
7
  * poker_resetYaml ハンドラー
@@ -49,12 +50,9 @@ export function createResetYamlHandler(taskManager) {
49
50
  throw new McpError(ErrorCode.InvalidParams, `reset_level は ${validResetLevels.join(', ')} のいずれかである必要があります`);
50
51
  }
51
52
 
52
- const validMaterials = [
53
- 'Carbon', 'Concrete', 'Iron', 'Lead', 'Aluminium', 'Copper', 'Tungsten',
54
- 'Air', 'Water', 'PyrexGlass', 'AcrylicResin', 'Polyethylene', 'Soil', 'VOID'
55
- ];
56
- if (!validMaterials.includes(atmosphere_material)) {
57
- throw new McpError(ErrorCode.InvalidParams, `atmosphere_material は ${validMaterials.join(', ')} のいずれかである必要があります`);
53
+ if (!MaterialCatalog.has(atmosphere_material)) {
54
+ throw new McpError(ErrorCode.InvalidParams,
55
+ `atmosphere_material は ${MaterialCatalog.allMaterials().join(', ')} のいずれかである必要があります`);
58
56
  }
59
57
 
60
58
  // VOID材料の密度指定チェック
@@ -0,0 +1,48 @@
1
+ // mcp/handlers/thinnedIndicesHandlers.js
2
+ //
3
+ // thinnedindices(サマリー出力量の制御)のハンドラ。
4
+ // 既定値は poker_mcp 側で持たず、POKER の .summary に出力される値を正とする。
5
+
6
+ import { logger } from '../../utils/logger.js';
7
+
8
+ export function createThinnedIndicesHandlers(taskManager) {
9
+ return {
10
+ async proposeThinnedIndices(args) {
11
+ const result = await taskManager.proposeThinnedIndices(args || {});
12
+ return {
13
+ content: [{
14
+ type: 'text',
15
+ text: JSON.stringify({
16
+ success: true,
17
+ message: 'thinnedindices を提案しました(applyChanges で確定)',
18
+ ...result
19
+ }, null, 2)
20
+ }]
21
+ };
22
+ },
23
+
24
+ async getThinnedIndices() {
25
+ const result = await taskManager.getThinnedIndices();
26
+ return {
27
+ content: [{
28
+ type: 'text',
29
+ text: JSON.stringify(result, null, 2)
30
+ }]
31
+ };
32
+ },
33
+
34
+ async updateThinnedIndices(args) {
35
+ const result = await taskManager.updateThinnedIndices(args || {});
36
+ const msg = (args && args.fit_for_paths)
37
+ ? 'thinnedindices を更新しました(入力の分割数・評価点数に合わせました)'
38
+ : 'thinnedindices を更新しました(applyChanges で確定)';
39
+ logger.info(msg, { indices: result.thinnedindices });
40
+ return {
41
+ content: [{
42
+ type: 'text',
43
+ text: JSON.stringify({ success: true, message: msg, ...result }, null, 2)
44
+ }]
45
+ };
46
+ }
47
+ };
48
+ }
@@ -12,7 +12,7 @@ export const buildupFactorTools = [
12
12
  },
13
13
  equivalent: {
14
14
  type: 'string',
15
- description: '非標準材料のビルドアップ等価材料(省略時は組成の光子実効Zで最近傍の標準材料を自動選択)'
15
+ description: '非標準材料のビルドアップ等価材料(標準材料名)。省略時は組成の散乱/吸収比を実用エネルギー帯域で照合して自動選択'
16
16
  },
17
17
  use_slant_correction: {
18
18
  type: 'boolean',
@@ -45,6 +45,10 @@ export const buildupFactorTools = [
45
45
  use_finite_medium_correction: {
46
46
  type: 'boolean',
47
47
  description: '新しい有限媒体補正設定'
48
+ },
49
+ equivalent: {
50
+ type: 'string',
51
+ description: '非標準材料のビルドアップ等価材料(標準材料名)。空文字を指定すると等価材料の指定を解除します'
48
52
  }
49
53
  },
50
54
  required: ['material']