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 +152 -6
- package/package.json +61 -55
- package/src/mcp/handlers/cadHandlers.js +187 -0
- package/src/mcp/handlers/calculationHandlers.js +2 -1
- package/src/mcp/handlers/index.js +6 -2
- package/src/mcp/handlers/resetHandlers.js +4 -6
- package/src/mcp/handlers/thinnedIndicesHandlers.js +48 -0
- package/src/mcp/tools/buildupFactorTools.js +5 -1
- package/src/mcp/tools/cadTools.js +65 -0
- package/src/mcp/tools/calculationTools.js +5 -1
- package/src/mcp/tools/index.js +9 -3
- package/src/mcp/tools/resetTools.js +1 -5
- package/src/mcp/tools/thinnedIndicesTools.js +78 -0
- package/src/services/CalculationService.js +16 -5
- package/src/services/DataManager.js +36 -0
- package/src/services/TaskManager.js +191 -19
- package/src/utils/MaterialAlternatives.js +13 -3
- package/src/utils/MaterialCatalog.js +278 -16
- package/src/utils/paths.js +83 -0
- package/src/utils/pendingView.js +50 -0
- package/src/utils/summaryParser.js +152 -65
- package/src/validators/PhysicsValidator.js +15 -2
- package/tools/audit_mfp.py +174 -0
- package/tools/compare_poker_trace.py +140 -0
- package/tools/gen_paths.py +470 -0
- package/tools/poker_lib.py +172 -0
- package/tools/ray_trace_tri.py +296 -0
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.
|
|
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
|
-
- **
|
|
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
|
-
### 🔧 **
|
|
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
|
-
### 📋 **全
|
|
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.
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
"
|
|
53
|
-
".
|
|
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
|
+
}
|
|
@@ -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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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: '
|
|
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']
|