# 機能設計書 48-コンポーネントファイル取得

## 概要

本ドキュメントは、MCPサーバーによる指定コンポーネントの.tsxファイル内容取得機能の設計について記載する。この機能は、Model Context Protocol（MCP）を使用した開発支援ツールとして、特定のUIコンポーネントのソースコードを取得するAPIを提供する。

### 本機能の処理概要

**業務上の目的・背景**：Liamアプリケーションは、`@liam-hq/ui`パッケージに多数のUIコンポーネントを持つ。開発者やAIアシスタントがコンポーネントの実装詳細を参照するために、特定コンポーネントの.tsxファイル内容を取得する機能が必要である。これにより、コンポーネントの使用方法やカスタマイズ方法を正確に把握できる。

**機能の利用シーン**：
- AIアシスタントがコンポーネントの実装を参照してコード生成する際
- 開発者がコンポーネントの実装詳細を確認する際
- コンポーネントの使用例やプロップスを理解する際

**主要な処理内容**：
1. MCPサーバーがツールリクエストを受信
2. componentNameパラメータを検証
3. パストラバーサル攻撃の検出と防止
4. コンポーネントディレクトリの存在確認
5. .tsxファイルの一覧取得
6. 各ファイルの内容を読み取り
7. ファイル名と内容を結合して返却

**関連システム・外部連携**：
- Model Context Protocol（MCP）
- @modelcontextprotocol/sdk
- Node.js fs/promises モジュール
- Zod（パラメータバリデーション）
- stdio トランスポート

**権限による制御**：MCPサーバーはローカル環境で実行され、ファイルシステムへの読み取りアクセス権限を持つ。パストラバーサル攻撃を防止するセキュリティチェックを実装。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面に直接関連しない開発支援ツール |

## 機能種別

開発支援ツール / API提供

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| componentName | string | Yes | 取得対象のコンポーネント名 | Zodでstring型検証、パストラバーサルチェック |

### 入力データソース

MCPクライアントからのツールリクエスト（stdioトランスポート経由）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| content | { type: 'text'; text: string }[] | .tsxファイル内容（ファイル名付き） |

### 出力先

MCPクライアントへのレスポンス

## 処理フロー

### 処理シーケンス

```
1. MCPクライアントからget_component_filesツールが呼び出される
2. componentNameパラメータを取得
3. コンポーネントディレクトリパスを構築
4. パストラバーサルチェック
   └─ resolvedPathがuiComponentsPath内か確認
5. ディレクトリ存在確認
   └─ fs.stat + isDirectory()
6. .tsxファイル一覧取得
   └─ fs.readdir + filter(*.tsx)
7. 各ファイルの内容を読み取り
   └─ Promise.all + fs.readFile
8. ファイル名と内容を結合
   └─ "=== filename ===" + content
9. 結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[get_component_files呼び出し] --> B[componentNameパラメータ取得]
    B --> C[パス構築]
    C --> D{パストラバーサル?}
    D -->|Yes| E[セキュリティエラー返却]
    D -->|No| F[fs.stat実行]
    F --> G{ディレクトリ存在?}
    G -->|No| H[コンポーネント不在エラー]
    G -->|Yes| I{isDirectory?}
    I -->|No| J[ディレクトリでないエラー]
    I -->|Yes| K[.tsxファイル一覧取得]
    K --> L{.tsxファイル存在?}
    L -->|No| M[ファイル不在エラー]
    L -->|Yes| N[ファイル内容読み取り]
    N --> O[結果を結合]
    O --> P[成功レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-48-01 | .tsxファイルのみ | .tsx拡張子のファイルのみを対象 | 常時 |
| BR-48-02 | パストラバーサル防止 | コンポーネントディレクトリ外へのアクセスを禁止 | 常時 |
| BR-48-03 | ファイル区切り形式 | "=== filename ===" でファイルを区切り | 常時 |
| BR-48-04 | UTF-8エンコーディング | ファイルはUTF-8として読み取り | 常時 |

### 計算ロジック

**パストラバーサルチェック**：
```typescript
const componentDir = path.join(uiComponentsPath, componentName)
const resolvedPath = path.resolve(componentDir)
if (!resolvedPath.startsWith(uiComponentsPath)) {
  return {
    content: [],
    isError: true,
    error: 'Security error: Path traversal attempt detected.',
  }
}
```

**ファイル内容フォーマット**：
```typescript
const fileContents = await Promise.all(
  tsxFiles.map(async (file) => {
    const content = await fs.readFile(path.join(componentDir, file), 'utf8')
    return `=== ${file} ===\n${content}`
  }),
)
return { content: [{ type: 'text', text: fileContents.join('\n\n') }] }
```

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | 本機能はデータベースを操作しない |

### テーブル別操作詳細

本機能はファイルシステムからの読み取りのみを行い、データベースは使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Security error | パストラバーサル検出 | 有効なコンポーネント名を指定 |
| - | Not a directory | 指定パスがディレクトリでない | 正しいコンポーネント名を確認 |
| ENOENT | Component not found | コンポーネントディレクトリが存在しない | コンポーネント名を確認 |
| - | No .tsx files | .tsxファイルが存在しない | コンポーネントディレクトリを確認 |
| - | ファイル読み取りエラー | ファイル読み取り失敗 | 権限を確認 |

### リトライ仕様

ファイルシステム操作は通常即座に完了するため、リトライは不要。

## トランザクション仕様

本機能はファイルシステム読み取りのみであり、トランザクション管理は不要。

## パフォーマンス要件

- ディレクトリ読み取り: 即時（ミリ秒単位）
- ファイル読み取り: ファイルサイズに依存（通常数百ミリ秒以内）
- 並列読み取り: Promise.allで効率化

## セキュリティ考慮事項

- **パストラバーサル防止**: resolvedPath.startsWith(uiComponentsPath)で検証
- ローカル環境でのみ実行
- 読み取り専用操作
- Zodによるパラメータバリデーション

## 備考

- MCPサーバー名: liam-development-mcp-server
- バージョン: 0.1.0
- ツール名: get_component_files
- stdioトランスポートを使用
- Zodでパラメータスキーマを定義

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: ツール定義を理解する

まず、get_component_filesツールの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.ts | `frontend/internal-packages/mcp-server/src/index.ts` | ツール定義とパラメータ |

**読解のコツ**:
- server.tool()の第3引数がZodスキーマによるパラメータ定義（63行目）
- componentNameパラメータはz.string()で定義

#### Step 2: セキュリティチェックを理解する

パストラバーサル防止の実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `frontend/internal-packages/mcp-server/src/index.ts` | セキュリティチェック |

**主要処理フロー**:
1. **65行目**: `path.join(uiComponentsPath, componentName)` でパス構築
2. **68行目**: `path.resolve(componentDir)` で絶対パス取得
3. **69行目**: `resolvedPath.startsWith(uiComponentsPath)` でパストラバーサル検出
4. **70-75行目**: 検出時のエラーレスポンス

#### Step 3: ファイル取得処理を理解する

.tsxファイルの取得と読み込みを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.ts | `frontend/internal-packages/mcp-server/src/index.ts` | ファイル取得処理 |

**主要処理フロー**:
- **78-86行目**: ディレクトリ存在確認（fs.stat + isDirectory）
- **89-90行目**: ディレクトリ内ファイル取得
- **91行目**: .tsxファイルフィルタリング
- **93-98行目**: .tsxファイル存在チェック
- **101-107行目**: ファイル内容読み取りとフォーマット
- **109行目**: 結果返却

#### Step 4: エラーハンドリングを理解する

各種エラーケースの処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.ts | `frontend/internal-packages/mcp-server/src/index.ts` | エラーハンドリング |

**主要処理フロー**:
- **112-124行目**: catch ブロック
- **114-117行目**: ENOENTエラー（コンポーネント不在）の検出
- **118-124行目**: その他エラーのハンドリング

### プログラム呼び出し階層図

```
MCPクライアント
    │
    └─ stdio トランスポート
           │
           └─ McpServer
                  │
                  └─ server.tool('get_component_files', { componentName }, ...)
                         │
                         ├─ path.join() + path.resolve()
                         │      └─ パストラバーサルチェック
                         │
                         ├─ fs.stat(componentDir)
                         │      └─ ディレクトリ存在確認
                         │
                         ├─ fs.readdir(componentDir)
                         │      └─ .tsx ファイルフィルタ
                         │
                         └─ Promise.all(fs.readFile(...))
                                └─ ファイル内容読み取り
```

### データフロー図

```
[入力]                      [処理]                          [出力]

                     ┌─────────────────────────┐
componentName ───────▶│   パス構築             │
                     │   path.join()          │
                     └──────────┬──────────────┘
                                │
                     ┌──────────▼──────────────┐
                     │   パストラバーサル      │
                     │   チェック              │
                     └──────────┬──────────────┘
                                │
                     ┌──────────▼──────────────┐
                     │   fs.stat              │
                     │   (存在・種別確認)      │
                     └──────────┬──────────────┘
                                │
                     ┌──────────▼──────────────┐
                     │   fs.readdir           │
                     │   filter(*.tsx)        │
                     └──────────┬──────────────┘
                                │
                     ┌──────────▼──────────────┐
                     │   Promise.all          │──────────▶ McpToolResult
                     │   fs.readFile          │            { content: [{
                     │   '=== file ===' format│              type: 'text',
                     └─────────────────────────┘              text: '=== Button.tsx ===\n...'
                                                            }] }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.ts | `frontend/internal-packages/mcp-server/src/index.ts` | ソース | MCPサーバーのメイン実装 |
| components/ | `frontend/packages/ui/src/components/` | 対象ディレクトリ | コンポーネント格納ディレクトリ |
