# MCPツール直接実行の技術的背景

## 1. はじめに

本ドキュメントは、`compatibility_test/scripts/run_compatibility_test.py` がなぜMCPサーバーを経由せずに直接ツールクラスをインスタンス化して実行できるのか、そしてなぜこのアプローチが互換性テストにおいて有効なのかについて、技術的背景を詳しく説明します。

## 2. 質問の背景

**質問**: なぜ今の`run_compatibility_test.py`が有効ですか？なぜAIクライアントで実行しなくても有効ですか？

この質問は、MCPプロトコルの本来の使用方法（AIクライアント → MCPサーバー → ツール実行）と、互換性テストスクリプトの実装方法（Python スクリプト → ツールクラス直接実行）の違いに関する重要な技術的疑問です。

## 3. MCPアーキテクチャの理解

### 3.1. 標準的なMCPフロー

```
AIクライアント (Claude, Cursor等)
    ↓ JSON-RPC over stdio/SSE
MCPサーバー (tree_sitter_analyzer.mcp.server)
    ↓ Python関数呼び出し
MCPツールクラス (SearchContentTool, QueryTool等)
    ↓ 内部処理
tree-sitter-analyzer コアライブラリ
```

### 3.2. 互換性テストでの直接実行フロー

```
run_compatibility_test.py
    ↓ 直接インポート & インスタンス化
MCPツールクラス (SearchContentTool, QueryTool等)
    ↓ 内部処理
tree-sitter-analyzer コアライブラリ
```

## 4. 直接実行が可能な理由

### 4.1. アーキテクチャの分離設計

`tree-sitter-analyzer` は、以下のような分離されたアーキテクチャを採用しています。

1. **コアライブラリ** (`tree_sitter_analyzer.core.*`)
   - 実際の解析処理を担当
   - MCPプロトコルに依存しない純粋なPythonライブラリ

2. **MCPツールクラス** (`tree_sitter_analyzer.mcp.tools.*`)
   - コアライブラリをラップし、MCP仕様に準拠したインターフェースを提供
   - 独立したPythonクラスとして実装されており、MCPサーバー外でも実行可能

3. **MCPサーバー** (`tree_sitter_analyzer.mcp.server`)
   - MCPプロトコルの通信処理を担当
   - ツールクラスを呼び出すだけの薄いレイヤー

### 4.2. ツールクラスの独立性

各MCPツールクラスは以下の特徴を持っています。

```python
# 例: SearchContentTool の実装構造
class SearchContentTool(BaseMCPTool):
    def __init__(self, project_root: str = None):
        # MCPサーバーに依存しない初期化
        super().__init__(project_root)
        
    async def execute(self, arguments: dict) -> dict:
        # 実際の処理ロジック（MCPプロトコルとは独立）
        return await self._perform_search(arguments)
```

**重要なポイント**:
- ツールクラスは `project_root` パラメータのみで初期化可能
- `execute()` メソッドは標準的な Python の `dict` を入出力とする
- MCPサーバーやAIクライアントへの依存関係は一切ない

### 4.3. 依存関係の方向

```
MCPサーバー → MCPツールクラス → コアライブラリ
     ↑              ↑
   依存する      依存しない
```

この設計により、MCPツールクラスはMCPサーバーに依存せず、独立して実行できます。

## 5. 直接実行の利点

### 5.1. テストの信頼性向上

1. **プロトコルオーバーヘッドの排除**
   - JSON-RPC通信のエラーやタイムアウトの影響を受けない
   - ネットワーク層の問題を排除

2. **環境依存性の最小化**
   - AIクライアントの設定や状態に依存しない
   - MCPサーバーの起動状態に依存しない

3. **デバッグの容易さ**
   - Python の標準的なデバッグツールが使用可能
   - スタックトレースが直接的で分かりやすい

### 5.2. 自動化の実現

1. **CI/CDパイプラインでの実行**
   - AIクライアントなしで自動実行可能
   - バッチ処理として組み込み可能

2. **スクリプト化**
   - 複数バージョンの自動比較
   - 大量のテストケースの並列実行

### 5.3. パフォーマンス

1. **オーバーヘッドの削減**
   - JSON シリアライゼーション/デシリアライゼーションが不要
   - プロセス間通信のコストが不要

2. **リソース効率**
   - MCPサーバープロセスの起動が不要
   - メモリ使用量の最適化

## 6. 実装の詳細

### 6.1. ツールクラスの直接インスタンス化

```python
# run_compatibility_test.py での実装例
async def _execute_mcp_tool(self, tool_name: str, params: Dict[str, Any]) -> Any:
    project_root = str(self.project_root)
    
    if tool_name == "search_content":
        from tree_sitter_analyzer.mcp.tools.search_content_tool import SearchContentTool
        tool = SearchContentTool(project_root)  # 直接インスタンス化
        return await tool.execute(params)       # 直接実行
```

### 6.2. パラメータの互換性

MCPプロトコル経由で渡されるパラメータと、直接実行時のパラメータは完全に同一です。

```python
# MCPクライアント経由の場合
{
    "file_path": "examples/Sample.java",
    "query_key": "methods",
    "output_format": "json"
}

# 直接実行の場合（同じパラメータ）
{
    "file_path": "examples/Sample.java", 
    "query_key": "methods",
    "output_format": "json"
}
```

### 6.3. 結果の互換性

出力結果も完全に同一です。

```python
# どちらの実行方法でも同じ結果
{
    "success": True,
    "count": 5,
    "results": [...],
    "elapsed_ms": 123
}
```

## 7. 互換性テストにおける妥当性

### 7.1. 機能的等価性

直接実行とMCP経由実行は、以下の点で機能的に等価です。

1. **同一のコードパス**
   - 両方とも最終的に同じ `execute()` メソッドを呼び出す
   - 同一のコアライブラリを使用

2. **同一の入出力**
   - パラメータ形式が同一
   - 結果形式が同一

3. **同一のエラーハンドリング**
   - 例外処理ロジックが同一
   - エラーメッセージが同一

### 7.2. バージョン間比較の有効性

互換性テストの目的は「異なるバージョン間でツールの動作が一致するか」を確認することです。

- **MCPプロトコル層**: バージョン間で変化しない（テスト対象外）
- **ツール実装層**: バージョン間で変化する可能性がある（テスト対象）
- **コアライブラリ層**: バージョン間で変化する可能性がある（テスト対象）

直接実行により、テスト対象である「ツール実装層」と「コアライブラリ層」の変化を正確に検出できます。

### 7.3. テスト結果の信頼性

1. **ノイズの除去**
   - MCPプロトコルの実装差異による影響を排除
   - AIクライアントの状態による影響を排除

2. **再現性の確保**
   - 同一環境での実行結果が常に一致
   - 外部要因による変動を最小化

## 8. 制限事項と注意点

### 8.1. テスト範囲の制限

直接実行では以下の要素はテストされません。

1. **MCPプロトコル実装**
   - JSON-RPC通信の正確性
   - エラーハンドリングの適切性

2. **AIクライアント統合**
   - クライアント固有の動作
   - ユーザーインターフェース

### 8.2. 実際の使用環境との差異

実際のユーザーはMCPクライアント経由でツールを使用するため、以下の点で差異があります。

1. **実行環境**
   - プロセス分離の有無
   - リソース制限の違い

2. **エラー伝播**
   - プロトコル層でのエラー変換
   - タイムアウト処理の違い

### 8.3. 推奨される補完テスト

直接実行テストに加えて、以下のテストも推奨されます。

1. **統合テスト**
   - 実際のMCPクライアントを使用したテスト
   - エンドツーエンドの動作確認

2. **プロトコルテスト**
   - MCPサーバーの起動・停止テスト
   - 通信プロトコルの正確性テスト

## 9. 結論

### 9.1. 直接実行の妥当性

`run_compatibility_test.py` の直接実行アプローチは、以下の理由により互換性テストにおいて妥当で有効です。

1. **アーキテクチャの分離設計**: MCPツールクラスがMCPサーバーに依存しない独立したコンポーネントとして設計されている

2. **機能的等価性**: 直接実行とMCP経由実行が同一のコードパスを通り、同一の結果を生成する

3. **テスト目的との整合性**: バージョン間でのツール実装の差異を正確に検出できる

4. **実用性**: 自動化、デバッグ、CI/CD統合が容易

### 9.2. AIクライアント不要の理由

AIクライアントが不要な理由は以下の通りです。

1. **レイヤー分離**: テスト対象（ツール実装）とテスト手段（MCPプロトコル）が適切に分離されている

2. **依存関係の最小化**: ツールクラスがAIクライアントやMCPサーバーに依存していない

3. **テスト効率**: プロトコルオーバーヘッドを排除し、純粋な機能テストに集中できる

### 9.3. 今後の展望

この直接実行アプローチは、以下の発展が期待されます。

1. **テストカバレッジの拡大**: より多くのエッジケースやパフォーマンステストの追加

2. **自動化の強化**: CI/CDパイプラインでの継続的な互換性監視

3. **補完テストの統合**: MCPプロトコル層のテストとの組み合わせによる包括的な品質保証

---

**注記**: 本ドキュメントは、`tree-sitter-analyzer` v1.6.1.2 および v1.9.2 の実装に基づいて作成されています。将来のバージョンでアーキテクチャが変更された場合は、本ドキュメントの内容も更新される必要があります。

## スマート比較の技術的背景

スマート比較機能 (`smart_json_comparator.py`) は、JSONオブジェクト間の意味的な差分をインテリジェントに検出するために設計されています。単純なテキスト比較とは異なり、JSON構造の文脈を理解し、`comparison_config.json` に基づいて比較プロセスを正規化します。

### 主要な技術要素：

1.  **設定駆動型の正規化**:
    比較の前に、両方のJSONオブジェクトは設定ファイルに基づいて前処理されます。
    -   **フィールドの無視**: `ignore_fields` に指定されたキーは、比較前にオブジェクトから再帰的に削除されます。
    -   **配列のソート**: `sort_arrays_by` で指定されたキーを持つオブジェクトを含む配列は、そのキーの値に基づいてソートされます。これにより、要素の順序が異なっていても、内容が同じであれば差分として検出されません。`secondary_sort` は、プライマリキーが同じ場合の第二のソートキーを提供します。
    -   **順序の維持**: `preserve_array_order` にリストされたキーを持つ配列は、意図的にソートされず、元の順序が比較されます。

2.  **再帰的な比較ロジック**:
    正規化後、`deepdiff` ライブラリを使用して、2つのJSONオブジェクトが再帰的に比較されます。`ignore_order=True` オプションがデフォルトで有効になっており、オブジェクト内のキーの順序やセット内の要素の順序の違いを無視します。

3.  **正規化済み出力**:
    `--generate-normalized` フラグが使用されると、比較に使用された正規化済みのJSONオブジェクトが `.analysis-*-normalized/` ディレクトリに保存されます。これにより、比較ロジックがどのようにデータを解釈したかを正確に確認でき、デバッグと透明性が向上します。

このアプローチにより、開発者はバージョン間の本質的な変更点に集中でき、タイムスタンプやキャッシュヒットの有無といった非機能的な差異に起因するノイズを排除できます。
