# 技術スタック評価
## 評価日
2025-11-06
## 背景
Search MCPの役割が**MCPアグリゲーター**として明確になったため、技術スタックを再評価する。
### プロジェクト要件
1. **stdio通信**: AIクライアントとJSON-RPC 2.0 over stdioで通信
2. **プロセス管理**: 複数のMCPサーバープロセスを起動・管理(child process spawn)
3. **JSON処理**: JSON-RPC 2.0のパース/シリアライズ
4. **軽量性**: メモリフットプリント最小化(コンテキスト削減が目的)
5. **信頼性**: プロセス監視、再起動、エラーハンドリング
6. **配布**: ユーザーが簡単にインストール・実行できる
7. **保守性**: 将来的な機能追加・変更が容易
### 非機能要件
- **パフォーマンス**: ツールリスト取得は高速(100ms以内)、プロキシのオーバーヘッド最小
- **エコシステム**: 既存MCP実装(ほぼNode.js)との親和性
- **開発効率**: 短期間でMVP実装が可能
---
## 候補技術スタック
### 1. Node.js + TypeScript(現状)
#### 長所
**プロセス管理**
- `child_process.spawn()` がネイティブでstdio管理に最適
- イベントドリブンでstdout/stderrのストリーム処理が自然
- 非同期I/O処理がデフォルト
**エコシステム**
- 既存のMCPサーバーのほぼ全てがNode.js実装
- 公式MCP SDK(`@modelcontextprotocol/sdk`)がTypeScriptで提供
- JSON処理がネイティブで高速
**開発効率**
- TypeScriptによる型安全性
- npmエコシステムの豊富なライブラリ
- 開発スピードが速い
**配布**
- `npx` で簡単にインストール可能
- `pkg` や `nexe` でバイナリ化も可能
- ユーザーはNode.jsランタイムのみで実行可能
#### 短所
**パフォーマンス**
- メモリフットプリント: 30-50MB(V8エンジン)
- 起動時間: 200-300ms
- シングルスレッド(ただし、I/Oバウンドなので問題になりにくい)
**ランタイム依存**
- Node.jsのインストールが必要(ただし、ターゲットユーザーはCLI開発者なので問題にならない可能性)
**セキュリティ**
- npm依存関係の脆弱性管理
#### 評価
| 項目 | スコア | コメント |
|------|--------|----------|
| stdio通信 | ⭐⭐⭐⭐⭐ | 最適。readline、stream処理が自然 |
| プロセス管理 | ⭐⭐⭐⭐⭐ | child_process APIが強力 |
| JSON処理 | ⭐⭐⭐⭐⭐ | ネイティブサポート |
| 軽量性 | ⭐⭐⭐ | 30-50MB、起動300ms |
| 配布 | ⭐⭐⭐⭐ | npxで簡単、バイナリ化可能 |
| エコシステム | ⭐⭐⭐⭐⭐ | MCP公式SDKあり |
| 開発効率 | ⭐⭐⭐⭐⭐ | 非常に高い |
**総合評価: 32/35**
---
### 2. Go
#### 長所
**パフォーマンス**
- メモリフットプリント: 10-20MB
- 起動時間: 50-100ms
- 並行処理(goroutine)が強力
**配布**
- シングルバイナリで配布可能
- クロスコンパイル容易
- ランタイム不要
**信頼性**
- 型安全性
- エラーハンドリングが明示的
- プロダクションレディ
#### 短所
**プロセス管理**
- `exec.Command` は使えるが、stdioの双方向通信がNode.jsより煩雑
- ストリーム処理のためのボイラープレートが多い
**エコシステム**
- MCP公式SDKなし(自前実装が必要)
- JSON-RPC 2.0ライブラリは存在するが、MCP特有の実装は必要
**開発効率**
- Node.jsと比較すると冗長(エラーハンドリング、構造体定義等)
- 依存管理はmodules(問題なし)
#### 評価
| 項目 | スコア | コメント |
|------|--------|----------|
| stdio通信 | ⭐⭐⭐⭐ | 可能だが、Node.jsより複雑 |
| プロセス管理 | ⭐⭐⭐⭐ | exec.Commandで可能 |
| JSON処理 | ⭐⭐⭐⭐ | encoding/json標準ライブラリ |
| 軽量性 | ⭐⭐⭐⭐⭐ | 10-20MB、起動高速 |
| 配布 | ⭐⭐⭐⭐⭐ | シングルバイナリ |
| エコシステム | ⭐⭐⭐ | MCP SDKなし |
| 開発効率 | ⭐⭐⭐ | Node.jsより時間かかる |
**総合評価: 28/35**
---
### 3. Rust
#### 長所
**パフォーマンス**
- メモリフットプリント: 5-15MB
- 起動時間: 10-50ms
- 最速、最小メモリ
**配布**
- シングルバイナリで配布可能
- クロスコンパイル可能
- ランタイム不要
**信頼性**
- メモリ安全性
- 型安全性が最強
- 並行処理の安全性
#### 短所
**プロセス管理**
- `std::process::Command` は使えるが、非同期stdio処理が複雑
- `tokio` による非同期処理の学習コストが高い
**エコシステム**
- MCP公式SDKなし(自前実装が必要)
- JSON-RPC 2.0ライブラリはあるが、統合が必要
**開発効率**
- 学習曲線が急
- コンパイル時間が長い
- 借用チェッカーとの戦い
- MVPまでの時間が最長
#### 評価
| 項目 | スコア | コメント |
|------|--------|----------|
| stdio通信 | ⭐⭐⭐ | tokioで可能だが複雑 |
| プロセス管理 | ⭐⭐⭐ | Command APIあり |
| JSON処理 | ⭐⭐⭐⭐ | serdeで高速 |
| 軽量性 | ⭐⭐⭐⭐⭐ | 最軽量 |
| 配布 | ⭐⭐⭐⭐⭐ | シングルバイナリ |
| エコシステム | ⭐⭐ | MCP SDKなし |
| 開発効率 | ⭐⭐ | 学習コスト高、時間かかる |
**総合評価: 24/35**
---
### 4. Python
#### 長所
**開発効率**
- 簡潔なコード
- 豊富なライブラリ
**エコシステム**
- MCP実装がいくつか存在
- JSON処理が簡単
#### 短所
**パフォーマンス**
- メモリフットプリント: 40-70MB
- 起動時間: 200-400ms
- Node.jsより遅い
**プロセス管理**
- `subprocess` モジュールは使えるが、非同期stdio処理が煩雑
- asyncioとの統合が必要
**配布**
- PyInstallerでバイナリ化可能だが、サイズが大きい(50MB+)
- Pythonインストールが必要
**型安全性**
- 型ヒントはあるが、TypeScriptほど強力ではない
#### 評価
| 項目 | スコア | コメント |
|------|--------|----------|
| stdio通信 | ⭐⭐⭐ | 可能だが、asyncioで複雑 |
| プロセス管理 | ⭐⭐⭐ | subprocessモジュール |
| JSON処理 | ⭐⭐⭐⭐⭐ | 標準ライブラリで簡単 |
| 軽量性 | ⭐⭐ | 40-70MB |
| 配布 | ⭐⭐⭐ | PyInstallerで可能 |
| エコシステム | ⭐⭐⭐ | MCP実装あり |
| 開発効率 | ⭐⭐⭐⭐ | 高い |
**総合評価: 23/35**
---
## 特殊候補
### 5. Deno
Node.jsの改良版として、TypeScriptネイティブサポート、セキュリティ強化。
**利点**: TypeScript標準、セキュアな実行環境、シングルバイナリ配布可能
**欠点**: MCP エコシステムが未成熟、npm互換性に問題の可能性
**評価: 27/35** - Node.jsと類似だが、エコシステムが未成熟
### 6. Bun
JavaScriptランタイムでNode.jsより高速。
**利点**: Node.jsより高速、TypeScript標準サポート
**欠点**: まだ新しい、本番環境での実績が少ない、MCP SDKの互換性未確認
**評価: 26/35** - 有望だが、安定性に不安
---
## 比較表
| 技術スタック | stdio通信 | プロセス管理 | JSON処理 | 軽量性 | 配布 | エコシステム | 開発効率 | 総合 |
|------------|----------|------------|---------|--------|------|------------|---------|------|
| Node.js + TypeScript | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | **32/35** |
| Go | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | 28/35 |
| Rust | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐ | 24/35 |
| Python | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | 23/35 |
| Deno | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐ | ⭐⭐⭐⭐ | 27/35 |
| Bun | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐ | 26/35 |
---
## 重要な考慮点
### 1. MCPエコシステムとの親和性
**現状**:
- 公式MCP SDK: `@modelcontextprotocol/sdk` (TypeScript/JavaScript)
- 既存MCPサーバー: ほぼ全てがNode.js/npx経由でインストール
- Claude Desktop設定: Node.js実行を前提
**影響**:
- Node.js以外を選択すると、公式SDKが使えず、MCPプロトコルを自前実装が必要
- コミュニティとのコード共有や相互運用性が低下
### 2. プロセス管理の複雑さ
**Search MCPの役割**:
- 複数の外部MCPサーバープロセスをspawn
- 各プロセスのstdin/stdoutを双方向で管理
- JSON-RPC 2.0メッセージのストリーミング処理
- プロセスのクラッシュ検出と再起動
**Node.jsの優位性**:
```javascript
const child = spawn('npx', ['-y', '@modelcontextprotocol/server-filesystem']);
child.stdout.on('data', handleStdout); // ストリーム処理が自然
child.stdin.write(JSON.stringify(request) + '\n'); // 簡潔
```
**Goの場合**:
```go
cmd := exec.Command("npx", "-y", "@modelcontextprotocol/server-filesystem")
stdout, _ := cmd.StdoutPipe()
stdin, _ := cmd.StdinPipe()
// Goroutineでストリーム処理、バッファ管理が必要
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
handleStdout(scanner.Text())
}
}()
```
→ Node.jsの方が自然でエラーが起きにくい
### 3. 開発スピードとMVP
**現状**: プロトタイプが既にNode.js/TypeScriptで存在
**技術スタック変更の影響**:
- Go: 2-3週間の再実装が必要
- Rust: 4-6週間の再実装が必要(学習コスト含む)
### 4. パフォーマンス要件の現実性
**実際のボトルネック**:
- Search MCP自体の処理時間: 1-5ms
- バックエンドMCPサーバーの応答時間: 10-1000ms(ファイルシステムアクセス、Web API呼び出し等)
→ Search MCPのオーバーヘッドは無視できるレベル
→ 軽量性よりも、開発効率とエコシステムの方が重要
---
## 推奨
### **推奨: Node.js + TypeScript(現状維持)**
#### 理由
1. **MCPエコシステムとの完全な親和性**
- 公式SDKがそのまま使える
- 既存のMCPサーバーとの統合が容易
- コミュニティのベストプラクティスを活用可能
2. **プロセス管理の最適性**
- stdio通信とストリーム処理が自然
- イベントドリブンモデルがMCPアグリゲーターに最適
- 複数プロセス管理のボイラープレートが最小
3. **開発効率とメンテナンス性**
- 既存のプロトタイプをベースに短期間で完成可能
- TypeScriptによる型安全性
- 豊富なnpmエコシステム
4. **配布の容易さ**
- `npx @your-org/search-mcp` で即座に実行可能
- ユーザー(CLI開発者)は既にNode.jsを持っている可能性が高い
- 必要ならば`pkg`でバイナリ化も可能
5. **パフォーマンスは十分**
- Search MCPのオーバーヘッド(30-50MB、300ms起動)は、バックエンドMCPサーバーの応答時間(数百ms〜数秒)と比較して無視できる
- I/Oバウンドな処理(stdio通信、JSON処理)にNode.jsは最適
#### 軽量性が問題になる場合の対策
もし将来的にメモリフットプリントが問題になる場合:
1. **Deno**への移行を検討(TypeScriptコードの大部分を再利用可能)
2. **Bun**への移行を検討(Node.js互換性が高い)
3. Goへの部分的な書き換え(ホットパスのみ)
---
## 代替案: Go(長期的な選択肢)
もし以下の条件が揃う場合、Goへの移行を検討する価値あり:
### 条件
1. **パフォーマンスが実際に問題になった**(現時点では問題ない)
2. **シングルバイナリ配布が強く求められる**(ユーザーがNode.jsを持っていない環境)
3. **開発チームにGo経験者がいる**
### Go選択時の注意点
- MCP SDKを自前実装が必要(2-3週間)
- 既存のNode.js実装を参考にできる
- メンテナンスコストが上がる
---
## 結論
**現時点では Node.js + TypeScript を継続すべき**
### 根拠
1. MCPエコシステムとの親和性が最重要
2. プロセス管理の容易さ
3. 開発効率(Time to Market)
4. パフォーマンスは十分(軽量性の犠牲は許容範囲)
5. 既存のプロトタイプを活用できる
### 今後の見直しタイミング
- ユーザーから「重い」というフィードバックが複数来た場合
- シングルバイナリ配布の要望が強い場合
- MCPエコシステムがNode.js以外に広がった場合
### アクション
1. Node.js + TypeScriptでMVP完成を優先
2. パフォーマンスモニタリングを実装
3. 将来的な移行を考慮した設計(インターフェース分離、モジュール化)