Skip to main content
Glama
zaqdaisuki

mahjong-calculator

by zaqdaisuki
README.md
# 麻雀点数計算 MCP サーバー

Claude ProjectsやClaude Desktopから麻雀の点数計算ができるMCPサーバーです。

## 特徴

- テキスト形式で牌姿を入力(例: `123m456p789s11z`)
- 赤ドラ対応(`0`で表現、例: `50m` = 赤5萬)
- 点数、役、翻数、符を自動計算
- Claude Desktopからツールとして直接呼び出し可能
- stdio/SSE両方のトランスポートに対応

## MCPサーバーとは

MCP (Model Context Protocol) は、Claude DesktopとAIツール間の通信プロトコルです。MCPサーバーを作成することで、Claudeに新しい機能(ツール)を追加できます。

このプロジェクトでは、麻雀の点数計算をClaudeから呼び出せるようにしています。

### トランスポート方式

MCPサーバーには2つの接続方式があります:

- **stdio(標準入出力)**: Claude Desktopがサーバープロセスを直接起動・管理(推奨)
- **SSE(Server-Sent Events)**: HTTPサーバーとして常駐し、Claude Desktopが接続

このプロジェクトでは、安定性と管理の容易さから **stdio方式** を推奨しています。

## セットアップ

### 1. 依存関係のインストール

```bash
uv sync
```

### 2. Claude Desktop での設定

設定ファイルの場所:
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`

#### Linux/macOS(ネイティブ環境)の場合

```json
{
  "mcpServers": {
    "mahjong-calculator": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/mahjong_calculator",
        "run",
        "python",
        "-m",
        "src.server"
      ]
    }
  }
}
```

**注意**: `/absolute/path/to/mahjong_calculator` の部分は、このプロジェクトの絶対パスに置き換えてください。

#### Windows + WSL環境の場合(推奨設定)

Windows上のClaude DesktopからWSL内のMCPサーバーを起動する場合:

```json
{
  "mcpServers": {
    "mahjong-calculator": {
      "command": "wsl",
      "args": [
        "-e",
        "bash",
        "-c",
        "export PATH=$HOME/.local/bin:$PATH && cd /home/your-username/projects/mahjong_calculator && exec uv run python -m src.server"
      ]
    }
  }
}
```

**重要**:
- `/home/your-username/projects/mahjong_calculator` をWSL内の実際のプロジェクトパスに置き換えてください
- `your-username` をWSLのユーザー名に置き換えてください
- この設定は、一行のコマンドとして実行されるため、確実に動作します

### 3. Claude Desktopを再起動

設定を反映させるため、Claude Desktopを完全に終了してから再起動してください。

## 使用方法

Claude DesktopやClaude Projectsで以下のように質問してください:

### 基本的な使い方

```
手牌: 234m345p456s6677z
和了牌: 7z
の点数を教えて
```

**注意**: 手牌(13枚)と和了牌(1枚)の合計14枚が正しい和了形(4面子1雀頭)である必要があります。

### 立直ツモの場合

```
手牌: 234m234p234s555z
和了牌: 5z
でツモ和了、立直ありの場合の点数を計算して
```

### ドラありの場合

```
手牌: 234m456p678s3344s
和了牌: 5s
でロン和了、ドラ表示牌が1mの場合の点数は?
```

## 入力形式

### 牌の表記

- **萬子**: `1-9m`(例: `123m`)
- **筒子**: `1-9p`(例: `456p`)
- **索子**: `1-9s`(例: `789s`)
- **字牌**: `1-7z`
  - `1z` = 東
  - `2z` = 南
  - `3z` = 西
  - `4z` = 北
  - `5z` = 白
  - `6z` = 發
  - `7z` = 中
- **赤ドラ**: `0`で表現(例: `50m` = 赤5萬)

### 例

| 牌姿 | 説明 |
|------|------|
| `123m456p789s1122z` | 一萬二萬三萬四筒五筒六筒七索八索九索東東南南 |
| `1230m456p789s11z` | 一萬二萬三萬赤五萬四筒五筒六筒七索八索九索東東 |
| `234m234p234s55z` | 二萬三萬四萬二筒三筒四筒二索三索四索白白 |

## パラメータ

MCPツール `calculate_mahjong_score` は以下のパラメータを受け付けます:

| パラメータ | 型 | 必須 | デフォルト | 説明 |
|-----------|-----|------|-----------|------|
| `tiles` | string | ✓ | - | 手牌 |
| `win_tile` | string | ✓ | - | 和了牌 |
| `dora_indicators` | string |  | "" | ドラ表示牌(カンマ区切り) |
| `player_wind` | string |  | "east" | 自風(east/south/west/north) |
| `round_wind` | string |  | "east" | 場風(east/south/west/north) |
| `is_tsumo` | boolean |  | true | ツモ和了かどうか |
| `is_riichi` | boolean |  | false | 立直しているか |
| `is_ippatsu` | boolean |  | false | 一発か |
| `is_rinshan` | boolean |  | false | 嶺上開花か |
| `is_chankan` | boolean |  | false | 搶槓か |
| `is_haitei` | boolean |  | false | 海底摸月か |
| `is_houtei` | boolean |  | false | 河底撈魚か |

## トラブルシューティング

### Claude Desktopで認識されない

1. **設定ファイルのパスと形式を確認**
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
   - JSON構文エラーがないか確認([JSONLint](https://jsonlint.com/)で検証可能)
   - ファイルをUTF-8で保存しているか確認

2. **プロジェクトのパスが絶対パスになっているか確認**
   - 相対パスは使用できません
   - WSL環境の場合: `/home/username/...` 形式

3. **WSL環境での確認事項**
   - `uv` コマンドが正しくインストールされているか確認:
     ```bash
     which uv
     uv --version
     ```
   - PATHが正しく設定されているか確認
   - Windows側から手動でコマンドを実行してテスト:
     ```cmd
     wsl -e bash -c "export PATH=$HOME/.local/bin:$PATH && cd /home/username/projects/mahjong_calculator && uv run python -m src.server"
     ```

4. **Claude Desktopを完全に再起動**
   - Windowsの場合: タスクマネージャーでプロセスが完全に終了していることを確認
   - 設定変更後は必ず再起動が必要

### サーバーを再起動すると接続できなくなる(WSL環境)

**問題**: ローカルでSSE形式のサーバーを起動した場合、再起動後にClaude Desktopから接続できなくなる

**解決策**: stdio形式を使用する(上記の「Windows + WSL環境の場合」の設定)

stdio形式の利点:
- Claude Desktopがサーバープロセスのライフサイクルを管理
- ポートの競合や接続問題が発生しない
- 設定が簡単で安定している

### SSE形式を使いたい場合

どうしてもSSE形式を使いたい場合は、以下の手順で起動:

```bash
bash /home/miz/projects/mahjong_calculator/start_http_server.sh
```

設定ファイル:
```json
{
  "mcpServers": {
    "mahjong-calculator": {
      "url": "http://localhost:8000/sse"
    }
  }
}
```

**注意**: SSE形式は手動でサーバーを起動・停止する必要があり、管理が煩雑です。

### 計算結果がおかしい

1. **入力形式が正しいか確認**
   - 萬子: `m`, 筒子: `p`, 索子: `s`, 字牌: `z`
   - 数字は0-9のみ(0は赤ドラ)
   - 例: `123m456p789s1122z`

2. **手牌が14枚になっているか確認**
   - 手牌13枚 + 和了牌1枚 = 合計14枚
   - 正しい和了形(4面子1雀頭)である必要があります

3. **和了っているか確認**
   - 向聴数が-1(テンパイを超えている状態)

### Claude Desktopのログを確認

MCPサーバーのログは標準エラー出力に出力されます。Claude Desktopのログで詳細を確認できます:

- **macOS**: `~/Library/Logs/Claude/`
- **Windows**: `%APPDATA%\Claude\logs\`

ログで以下を確認:
- サーバーが正常に起動しているか
- コマンドのパスが正しいか
- 実行時エラーが発生していないか

## 開発

### ローカルでのテスト

MCPサーバーとして起動せずに、直接Pythonスクリプトとして動作確認できます:

```bash
# JSON出力のテスト
uv run python test_json_output.py

# エラーケースのテスト
uv run python test_error_cases.py
```

### MCPサーバーのテスト

stdio形式で手動テスト:
```bash
bash start_stdio_server.sh
```

SSE形式で手動テスト(別ターミナルで実行):
```bash
# サーバー起動
bash start_http_server.sh

# 別ターミナルでアクセスを確認
curl http://localhost:8000/sse
```

### テストの実行

```bash
uv run pytest
```

### 型チェック

```bash
uv run mypy src/
```

### コードフォーマット

```bash
uv run ruff check src/
```

### 依存関係の更新

```bash
# 依存関係を追加
uv add package-name

# 依存関係を更新
uv sync --upgrade
```

## プロジェクト構成

```
mahjong_calculator/
├── pyproject.toml              # プロジェクト設定・依存関係
├── uv.lock                     # 依存関係のロックファイル
├── README.md                   # このファイル
├── main.py                     # スタンドアロン実行用(MCP不使用)
├── start_http_server.sh        # SSE形式でのサーバー起動スクリプト
├── start_stdio_server.sh       # stdio形式でのサーバー起動スクリプト
├── test_json_output.py         # JSON出力のテスト
├── test_error_cases.py         # エラーケースのテスト
└── src/
    ├── __init__.py             # パッケージ初期化
    ├── constants.py            # 定数定義
    ├── tile_parser.py          # 入力解析(テキスト→内部形式)
    ├── calculator.py           # 点数計算ロジック
    └── server.py               # MCPサーバー(エントリーポイント)
```

### ファイルの役割

#### コアモジュール
- **server.py**: MCPサーバーのエントリーポイント。Claude Desktopとの通信を担当
  - `calculate_mahjong_score()`: MCPツールとして公開される関数
  - stdio/SSE両方のトランスポートに対応

- **calculator.py**: 麻雀の点数計算ロジック
  - `calculate_hand()`: 手牌と和了牌から点数を計算
  - `GameContext`: 対局状況(自風、場風、リーチなど)を管理
  - 役、符、点数の詳細を返す

- **tile_parser.py**: テキスト形式の牌姿を解析
  - `123m456p789s11z` のような入力をmahjongライブラリの形式に変換
  - 赤ドラ(`0`)の処理に対応

- **constants.py**: 役名や符の理由の日本語翻訳など、定数を定義

#### 起動スクリプト
- **start_stdio_server.sh**: stdio形式でサーバーを起動(Claude Desktop推奨)
- **start_http_server.sh**: SSE形式(HTTP)でサーバーを起動

#### テスト
- **test_json_output.py**: 計算結果のJSON形式をテスト
- **test_error_cases.py**: エラーハンドリングをテスト

### アーキテクチャ

```
Claude Desktop
    ↓ (MCP stdio/SSE)
server.py (FastMCP)
    ↓
calculator.py (計算ロジック)
    ↓
tile_parser.py (入力解析)
    ↓
mahjong-python (外部ライブラリ)
```

1. **Claude Desktop** が MCP プロトコルでリクエストを送信
2. **server.py** が `calculate_mahjong_score` ツールとしてリクエストを受信
3. **tile_parser.py** が牌姿テキストを解析
4. **calculator.py** が mahjong-python ライブラリを使って計算
5. 結果を JSON 形式で Claude Desktop に返却

## ライセンス

このプロジェクトは個人用です。

TDQS

A4.6/5.0

Scored across 1 tool

Disambiguation5/5

With only one tool, there is no potential for confusion or overlap. The single tool has a clearly defined purpose: calculating mahjong scores.

Naming Consistency5/5

The tool name 'calculate_mahjong_score' follows a clear verb_noun pattern and is self-explanatory. With a single tool, naming consistency is trivially maintained.

Tool Count2/5

A single tool is too few for a typical MCP server, even for a calculator domain. The tool is comprehensive, but the server feels thin and under-scoped.

Completeness5/5

The tool covers all necessary aspects of mahjong score calculation, including hand tiles, win tile, dora indicators, winds, and various special conditions. It provides a complete solution for its stated purpose.

Maintenance

ActivityInactive
ResponsivenessNo issues