感情王国
ブログ一覧に戻る

devcontainer内のClaude CodeからホストのUnity MCPへ接続する方法 - socatによるポート中継とセキュリティ考慮事項

Unity MCP(Model Context Protocol)サーバーをホストマシンで起動し、devcontainer内のClaude Codeから接続したい場合、いくつかの課題に直面します。この記事では、実際に遭遇した問題とその解決策を、再現可能な手順とともに解説します。

この記事の対象読者:

  • Unity + MCP for Unity を使って Claude Code と連携したい方
  • devcontainer環境でホストマシンのサービスに接続したい方
  • Dockerネットワークとポート中継について理解を深めたい方

背景と問題

アーキテクチャ

Unity MCP for Unity はホストマシン(macOS)で動作し、HTTP Server として 127.0.0.1:8080 でリッスンします。一方、Claude Code は devcontainer という隔離された Linux 環境で動作しています。

┌─────────────────────────────────────────────────┐
│ ホスト (macOS)                                   │
│  ┌─────────────────┐                            │
│  │ Unity Editor    │                            │
│  │ (MCP Server)    │                            │
│  │ 127.0.0.1:8080  │                            │
│  └─────────────────┘                            │
│           ▲                                      │
│           │                                      │
│  ┌────────┼──────────────────────────────┐     │
│  │ devcontainer                          │     │
│  │        │                               │     │
│  │  ┌─────┴─────────┐                    │     │
│  │  │ Claude Code   │                    │     │
│  │  │ (MCP Client)  │                    │     │
│  │  └───────────────┘                    │     │
│  └───────────────────────────────────────┘     │
└─────────────────────────────────────────────────┘

直面した課題

devcontainer内から localhost:8080 にアクセスしようとすると、コンテナ自身の 8080 ポートに接続しようとするため、ホストマシンの Unity MCP には到達できません。

Dockerには host.docker.internal という特殊なホスト名があり、これを使えばホストマシンにアクセスできますが、Unity MCP は 127.0.0.1 でのみリッスンしているため、外部から接続できません。

解決策の検討

方式1: Unity MCP を 0.0.0.0 でバインド

Unity MCP の設定を変更して、全インターフェース(0.0.0.0)でリッスンさせる方法です。

メリット:

  • 設定が簡単
  • 追加ツール不要

デメリット:

  • セキュリティリスク(同一ネットワーク全体に公開)
  • Unity MCP の設定変更が必要

方式2: socat によるポート中継(推奨)

ホストマシンで socat を使い、別のポート(8081)で受けたリクエストを Unity MCP の 127.0.0.1:8080 に中継する方法です。

メリット:

  • Unity MCP の設定変更不要
  • バインドアドレスを柔軟に選択可能
  • 一時的な接続として管理しやすい

デメリット:

  • socat のインストールが必要
  • ポート中継の理解が必要

この記事では、より柔軟で安全な方式2(socat) を採用します。

socatによるポート中継の実装

socatのインストール

macOSではHomebrewで簡単にインストールできます。

brew install socat

ポート中継スクリプトの作成

Unity MCP への接続を中継するスクリプトを作成しました。

.devcontainer/scripts/start-socat.sh:

#!/bin/bash
# Unity MCP用socat中継スクリプト(セキュア版)
# macOSのホスト側で実行

set -e

echo "======================================"
echo "Unity MCP socat Bridge (Secure)"
echo "======================================"

# 既存のsocatプロセスを停止
if pgrep -f "socat.*8081.*8080" > /dev/null; then
    echo "Stopping existing socat process..."
    pkill -f "socat.*8081.*8080" || true
    sleep 1
fi

# Unity MCPサーバーが起動しているか確認
if ! lsof -i :8080 -P -n | grep -q "python.*LISTEN"; then
    echo "⚠ Warning: Unity MCP server is not running on port 8080"
    echo ""
    echo "Please start Unity Editor and ensure MCP For Unity is active."
    exit 1
fi

# セキュアモード: localhostのみでバインド
BIND_ADDRESS="127.0.0.1"

echo ""
echo "Starting socat bridge..."
echo "  Bind address: ${BIND_ADDRESS}:8081"
echo "  Target: 127.0.0.1:8080 (Unity MCP)"
echo "  Mode: Secure (localhost only, Docker port forwarding)"
echo ""

# socatをバックグラウンドで起動
socat TCP-LISTEN:8081,bind=${BIND_ADDRESS},fork TCP:127.0.0.1:8080 > /tmp/socat-unity-mcp.log 2>&1 &
SOCAT_PID=$!

# 起動確認
sleep 1
if ps -p $SOCAT_PID > /dev/null; then
    echo "✓ socat started successfully (PID: $SOCAT_PID)"
    echo ""
    echo "To stop: pkill -f 'socat.*8081.*8080'"
    echo "View logs: tail -f /tmp/socat-unity-mcp.log"
else
    echo "✗ Failed to start socat"
    exit 1
fi

このスクリプトは以下の機能を持ちます:

  • 既存の socat プロセスを自動停止
  • Unity MCP の起動確認
  • 127.0.0.1:8081127.0.0.1:8080 のポート中継
  • エラーハンドリングとログ出力

スクリプトの実行

# ホストマシン(macOS)で実行
chmod +x .devcontainer/scripts/start-socat.sh
./.devcontainer/scripts/start-socat.sh

出力例:

======================================
Unity MCP socat Bridge (Secure)
======================================

Starting socat bridge...
  Bind address: 127.0.0.1:8081
  Target: 127.0.0.1:8080 (Unity MCP)
  Mode: Secure (localhost only, Docker port forwarding)

✓ socat started successfully (PID: 12345)

To stop: pkill -f 'socat.*8081.*8080'
View logs: tail -f /tmp/socat-unity-mcp.log

devcontainer側の設定

devcontainer.json の設定

devcontainerから socat経由でUnity MCPに接続するため、環境変数とポートフォワーディングを設定します。

.devcontainer/devcontainer.json:

{
  "name": "Unity MCP Development",
  "containerEnv": {
    "UNITY_HTTP_URL": "http://host.docker.internal:8081",
    "UNITY_MCP_API_KEY": "unity-mcp-dev-key"
  },
  "forwardPorts": [8081],
  "portsAttributes": {
    "8081": {
      "label": "Unity MCP Server (via socat)",
      "onAutoForward": "silent"
    }
  }
}

設定のポイント:

  • UNITY_HTTP_URL: ホストの 8081 ポートに接続(socat経由)
  • forwardPorts: Docker のポートフォワーディング機能を使用
  • host.docker.internal: Docker for Mac/Windows で提供される特殊ホスト名

MCP接続の設定

devcontainer内でClaude CodeにUnity MCPサーバーを登録します。

# devcontainer内で実行
claude mcp add --transport http -s local UnityMCP \
  "http://host.docker.internal:8081/mcp" \
  --header "Authorization: Bearer unity-mcp-dev-key"

接続確認とトラブルシューティング

SSE (Server-Sent Events) エラーについて

接続確認のため、curl で Unity MCP にアクセスしてみましょう。

# devcontainer内で実行
curl http://host.docker.internal:8081/mcp

すると、次のようなエラーが返ってきます:

{
  "jsonrpc": "2.0",
  "id": "server-error",
  "error": {
    "code": -32600,
    "message": "Not Acceptable: Client must accept text/event-stream"
  }
}

これは正常な応答です!

最初は接続エラーかと思いましたが、調査の結果、Unity MCP は SSE (Server-Sent Events) プロトコルを使用していることが判明しました。

SSEプロトコルとは

SSE は HTTP 上でサーバーからクライアントへの一方向ストリーミングを実現するプロトコルです。クライアントは Accept: text/event-stream ヘッダーを送信する必要があります。

通常の curl は Accept: */* を送信するため、Unity MCP が拒否します。これは接続が成功している証拠であり、以下を確認できています:

  1. host.docker.internal:8081 への到達成功
  2. ✅ socat によるポート中継が動作
  3. ✅ Unity MCP サーバーが正常に応答

Claude Code の MCP client は適切なヘッダーを送信するため、実際の使用では問題ありません。

正しいHTTPステータスコードの確認

SSEエラーのHTTPステータスコードを確認してみましょう。

curl -s -o /dev/null -w "%{http_code}" http://host.docker.internal:8081/mcp

期待される結果: 406(Not Acceptable)

これが返れば、接続は成功しています。

接続失敗のパターン

以下のエラーが出た場合は、それぞれ対処が必要です。

Connection refused:

curl: (7) Failed to connect to host.docker.internal port 8081: Connection refused

原因:

  • socat が起動していない
  • または Unity MCP サーバーが停止している

解決策:

# ホストマシンで socat を起動
./.devcontainer/scripts/start-socat.sh

# Unity Editor で MCP For Unity を起動

401 Unauthorized:

{"error": {"message": "Unauthorized"}}

原因: API Key の不一致

解決策:

  • Unity Editor の API Key 設定を確認
  • devcontainer 側の設定を再実行

Claude Code での動作確認

Claude Code のセッション内で、Unity MCP のツールが利用可能か確認します。

利用可能なツール一覧を確認してください

以下のような Unity MCP ツールが表示されれば成功です:

  • mcp__UnityMCP__manage_scene
  • mcp__UnityMCP__manage_gameobject
  • mcp__UnityMCP__manage_script

セキュリティ考慮事項

socat によるポート中継では、バインドアドレスの選択が重要です。

バインドアドレスの選択肢

1. 127.0.0.1(推奨)

socat TCP-LISTEN:8081,bind=127.0.0.1,fork TCP:127.0.0.1:8080

特徴:

  • localhost のみでリッスン
  • Docker のポートフォワーディング機能と組み合わせる
  • 最もセキュア

推奨理由:

  • 外部ネットワークから完全に隔離
  • Docker が内部的にポート接続を処理
  • 同一マシン内でのみ通信

2. 192.168.x.x(WiFiインターフェース)

socat TCP-LISTEN:8081,bind=192.168.1.100,fork TCP:127.0.0.1:8080

特徴:

  • WiFi 経由でのみアクセス可能
  • 同一ネットワーク内の他のデバイスからもアクセス可能

注意点:

  • DHCP でIPアドレスが変わる可能性がある
  • ファイアウォール設定が必要
  • 公共WiFiでは使用しない

3. 0.0.0.0(非推奨)

socat TCP-LISTEN:8081,bind=0.0.0.0,fork TCP:127.0.0.1:8080

特徴:

  • 全ネットワークインターフェースでリッスン
  • 同一ネットワーク全体に公開

リスク:

  • 最もセキュリティリスクが高い
  • 同一WiFi上の全デバイスからアクセス可能
  • API Key認証が必須

推奨事項

devcontainer + Unity MCP の用途では、127.0.0.1 バインド + Docker ポートフォワーディング を推奨します。

追加のセキュリティ対策:

  1. API Key設定必須

    • 推測困難な値を使用
    • 定期的に変更
  2. macOS ファイアウォール

    • システム設定からファイアウォールを有効化
    • 必要なアプリケーションのみ許可
  3. 使用時のみ起動

    • 作業終了後は socat を停止
    • pkill -f 'socat.*8081.*8080'
  4. 公共WiFi使用時

    • VPN 経由での接続を推奨
    • または一時的に接続を無効化

まとめ

devcontainer 内の Claude Code からホストマシンの Unity MCP へ接続するには、以下の手順を実施します。

実装手順の要約

  1. socat をインストール

    brew install socat
    
  2. ホストマシンで socat を起動

    ./.devcontainer/scripts/start-socat.sh
    
  3. devcontainer.json を設定

    • UNITY_HTTP_URLhttp://host.docker.internal:8081 に設定
    • forwardPorts で 8081 を指定
  4. Claude Code に MCP サーバーを登録

    claude mcp add --transport http -s local UnityMCP \
      "http://host.docker.internal:8081/mcp" \
      --header "Authorization: Bearer unity-mcp-dev-key"
    
  5. 接続確認

    • curl で HTTP 406 が返ることを確認
    • Claude Code でツールが表示されることを確認

重要なポイント

  • SSEエラーは正常: text/event-stream エラーは接続成功のサイン
  • セキュアなバインド: 127.0.0.1 でバインドし、Docker ポートフォワーディングを使用
  • API Key認証: セキュリティのため必ず設定
  • 一時的な中継: 使用時のみ socat を起動

トラブルシューティングのチェックリスト

接続できない場合は、以下を順番に確認してください。

  1. Unity MCP が起動しているか(lsof -i :8080
  2. socat が起動しているか(ps aux | grep socat
  3. devcontainer の環境変数が正しいか(echo $UNITY_HTTP_URL
  4. curl で HTTP 406 が返るか
  5. API Key が一致しているか

これらの手順により、devcontainer環境でもUnity MCPの機能をフルに活用できるようになります。socat によるポート中継は、他のローカルサービスへの接続にも応用できる汎用的な手法です。

参考リンク