poker-mcp 1.2.5 → 1.2.7

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,12 +4,33 @@ YAML-based input file management tool for radiation-shielding calculation code P
4
4
 
5
5
  ## 📋 クイック情報
6
6
 
7
- - **バージョン**: 1.2.5 (Enhanced Release)
7
+ - **バージョン**: 1.2.7
8
8
  - **プロトコル**: MCP (Model Context Protocol) 1.0.0 完全準拠
9
9
  - **メインサーバー**: `src/mcp_server_stdio_v4.js`
10
- - **データ保存**: tasks/ディレクトリ(実行時自動作成)
10
+ - **データ保存**: `~/.poker-mcp/`(`POKER_MCP_HOME`環境変数で変更可)
11
11
  - **実行方式**: STDIO通信(MCPプロトコル標準)
12
12
 
13
+ ## 🆕 バージョン1.2.7の修正(バグフィックス)
14
+
15
+ ### 🐛 `poker_executeCalculation` の yaml_file パス解決を修正
16
+ ファイル名のみ(例: `poker.yaml`)を渡すと絶対パス要求でエラーになっていた
17
+ スキーマ・ハンドラー間の矛盾を修正しました。
18
+
19
+ - **ファイル名のみ指定** → `POKER_MCP_HOME/tasks/` に自動解決
20
+ - **絶対パス指定** → そのまま使用(後方互換)
21
+
22
+ ## 🆕 バージョン1.2.6の修正(バグフィックス)
23
+
24
+ ### 🐛 SERVER DISCONNECTED 問題を修正
25
+ `npx poker-mcp` 実行時にClaude Desktopがカレントディレクトリを
26
+ `C:\Windows\System32` に設定するため、相対パスでのフォルダ作成が
27
+ 権限エラー(EPERM)で失敗していた問題を修正しました。
28
+
29
+ - **`src/utils/paths.js` 新設**: 作業ディレクトリを一元管理
30
+ - **全ファイルパスを絶対パス化**: `logs/`・`backups/`・`tasks/`・`data/`
31
+ - **`POKER_MCP_HOME` 環境変数サポート**: 作業場所を自由に指定可能
32
+ - **エラー出力を `stderr` に追加**: 問題発生時の原因特定が容易に
33
+
13
34
  ## 🆕 バージョン1.2.5の新機能
14
35
 
15
36
  ### ⚡ 衝突検出システム
@@ -41,31 +62,45 @@ YAML-based input file management tool for radiation-shielding calculation code P
41
62
 
42
63
  ### 1. インストール
43
64
  ```bash
44
- # 依存関係インストール
65
+ # 依存関係インストール(ローカル開発時のみ)
45
66
  npm install
46
67
 
47
- # または NPX で直接使用
68
+ # または NPX で直接使用(インストール不要)
48
69
  npx poker-mcp
49
70
  ```
50
71
 
51
- ### 2. 環境変数設定(オプション)
72
+ ### 2. 環境変数設定
73
+
74
+ #### `POKER_MCP_HOME`(推奨・新設)
75
+ 作業ファイル(YAML・バックアップ・ログ・核種DB)の格納先を指定します。
76
+ **未設定時は `~/.poker-mcp/` が自動的に使用されます。**
77
+
78
+ #### `POKER_INSTALL_PATH`(オプション)
79
+ ICRP-07.NDX 核種データベースのコピー元を指定します。
52
80
 
53
- **POKER_INSTALL_PATH環境変数**(オプション):
54
81
  ```bash
55
- # Windowsの場合(コマンドプロンプト)
56
- set POKER_INSTALL_PATH=C:\Program Files\POKER
82
+ # Windows(コマンドプロンプト)
83
+ set POKER_MCP_HOME=C:\Users\yoshi\poker_mcp_workspace
84
+ set POKER_INSTALL_PATH=C:/Poker
57
85
 
58
- # Windowsの場合(PowerShell)
59
- $env:POKER_INSTALL_PATH="C:\Program Files\POKER"
86
+ # Windows(PowerShell)
87
+ $env:POKER_MCP_HOME="C:\Users\yoshi\poker_mcp_workspace"
88
+ $env:POKER_INSTALL_PATH="C:/Poker"
60
89
 
61
- # Linux/macOSの場合
90
+ # Linux/macOS
91
+ export POKER_MCP_HOME="$HOME/.poker-mcp"
62
92
  export POKER_INSTALL_PATH="/usr/local/share/poker"
63
93
  ```
64
94
 
65
- - **デフォルト値**: `C:/Poker`
66
- - **目的**: `lib/ICRP-07.NDX`核種データベースファイルの取得元ディレクトリ指定
67
- - **動作**: 初回起動時に`{POKER_INSTALL_PATH}/lib/ICRP-07.NDX`を`data/`ディレクトリにコピー
68
- - **注意**: `data/ICRP-07.NDX`が既に存在する場合はコピーをスキップ
95
+ **データ格納先の構造:**
96
+ ```
97
+ POKER_MCP_HOME/ # デフォルト: ~/.poker-mcp/
98
+ ├── tasks/ # poker.yaml, pending_changes.json
99
+ ├── backups/ # 自動バックアップ(最大10世代)
100
+ ├── data/ # ICRP-07.NDX 核種データベース
101
+ ├── logs/ # error.log, combined.log
102
+ └── config.json # ユーザー設定(任意)
103
+ ```
69
104
 
70
105
  ### 3. Claude Desktop設定
71
106
 
@@ -78,22 +113,7 @@ export POKER_INSTALL_PATH="/usr/local/share/poker"
78
113
  Linux: ~/.config/claude/claude_desktop_config.json
79
114
  ```
80
115
 
81
- 2. **MCP設定を追加**
82
- ```json
83
- {
84
- "mcpServers": {
85
- "poker-mcp": {
86
- "command": "node",
87
- "args": ["C:\\Users\\yoshi\\Desktop\\poker_mcp\\src\\mcp_server_stdio_v4.js"],
88
- "env": {
89
- "POKER_INSTALL_PATH": "C:/Program Files/POKER"
90
- }
91
- }
92
- }
93
- }
94
- ```
95
-
96
- 3. **NPXを使用する場合**
116
+ 2. **推奨設定(v1.2.6)**
97
117
  ```json
98
118
  {
99
119
  "mcpServers": {
@@ -101,18 +121,20 @@ export POKER_INSTALL_PATH="/usr/local/share/poker"
101
121
  "command": "npx",
102
122
  "args": ["poker-mcp"],
103
123
  "env": {
104
- "POKER_INSTALL_PATH": "C:/Program Files/POKER"
124
+ "POKER_MCP_HOME": "C:\\Users\\<username>\\poker_mcp_workspace",
125
+ "POKER_INSTALL_PATH": "C:/Poker"
105
126
  }
106
127
  }
107
128
  }
108
129
  }
109
130
  ```
131
+ `<username>` はご自身のWindowsユーザー名に置き換えてください。
132
+ `POKER_INSTALL_PATH` は省略可能です(デフォルト: `C:/Poker`)。
110
133
 
111
- 4. **Claude Desktopを再起動** してMCPサーバーを有効化
134
+ > **⚠️ 注意:** `cwd`(作業ディレクトリ)の指定は不要です。`POKER_MCP_HOME`
135
+ > 環境変数で管理するため、`cwd` を設定すると v1.2.5 以前の問題が再発します。
112
136
 
113
- **注意**:
114
- - `env`セクションの`POKER_INSTALL_PATH`はオプションです(省略時は`C:/Poker`を使用)
115
- - 環境変数で指定したパスの`lib/ICRP-07.NDX`ファイルが初回起動時に`data/`にコピーされます
137
+ 3. **Claude Desktopを再起動** してMCPサーバーを有効化
116
138
 
117
139
  ### 4. 動作確認
118
140
  Claude Desktopで以下のようにテストできます:
@@ -188,28 +210,28 @@ poker_mcp/
188
210
  │ ├── 📁 services/ # ビジネスロジック
189
211
  │ ├── 📁 validators/ # データ検証(物理・単位・衝突)
190
212
  │ ├── 📁 utils/ # ユーティリティ
213
+ │ │ ├── paths.js # ★ パス管理(POKER_MCP_HOME起点)
214
+ │ │ ├── logger.js # ログ出力(絶対パス)
215
+ │ │ └── ...
191
216
  │ └── 📁 config/ # 設定管理
192
- ├── 📁 data/ # 📊 核種データベース
193
- │ └── ICRP-07.NDX # ICRP-107核種データ(1,254核種)
194
- ├── 📁 config/ # ⚙️ 設定ファイル
195
- │ ├── mcp-manifest.json # MCPマニフェスト (2,276行)
196
- │ └── mcp-example.json # 設定例
197
217
  ├── 📁 docs/ # 📚 完全ドキュメント
198
- │ ├── README.md # 詳細ドキュメント
199
- │ ├── 📁 manuals/ # マニュアル集
200
- │ └── 📁 interactive_guides/ # インタラクティブ学習ガイド
201
- ├── 📁 node_modules/ # 📦 依存パッケージ
202
218
  ├── .mcp.json # MCPクライアント接続設定
203
- ├── package.json # パッケージ定義
204
- ├── package-lock.json # 依存関係ロック
219
+ ├── package.json # パッケージ定義(v1.2.6)
205
220
  └── README.md # このファイル
206
221
 
207
- # 実行時に自動作成されるディレクトリ
208
- ├── 📁 tasks/ # 📊 作業ディレクトリ(自動作成)
222
+ # 実行時に自動作成されるディレクトリ(POKER_MCP_HOME配下)
223
+ # デフォルト: C:\Users\<username>\.poker-mcp\ または ~/.poker-mcp/
224
+ POKER_MCP_HOME/
225
+ ├── 📁 tasks/ # 📊 作業ディレクトリ
209
226
  │ ├── poker.yaml # メインYAMLファイル
210
227
  │ └── pending_changes.json # 保留中の変更
211
- ├── 📁 backups/ # 💾 自動バックアップ(自動作成)
212
- └── 📁 logs/ # 📝 ログファイル(自動作成)
228
+ ├── 📁 backups/ # 💾 自動バックアップ(最大10世代)
229
+ ├── 📁 data/ # 🧪 核種データベース
230
+ │ └── ICRP-07.NDX # ICRP-07核種データ(1,254核種)
231
+ ├── 📁 logs/ # 📝 ログファイル
232
+ │ ├── error.log
233
+ │ └── combined.log
234
+ └── config.json # ユーザー設定(任意)
213
235
  ```
214
236
 
215
237
  ## 🔧 Claude経由での使用例
@@ -323,6 +345,18 @@ poker_mcp/
323
345
 
324
346
  ## 📝 更新履歴
325
347
 
348
+ ### v1.2.7 (2026-05-16)
349
+ - 🐛 `poker_executeCalculation` の `yaml_file` パス解決バグを修正(スキーマ・ハンドラー間の矛盾)
350
+ - ✨ ファイル名のみの指定で `POKER_MCP_HOME/tasks/` 配下を自動参照
351
+ - 📝 `API_COMPLETE.md`・`INTEGRATION_GUIDE.md`・`RESEARCH_WORKFLOWS.md` 更新
352
+
353
+ ### v1.2.6 (2026-05-16)
354
+ - 🐛 `npx` 実行時のSERVER DISCONNECTED問題を修正(EPERM: C:\Windows\System32\logs)
355
+ - ✨ `src/utils/paths.js` 新設(`POKER_MCP_HOME`環境変数によるパス一元管理)
356
+ - ✨ `POKER_MCP_HOME`環境変数サポート(未設定時は`~/.poker-mcp/`をデフォルト使用)
357
+ - 🐛 全ファイルパスを絶対パスに変更(logger, DataManager, ConfigManager, server)
358
+ - ✨ 致命的エラーを`stderr`にも出力(Claude Desktopログから原因確認可能に)
359
+
326
360
  ### v1.2.5 (2025-01-24)
327
361
  - ✨ 衝突検出システム実装
328
362
  - ✨ 子孫核種自動補完機能追加(ICRP-07統合)
@@ -330,9 +364,7 @@ poker_mcp/
330
364
  - ✨ YAMLリセット機能実装(3段階レベル)
331
365
  - ✨ 検出器分析機能追加
332
366
  - 🐛 NuclideManagerデフォルトパス統一
333
- - 📝 .mcp.json完全化
334
367
  - 📝 材料数13→14(VOID追加明記)
335
- - 🗑️ archiveディレクトリ削除(未使用ファイル整理)
336
368
 
337
369
  ### v1.1.0 (Previous)
338
370
  - 基本24メソッド実装
@@ -348,11 +380,11 @@ poker_mcp/
348
380
  - **📖 詳細README**: [docs/README.md](docs/README.md)
349
381
  - **📚 完全マニュアル**: [docs/manuals/](docs/manuals/)
350
382
  - **🎓 インタラクティブガイド**: [docs/interactive_guides/](docs/interactive_guides/)
351
- - **📋 マニフェスト**: [config/mcp-manifest.json](config/mcp-manifest.json)
383
+ - **📋 変更履歴**: [CHANGELOG.md](CHANGELOG.md)
352
384
  - **🐛 Issues**: [GitHub Issues](https://github.com/Hirao-Y/poker_mcp/issues)
353
385
 
354
386
  ---
355
387
 
356
- **🎯 Poker MCP Server v1.2.5**
388
+ **🎯 Poker MCP Server v1.2.7**
357
389
  **プロトコル**: MCP 1.0.0 完全準拠
358
390
  **作者**: Yoshihiro Hirao | **ライセンス**: ISC
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poker-mcp",
3
- "version": "1.2.5",
3
+ "version": "1.2.7",
4
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
5
  "main": "src/mcp_server_stdio_v4.js",
6
6
  "type": "module",
@@ -1,14 +1,21 @@
1
1
  // src/config/ConfigManager.js
2
2
  import fs from 'fs/promises';
3
3
  import path from 'path';
4
+ import { fileURLToPath } from 'url';
4
5
  import { logger } from '../utils/logger.js';
5
6
  import { DataError } from '../utils/errors.js';
7
+ import { USER_CONFIG } from '../utils/paths.js';
8
+
9
+ const __filename = fileURLToPath(import.meta.url);
10
+ const __dirname = path.dirname(__filename);
6
11
 
7
12
  export class ConfigManager {
8
13
  constructor() {
9
14
  this.config = null;
10
- this.configPath = 'src/config/default.json';
11
- this.userConfigPath = 'config.json';
15
+ // default.json はパッケージ同梱なので __dirname 基準の絶対パスで解決
16
+ this.configPath = path.join(__dirname, 'default.json');
17
+ // ユーザー設定は POKER_MCP_HOME 配下に置く
18
+ this.userConfigPath = USER_CONFIG;
12
19
  }
13
20
 
14
21
  async load() {
@@ -3,6 +3,7 @@ import { CalculationService } from '../../services/CalculationService.js';
3
3
  import { ValidationError, CalculationError } from '../../utils/errors.js';
4
4
  import { logger } from '../../utils/logger.js';
5
5
  import path from 'path';
6
+ import { TASKS_DIR } from '../../utils/paths.js';
6
7
 
7
8
  export function createCalculationHandlers(taskManager) {
8
9
  const calculationService = new CalculationService();
@@ -15,18 +16,22 @@ export function createCalculationHandlers(taskManager) {
15
16
  throw new ValidationError('YAML file is required', 'yaml_file', args.yaml_file);
16
17
  }
17
18
 
18
- // 絶対パス形式の事前チェック(詳細検証はサービス層で実行)
19
+ // パス解決:
20
+ // 絶対パスが渡された場合 → そのまま使用(後方互換)
21
+ // ファイル名のみの場合 → TASKS_DIR と結合して絶対パスに解決
19
22
  const absolutePathPattern = /^([a-zA-Z]:[\\\/]|\/)/;
20
- if (!absolutePathPattern.test(args.yaml_file)) {
21
- throw new ValidationError(
22
- 'YAML file must be specified with absolute path. Examples: C:\\path\\to\\file.yaml or /path/to/file.yaml',
23
- 'yaml_file',
24
- args.yaml_file
25
- );
26
- }
23
+ const resolvedYamlFile = absolutePathPattern.test(args.yaml_file)
24
+ ? args.yaml_file
25
+ : path.join(TASKS_DIR, args.yaml_file);
26
+
27
+ logger.info('yaml_file path resolved', {
28
+ input: args.yaml_file,
29
+ resolved: resolvedYamlFile,
30
+ tasksDir: TASKS_DIR
31
+ });
27
32
 
28
33
  // YAML拡張子チェック
29
- if (!args.yaml_file.match(/\.(yaml|yml)$/i)) {
34
+ if (!resolvedYamlFile.match(/\.(yaml|yml)$/i)) {
30
35
  throw new ValidationError(
31
36
  'YAML file must have .yaml or .yml extension',
32
37
  'yaml_file',
@@ -46,13 +51,12 @@ export function createCalculationHandlers(taskManager) {
46
51
  const resolvedOutputFiles = {};
47
52
 
48
53
  if (Object.keys(outputFiles).length > 0) {
49
- // 入力YAMLファイルのディレクトリを取得
50
- const inputDir = path.dirname(args.yaml_file);
54
+ // 解決済みの入力YAMLファイルのディレクトリを取得
55
+ const inputDir = path.dirname(resolvedYamlFile);
51
56
 
52
57
  // 各出力ファイルの絶対パス化
53
58
  for (const [key, fileName] of Object.entries(outputFiles)) {
54
59
  if (fileName) {
55
- // ファイル名の拡張子チェック
56
60
  if (!fileName.match(/\.(yaml|yml)$/i)) {
57
61
  throw new ValidationError(
58
62
  `Output file ${key} must have .yaml or .yml extension`,
@@ -60,42 +64,35 @@ export function createCalculationHandlers(taskManager) {
60
64
  fileName
61
65
  );
62
66
  }
63
-
64
- // 絶対パスに解決
65
67
  resolvedOutputFiles[key] = path.join(inputDir, fileName);
66
-
67
68
  logger.debug('Output file path resolved', {
68
- key,
69
- fileName,
70
- inputDir,
69
+ key, fileName, inputDir,
71
70
  resolvedPath: resolvedOutputFiles[key]
72
71
  });
73
72
  }
74
73
  }
75
74
  }
76
75
 
77
- // 出力ファイル検証(従来の検証は不要、上記で実施済み)
78
-
79
76
  logger.info('Starting radiation shielding calculation', {
80
- yamlFile: args.yaml_file,
77
+ yamlFile: resolvedYamlFile,
81
78
  summaryOptions,
82
- outputFiles: outputFiles,
79
+ outputFiles,
83
80
  resolvedOutputFiles
84
81
  });
85
82
 
86
- // 計算実行(統合検証付き、絶対パス化済みの出力ファイルパスを使用)
83
+ // 計算実行(統合検証付き)
87
84
  const result = await calculationService.executeWithValidation(
88
- args.yaml_file,
85
+ resolvedYamlFile,
89
86
  summaryOptions,
90
- resolvedOutputFiles, // 絶対パス化済み
91
- undefined, // timeout(デフォルト値を使用)
92
- taskManager.dataManager // 事前検証用DataManager
87
+ resolvedOutputFiles,
88
+ undefined,
89
+ taskManager.dataManager
93
90
  );
94
91
 
95
92
  // 事前検証で重大エラーが検出された場合の処理
96
93
  if (result.success === false && result.stage === 'pre_validation') {
97
94
  logger.error('Pre-calculation validation failed', {
98
- yamlFile: args.yaml_file,
95
+ yamlFile: resolvedYamlFile,
99
96
  criticalErrors: result.criticalErrors
100
97
  });
101
98
 
@@ -128,7 +125,7 @@ export function createCalculationHandlers(taskManager) {
128
125
  success: true,
129
126
  message: 'Radiation shielding calculation completed successfully',
130
127
  calculation: {
131
- input_file: args.yaml_file,
128
+ input_file: resolvedYamlFile,
132
129
  execution_time_ms: result.executionTime,
133
130
  timestamp: result.summary.timestamp,
134
131
  options: result.summary.options
@@ -161,7 +158,7 @@ export function createCalculationHandlers(taskManager) {
161
158
  }
162
159
 
163
160
  logger.info('Calculation completed successfully', {
164
- yamlFile: args.yaml_file,
161
+ yamlFile: resolvedYamlFile,
165
162
  executionTime: result.executionTime,
166
163
  outputFiles: Object.keys(fileVerification).filter(k => k !== 'allFilesGenerated')
167
164
  });
package/src/mcp/server.js CHANGED
@@ -7,9 +7,10 @@ import { allTools } from './tools/index.js';
7
7
  import { createAllHandlers } from './handlers/index.js';
8
8
  import { safeExecute } from './middleware/errorHandler.js';
9
9
  import { logger } from '../utils/logger.js';
10
+ import { YAML_FILE, PENDING_FILE } from '../utils/paths.js';
10
11
 
11
12
  export class PokerMcpServer {
12
- constructor(yamlFile = 'tasks/poker.yaml', pendingFile = 'tasks/pending_changes.json') {
13
+ constructor(yamlFile = YAML_FILE, pendingFile = PENDING_FILE) {
13
14
  this.server = new Server(
14
15
  {
15
16
  name: 'poker-mcp',
@@ -8,8 +8,8 @@ export const calculationTools = [
8
8
  properties: {
9
9
  yaml_file: {
10
10
  type: 'string',
11
- description: '計算に使用するYAMLファイル名(拡張子.yamlを含む)',
12
- pattern: '^[a-zA-Z0-9_\\-\\.]+\\.(yaml|yml)$'
11
+ description: '計算に使用するYAMLファイル名(拡張子.yamlを含む)。ファイル名のみ指定(例: poker.yaml)で、POKER_MCP_HOME/tasks/ 配下のファイルが自動的に参照されます。絶対パスも指定可能です。',
12
+ pattern: '^([a-zA-Z0-9_\\-\\.]+\\.(yaml|yml)|([a-zA-Z]:[\\\\\/]|\\/)[^\\\\]+\\.(yaml|yml))$'
13
13
  },
14
14
  summary_options: {
15
15
  type: 'object',
@@ -1,45 +1,47 @@
1
- #!/usr/bin/env node
2
- // mcp_server_stdio_v4.js - MCP専用版(stdout汚染防止)
3
- import { PokerMcpServer } from './mcp/server.js';
4
- import { logger } from './utils/logger.js';
5
-
6
- async function main() {
7
- try {
8
- const server = new PokerMcpServer();
9
- await server.initialize();
10
- await server.start();
11
- } catch (error) {
12
- logger.error('サーバー起動失敗', { error: error.message });
13
- // console.errorは削除(stdout汚染防止)
14
- process.exit(1);
15
- }
16
- }
17
-
18
- // 未処理の例外とプロミス拒否のハンドリング
19
- process.on('uncaughtException', (error) => {
20
- logger.error('Uncaught Exception', { error: error.message, stack: error.stack });
21
- // console.errorは削除(stdout汚染防止)
22
- process.exit(1);
23
- });
24
-
25
- process.on('unhandledRejection', (reason, promise) => {
26
- logger.error('Unhandled Rejection', { reason: reason?.message || reason, promise });
27
- // console.errorは削除(stdout汚染防止)
28
- process.exit(1);
29
- });
30
-
31
- // グレースフルシャットダウン
32
- process.on('SIGINT', () => {
33
- logger.info('SIGINT受信、サーバーを終了します');
34
- process.exit(0);
35
- });
36
-
37
- process.on('SIGTERM', () => {
38
- logger.info('SIGTERM受信、サーバーを終了します');
39
- process.exit(0);
40
- });
41
-
42
- main().catch((error) => {
43
- logger.error('メイン関数エラー', { error: error.message });
44
- process.exit(1);
45
- });
1
+ #!/usr/bin/env node
2
+ // mcp_server_stdio_v4.js - MCP専用版(stdout汚染防止)
3
+ import { PokerMcpServer } from './mcp/server.js';
4
+ import { logger } from './utils/logger.js';
5
+
6
+ async function main() {
7
+ try {
8
+ const server = new PokerMcpServer();
9
+ await server.initialize();
10
+ await server.start();
11
+ } catch (error) {
12
+ logger.error('サーバー起動失敗', { error: error.message });
13
+ // stdoutは汚染禁止だが、stderrへの出力は許容(Claude Desktopがログに記録する)
14
+ process.stderr.write(`[poker-mcp] Fatal: ${error.message}\n`);
15
+ process.exit(1);
16
+ }
17
+ }
18
+
19
+ // 未処理の例外とプロミス拒否のハンドリング
20
+ process.on('uncaughtException', (error) => {
21
+ logger.error('Uncaught Exception', { error: error.message, stack: error.stack });
22
+ process.stderr.write(`[poker-mcp] Uncaught Exception: ${error.message}\n`);
23
+ process.exit(1);
24
+ });
25
+
26
+ process.on('unhandledRejection', (reason, promise) => {
27
+ logger.error('Unhandled Rejection', { reason: reason?.message || reason, promise });
28
+ process.stderr.write(`[poker-mcp] Unhandled Rejection: ${reason?.message || reason}\n`);
29
+ process.exit(1);
30
+ });
31
+
32
+ // グレースフルシャットダウン
33
+ process.on('SIGINT', () => {
34
+ logger.info('SIGINT受信、サーバーを終了します');
35
+ process.exit(0);
36
+ });
37
+
38
+ process.on('SIGTERM', () => {
39
+ logger.info('SIGTERM受信、サーバーを終了します');
40
+ process.exit(0);
41
+ });
42
+
43
+ main().catch((error) => {
44
+ logger.error('メイン関数エラー', { error: error.message });
45
+ process.stderr.write(`[poker-mcp] Main error: ${error.message}\n`);
46
+ process.exit(1);
47
+ });
@@ -7,13 +7,16 @@ import { DataError } from '../utils/errors.js';
7
7
  import CollisionDetector from '../utils/CollisionDetector.js';
8
8
  import NuclideManager from '../utils/NuclideManager.js';
9
9
  import EnhancedValidator from '../utils/EnhancedValidator.js';
10
+ import { BACKUPS_DIR, LOGS_DIR, TASKS_DIR, DATA_DIR, NDX_FILE,
11
+ YAML_FILE, PENDING_FILE } from '../utils/paths.js';
10
12
 
11
13
  export class SafeDataManager {
12
14
  constructor(yamlFile, pendingFile) {
13
- this.yamlFile = yamlFile;
14
- this.pendingFile = pendingFile;
15
- this.backupDir = 'backups';
16
- this.maxBackups = 10;
15
+ // 引数が省略された場合は paths.js の絶対パスをデフォルトとして使用
16
+ this.yamlFile = yamlFile ?? YAML_FILE;
17
+ this.pendingFile = pendingFile ?? PENDING_FILE;
18
+ this.backupDir = BACKUPS_DIR;
19
+ this.maxBackups = 10;
17
20
  this.data = null;
18
21
  this.pendingChanges = [];
19
22
 
@@ -24,11 +27,11 @@ export class SafeDataManager {
24
27
  max_auto_corrections: 10
25
28
  });
26
29
 
27
- // 核種管理の初期化
30
+ // 核種管理の初期化(絶対パスを使用)
28
31
  this.nuclideManager = new NuclideManager({
29
32
  contribution_threshold: 0.05,
30
33
  user_confirmation: true,
31
- database_file: 'data/ICRP-07.NDX'
34
+ database_file: NDX_FILE
32
35
  });
33
36
 
34
37
  // 強化検証の初期化
@@ -41,11 +44,11 @@ export class SafeDataManager {
41
44
 
42
45
  async initialize() {
43
46
  try {
44
- // 必要なフォルダをすべて作成
45
- await fs.mkdir(this.backupDir, { recursive: true }); // backups
46
- await fs.mkdir('logs', { recursive: true }); // logs
47
- await fs.mkdir('tasks', { recursive: true }); // tasks
48
- await fs.mkdir('data', { recursive: true }); // data
47
+ // 必要なフォルダをすべて作成(絶対パスで権限エラーを回避)
48
+ await fs.mkdir(BACKUPS_DIR, { recursive: true }); // backups
49
+ await fs.mkdir(LOGS_DIR, { recursive: true }); // logs
50
+ await fs.mkdir(TASKS_DIR, { recursive: true }); // tasks
51
+ await fs.mkdir(DATA_DIR, { recursive: true }); // data
49
52
 
50
53
  // 必要なデータファイルをコピー
51
54
  await this.ensureDataFiles();
@@ -70,7 +73,7 @@ export class SafeDataManager {
70
73
  // 新規メソッド: 必要なデータファイルの確保
71
74
  async ensureDataFiles() {
72
75
  try {
73
- const targetFile = 'data/ICRP-07.NDX';
76
+ const targetFile = NDX_FILE; // 絶対パスを使用
74
77
 
75
78
  // ターゲットファイルの存在チェック
76
79
  try {
@@ -1,24 +1,29 @@
1
- // utils/logger.js - MCP専用版(stdout汚染防止)
2
- import winston from 'winston';
3
- import path from 'path';
4
-
5
- const logger = winston.createLogger({
6
- level: process.env.LOG_LEVEL || 'info',
7
- format: winston.format.combine(
8
- winston.format.timestamp(),
9
- winston.format.errors({ stack: true }),
10
- winston.format.json()
11
- ),
12
- transports: [
13
- new winston.transports.File({
14
- filename: path.join('logs', 'error.log'),
15
- level: 'error'
16
- }),
17
- new winston.transports.File({
18
- filename: path.join('logs', 'combined.log')
19
- })
20
- // Console transportは削除(MCPサーバーではstdout汚染禁止)
21
- ]
22
- });
23
-
24
- export { logger };
1
+ // utils/logger.js - MCP専用版(stdout汚染防止)
2
+ import winston from 'winston';
3
+ import path from 'path';
4
+ import fs from 'fs';
5
+ import { LOGS_DIR } from './paths.js';
6
+
7
+ // ログディレクトリを起動時に確実に作成(相対パス問題を回避)
8
+ fs.mkdirSync(LOGS_DIR, { recursive: true });
9
+
10
+ const logger = winston.createLogger({
11
+ level: process.env.LOG_LEVEL || 'info',
12
+ format: winston.format.combine(
13
+ winston.format.timestamp(),
14
+ winston.format.errors({ stack: true }),
15
+ winston.format.json()
16
+ ),
17
+ transports: [
18
+ new winston.transports.File({
19
+ filename: path.join(LOGS_DIR, 'error.log'),
20
+ level: 'error'
21
+ }),
22
+ new winston.transports.File({
23
+ filename: path.join(LOGS_DIR, 'combined.log')
24
+ })
25
+ // Console transportは削除(MCPサーバーではstdout汚染禁止)
26
+ ]
27
+ });
28
+
29
+ export { logger };
@@ -0,0 +1,24 @@
1
+ // utils/paths.js - 実行時データの格納先を一元管理
2
+ //
3
+ // 優先順位:
4
+ // 1. 環境変数 POKER_MCP_HOME が設定されていれば、その値を使用
5
+ // 2. 未設定なら os.homedir()/.poker-mcp/ をデフォルトとする
6
+ //
7
+ // claude_desktop_config.json での設定例:
8
+ // "env": { "POKER_MCP_HOME": "C:\\Users\\yoshi\\poker_mcp_workspace" }
9
+ //
10
+ import path from 'path';
11
+ import os from 'os';
12
+
13
+ export const BASE_DIR = process.env.POKER_MCP_HOME
14
+ ?? path.join(os.homedir(), '.poker-mcp');
15
+
16
+ export const LOGS_DIR = path.join(BASE_DIR, 'logs');
17
+ export const TASKS_DIR = path.join(BASE_DIR, 'tasks');
18
+ export const BACKUPS_DIR = path.join(BASE_DIR, 'backups');
19
+ export const DATA_DIR = path.join(BASE_DIR, 'data');
20
+
21
+ export const YAML_FILE = path.join(TASKS_DIR, 'poker.yaml');
22
+ export const PENDING_FILE = path.join(TASKS_DIR, 'pending_changes.json');
23
+ export const NDX_FILE = path.join(DATA_DIR, 'ICRP-07.NDX');
24
+ export const USER_CONFIG = path.join(BASE_DIR, 'config.json');