mcpField
M
MoodMNKY MCP Server Stack

MoodMNKY MCP Server Stack

ローカル
github.com/MOODMNKY-LLC開発ツール074 週間前に更新

MoodMNKY MCP Server Stack について

MoodMNKY MCP Server Stackは、複数のMCPサーバーをDocker Composeでまとめて実行・設定する構成です。MCPツールをOpenAI Agents SDKやSSE対応クライアントに接続する開発者向けで、Cloudflare Tunnelによる外部公開にも対応します。

主な機能

  1. 01Docker Composeで複数のMCPサーバーを管理
  2. 02単一の.envファイルでサービスを設定
  3. 03SSEエンドポイントでツールを検出・呼び出し
  4. 04Cloudflare Tunnel経由でサービスを公開
  5. 05OpenAI Agents SDKとの連携

活用シーン

  1. 01ローカルでMCPサービス群を実行
  2. 02SSE経由でOpenAI Agents SDKをMCPサーバーに接続
  3. 03トンネル経由でリモートクライアントにMCPエンドポイントを公開

MCP 対応

複数のMCPサーバーを実行し、SSEエンドポイントを通じてクライアントにツールを提供します。Cloudflare Tunnelを使ってリモートクライアントに公開する方法も説明されています。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

インストール方法は未掲載です

このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。

リポジトリ

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

MoodMNKY MCP サーバースタック

Docker で複数の MCP サーバーを実行、公開、統合するための第一原理に基づくガイドです。Server-Sent Events(SSE)を介して、OpenAI Agents SDK やその他のクライアントからシームレスにアクセスできるようにします。


目次

  1. はじめに

  2. MCP と SSE の第一原理

    1. MCP とは?
    2. SSE を使う理由
    3. ストリーミングと SSE トランスポート
  3. リポジトリ構成

  4. 前提条件

    1. Docker と Docker Compose
    2. Cloudflare Tunnel(Cloudflared)
    3. ドメインと DNS の設定
    4. OpenAI Agents SDK
  5. 環境変数

    1. .env.example
    2. .env の作成
    3. Filesystem MCP のデフォルトパス
  6. Docker Compose を使って始める

    1. リポジトリのクローン
    2. すべての MCP サーバーを起動
    3. ローカルの /tools エンドポイントを確認
  7. Cloudflare Tunnel を介して MCP サーバーを公開

    1. トンネルを使う理由
    2. cloudflared のインストールと認証
    3. トンネルと DNS ルートの作成
    4. Cloudflared の config.yml の例
    5. cloudflared をサービスとして起動
    6. 公開 SSE エンドポイントを確認
  8. OpenAI Agents SDK との統合

    1. Python コードの例
    2. MCPServerSse の設定
  9. SSE と Streamable HTTP:トレードオフ

  10. トラブルシューティングとベストプラクティス

    1. ヘルスチェック
    2. ポートの競合
    3. シークレットの保護
    4. Redis の永続化
    5. MCP バージョンの更新
  11. MCP スタックの拡張

  12. ライセンス


はじめに

MoodMNKY MCP サーバースタックは、多様な**Model Context Protocol(MCP)**サーバーを Docker コンテナーとして実行し、1 つの便利な docker-compose.yml の背後でオーケストレーションする、独立したリポジトリです。このスタックにより、次のことが可能になります。

  • Notion、Sequential Thinking、Brave Search、Tavily、Firecrawl、Fetch、GitHub、Supabase‐Dev、Context7、YouTube Transcript、Redis を使った Memory など、多数のツール提供型 MCP サーバーを迅速にデプロイできます。
  • ホストとポートのバインド、API キー、パスを含む単一の .env ファイルで一元的に設定できます。
  • OpenAI Agents SDK(SSE 経由)や、SSE に対応したその他のクライアントとすぐに統合できます。
  • Cloudflare Tunnel を使って、各 MCP エンドポイントをパブリックインターネット経由で公開できます(任意)。ファイアウォールの安全性を保ちながら、安全に外部アクセスを提供します。

この README は第一原理に基づくアプローチを採用しています。各手順の「方法」だけでなく、その背景にある「理由」も説明するため、MCP、SSE、Docker、Cloudflare Tunnel に詳しくない開発者でも、何が起きているのか、なぜ重要なのか、今後のニーズに合わせてどう応用すればよいのかを理解できます。


MCP と SSE の第一原理

MCP とは?
  • **MCP(Model Context Protocol)**は、AI エージェント(GPT‐4 を搭載したアシスタントなど)が外部の「ツール」サービスを呼び出せるようにする、オープンソースの仕様です。
  • 各 MCP サーバーは、HTTP エンドポイント(通常は /tools)を通じて、ツールのシグネチャ(名前、引数、説明)のセットを公開します。
  • エージェントがツールを「呼び出す」必要がある場合、/call に JSON エンコードされた POST リクエストを送信します。MCP サーバーはツールを実行し(例:ウェブページの取得、データベースへのクエリ、コードの実行)、結果をストリーミングで返します。

主なメリット:

  1. 関心の分離:エージェントは計画と推論に集中し、MCP サーバーは専門的なタスクを処理します。
  2. 言語に依存しないツール:MCP サーバーは MCP 仕様に準拠していれば、任意の言語(Node、Python、Go など)で記述できます。
  3. 拡張性:スタックに新しい MCP サーバーを追加するだけで、新しいツールを追加できます。エージェントは実行時にそれらを検出します。

なぜ SSE なのか?
  • **SSE(Server‐Sent Events)**は HTTP ベースの一方向ストリーミングプロトコルで、サーバーが永続的な接続を通じてクライアントに JSON イベントをプッシュできます。

  • MCP のコンテキストでは、SSE は次の 2 つのフェーズで使用されます。

    1. ツールの検出(LIST):エージェントは http://<mcp-url>/tools に GET リクエストを送信し、利用可能な各ツールを説明する JSON が送られてくる SSE ストリームを受信します。
    2. ツールの呼び出し(CALL):エージェントは JSON 引数を含む POST リクエストを http://<mcp-url>/call に送信します。MCP サーバーはリクエストを処理し、既存の SSE 接続を通じて結果をストリーミングで返します。

WebSocket やポーリングではなく SSE を使う理由

  • シンプルさ:SSE は通常の HTTP を基盤としているため、特別な設定をしなくても、ほとんどのプロキシ、ファイアウォール、ロードバランサーを通過できます。
  • 自動再接続:ネイティブの再接続セマンティクスにより、一時的なネットワーク障害に対応できます。
  • 低オーバーヘッド:WebSocket のハンドシェイクやプロトコルのフレーミングは不要で、テキストベースのイベントだけを使用します。
  • 一方向通信:エージェントは通常の HTTP を使ってツールの呼び出しを送信します。SSE はストリーミング結果の受信にのみ使用され、MCP のモデルに適しています。

ストリーミングと SSE トランスポート
  • SSE の代わりに、独立した「ストリーミング可能な HTTP」トランスポート(チャンク転送エンコーディング)を実装している MCP サーバーもあります。

  • SSE(ここでは推奨):

    • 標準化されたイベント形式(data: { ... })を使用します。
    • 再接続機能を内蔵しています。
    • ほとんどの HTTP/2 対応環境で動作します。
  • ストリーミング/チャンク化 HTTP:

    • 極めて軽量なサーバーでは、よりシンプルに実装できます。
    • 「イベント」のフレーミング機能を内蔵していないため、クライアントがチャンクを手動で解析する必要があります。
  • 推奨:非常に明確な理由がない限り、SSE を使用してください。このスタックのすべての MCP リファレンスサーバーはデフォルトで SSE を使用し、動作を統一しています。


リポジトリの構成

moodmnky-mcp-server-stack/
├── README.md
├── docker-compose.yml    # Orchestrates all MCP services
└── .env.example          # Template for environment variables
  • README.md:(このファイル)セットアップ、使用方法、基本的な設計思想、チュートリアルについて説明します。
  • docker-compose.yml:18 個のサービス(MCP サーバーと Redis)を定義します。それぞれがシークレット、ホスト側のポートバインディング、またはパス用の環境変数を参照します。
  • .env.example:<PLACEHOLDER> 値として、必要な変数をすべて記載しています。.env にコピーしてプレースホルダーを実際の値に置き換えてください。実際の .env は決してコミットしないでください。

前提条件

Docker と Docker Compose
  • ホストマシン(Linux、macOS、または Windows)に Docker Engine(20.10 以降)と Docker Compose(v2 以降)がインストールされていること。

  • インストールを確認します。

    docker --version
    docker-compose --version
    
Cloudflare Tunnel(Cloudflared)
  • MCP サーバーをインターネットに公開する予定がある場合(例:リモートでホストされているエージェントからアクセスする場合)、同じホストに Cloudflare の cloudflared をインストールしてください。

    1. お使いの OS に対応する最新リリースを、Cloudflare Tunnel のドキュメントからダウンロードします。

    2. インストールします(例:Ubuntu の場合)。

      curl -LO https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
      sudo dpkg -i cloudflared-linux-amd64.deb
      
    3. 確認します。

      cloudflared version
      
ドメインと DNS の設定
  • Cloudflare で管理している登録済みドメイン(例:example.com)が必要です。
  • 外部に公開する MCP サーバーごとに、Cloudflare の DNS ダッシュボードで、トンネルによって自動的に割り当てられたホスト名(例:mcp-tunnel.cfargotunnel.com)を指す CNAME レコードを作成します。
OpenAI Agents SDK
  • これらの MCP サーバーを統合するには、OpenAI Agents SDK がインストールされた Python 環境が必要です。

    pip install openai-agents
    
  • エージェントはコード内で、MCPServerSse を使って MCP エンドポイント(SSE)を参照します。


環境変数

.env.example

以下は、プレースホルダー値を含む .env.example ファイルの全内容です。.env という名前のファイルはコミットしないでください。代わりに、このファイルを .env にコピーし、すべてのプレースホルダー(<...>)を実際のキー、ホストポート、パスに置き換えてください。

###############################################
# Rename this to ".env" and fill in your values
###############################################

###############################################
# 1. Notion MCP Server
###############################################
NOTION_MCP_HEADERS={"Authorization":"Bearer <YOUR_NOTION_PAT>","Notion-Version":"2022-06-28"}
NOTION_HOST_PORT=<YOUR_NOTION_HOST_PORT>  # e.g., 8100

###############################################
# 2. 21st-Dev Magic MCP Server
###############################################
MAGIC_API_KEY=<YOUR_MAGIC_API_KEY>
MAGIC_HOST_PORT=<YOUR_MAGIC_HOST_PORT>    # e.g., 8101

###############################################
# 3. Filesystem MCP Server
###############################################
FILESYSTEM_HOST_PATH=<ABSOLUTE_PATH_TO_SHARE>   # e.g., /home/ubuntu/new-wave-protocol
FILESYSTEM_HOST_PORT=<YOUR_FILESYSTEM_HOST_PORT> # e.g., 8102

###############################################
# 4. Discord MCP Server
###############################################
DISCORD_TOKEN=<YOUR_DISCORD_TOKEN>
DISCORD_BOT_PERMISSIONS=<YOUR_DISCORD_BOT_PERMISSIONS>
DISCORD_HOST_PORT=<YOUR_DISCORD_HOST_PORT>      # e.g., 8103

###############################################
# 5. Sequential Thinking MCP Server
###############################################
SEQUENTIAL_THINKING_HOST_PORT=<YOUR_SEQUENTIAL_THINKING_HOST_PORT>  # e.g., 8104

###############################################
# 6. Brave Search MCP Server
###############################################
BRAVE_API_KEY=<YOUR_BRAVE_API_KEY>
BRAVE_SEARCH_HOST_PORT=<YOUR_BRAVE_SEARCH_HOST_PORT>  # e.g., 8105

###############################################
# 7. Tavily Search MCP Server
###############################################
TAVILY_API_KEY=<YOUR_TAVILY_API_KEY>
TAVILY_HOST_PORT=<YOUR_TAVILY_HOST_PORT>  # e.g., 8106

###############################################
# 8. Firecrawl MCP Server
###############################################
FIRECRAWL_API_URL=<YOUR_FIRECRAWL_API_URL>                 # e.g., https://api.firecrawl.dev/v1
FIRECRAWL_RETRY_MAX_ATTEMPTS=<YOUR_FIRECRAWL_RETRY_MAX_ATTEMPTS>       # e.g., 5
FIRECRAWL_RETRY_INITIAL_DELAY=<YOUR_FIRECRAWL_RETRY_INITIAL_DELAY>     # e.g., 2000
FIRECRAWL_RETRY_MAX_DELAY=<YOUR_FIRECRAWL_RETRY_MAX_DELAY>             # e.g., 30000
FIRECRAWL_RETRY_BACKOFF_FACTOR=<YOUR_FIRECRAWL_RETRY_BACKOFF_FACTOR>   # e.g., 3
FIRECRAWL_CREDIT_WARNING_THRESHOLD=<YOUR_FIRECRAWL_CREDIT_WARNING_THRESHOLD>  # e.g., 2000
FIRECRAWL_CREDIT_CRITICAL_THRESHOLD=<YOUR_FIRECRAWL_CREDIT_CRITICAL_THRESHOLD> # e.g., 500
FIRECRAWL_API_KEY=<YOUR_FIRECRAWL_API_KEY>
FIRECRAWL_HOST_PORT=<YOUR_FIRECRAWL_HOST_PORT>  # e.g., 8107

###############################################
# 9. Fetch MCP Server
###############################################
FETCH_HOST_PORT=<YOUR_FETCH_HOST_PORT>    # e.g., 8108

###############################################
# 10. Playwright MCP Server
###############################################
PLAYWRIGHT_HOST_PORT=<YOUR_PLAYWRIGHT_HOST_PORT>  # e.g., 8109

###############################################
# 11. GitHub MCP Server
###############################################
GITHUB_PERSONAL_ACCESS_TOKEN=<YOUR_GITHUB_PERSONAL_ACCESS_TOKEN>
GITHUB_HOST_PORT=<YOUR_GITHUB_HOST_PORT>  # e.g., 8110

###############################################
# 12. Desktop Commander MCP Server
###############################################
DESKTOP_COMMANDER_HOST_PORT=<YOUR_DESKTOP_COMMANDER_HOST_PORT>  # e.g., 8111

###############################################
# 13. Supabase-Dev (Postgres MCP) Server
###############################################
SUPABASE_DEV_CONN=<YOUR_SUPABASE_DEV_CONNECTION_URL>  # e.g., postgresql://postgres:[email protected]:54322/postgres
SUPABASE_DEV_HOST_PORT=<YOUR_SUPABASE_DEV_HOST_PORT>  # e.g., 8112

###############################################
# 14. Context7 MCP Server
###############################################
CONTEXT7_HOST_PORT=<YOUR_CONTEXT7_HOST_PORT>  # e.g., 8113

###############################################
# 15. YouTube Transcript MCP Server
###############################################
YOUTUBE_TRANSCRIPT_HOST_PORT=<YOUR_YOUTUBE_TRANSCRIPT_HOST_PORT>  # e.g., 8114

###############################################
# 16. Redis (for Memory MCP)
###############################################
REDIS_HOST_PORT=<YOUR_REDIS_HOST_PORT>  # e.g., 6379

###############################################
# 17. Memory MCP Server
###############################################
MEMORY_HOST_PORT=<YOUR_MEMORY_HOST_PORT>  # e.g., 8115

###############################################
# 18. @magicuidesign/mcp MCP Server
###############################################
MAGICUIDESIGN_HOST_PORT=<YOUR_MAGICUIDESIGN_HOST_PORT>  # e.g., 8116

注:実際の .env に設定する「本番環境対応」の値は、次のものだけです。

  • API キーとトークン(Notion PAT、Brave、Tavily、Firecrawl、GitHub、Discord など)。
  • FILESYSTEM_HOST_PATH の絶対パス(例:/home/moodmnky/new-wave-protocol)。
  • ホストポートは任意ですが、マシン上の他のサービスと競合しないようにしてください。

Docker Compose での始め方

1. リポジトリをクローンする
git clone https://github.com/<your-org>/moodmnky-mcp-server-stack.git
cd moodmnky-mcp-server-stack
2. .env をコピーして編集する
cp .env.example .env
notepad .env
  • 各 <PLACEHOLDER> を実際の値(API キー、ホストポート、パス)に置き換えてください。
  • ほかのすべての行はそのままにし、作成した .env を Git にコミットしないでください。
3. すべての MCP サーバーを起動する
docker-compose up -d
  • Docker Compose は次の処理を行います。

    1. 各イメージ(例:mcp/notion:latest、node:18-alpine、redis:7-alpine)をプルします。
    2. 18 個のコンテナを作成して起動し、各コンテナのポートを .env で設定したホストポートに割り当てます。
    3. ホストのディレクトリを /mnt/shared にマウントし、filesystem コンテナで使用できるようにします。
4. ローカルの /tools エンドポイントを確認する

新しい PowerShell ウィンドウまたはタブを開き、各サービスに対して SSE 形式の curl を実行します。

# Notion MCP
curl.exe -N http://localhost:8100/tools

# Magic MCP
curl.exe -N http://localhost:8101/tools

# Filesystem MCP
curl.exe -N http://localhost:8102/tools

# Discord MCP
curl.exe -N http://localhost:8103/tools

# Sequential Thinking MCP
curl.exe -N http://localhost:8104/tools

# Brave Search MCP
curl.exe -N http://localhost:8105/tools

# Tavily MCP
curl.exe -N http://localhost:8106/tools

# Firecrawl MCP
curl.exe -N http://localhost:8107/tools

# Fetch MCP
curl.exe -N http://localhost:8108/tools

# Playwright MCP
curl.exe -N http://localhost:8109/tools

# GitHub MCP
curl.exe -N http://localhost:8110/tools

# Desktop Commander MCP
curl.exe -N http://localhost:8111/tools

# Supabase-Dev (Postgres MCP)
curl.exe -N http://localhost:8112/tools

# Context7 MCP
curl.exe -N http://localhost:8113/tools

# YouTube Transcript MCP
curl.exe -N http://localhost:8114/tools

# Memory MCP (requires Redis)
curl.exe -N http://localhost:8115/tools

# @magicuidesign/mcp
curl.exe -N http://localhost:8116/tools

成功すると、各ツール(名前、引数、説明)を記述した JSON オブジェクトが流れる 無限の SSE ストリームが返されます。接続がすぐに切れる場合は、ホストポートが一致していることと、コンテナが起動していることを再確認してください。


Cloudflare Tunnel による MCP サーバーの公開

ローカルネットワークの外部から MCP エンドポイントにアクセスできるようにしつつ、ファイアウォールを閉じたままにするには、**Cloudflare Tunnel(cloudflared)**を使用できます。このセクションでは、一般的な「サービスごとにトンネルを作成する」構成について説明します。

トンネルを使用する理由
  • インバウンドポートを開放しない:生の TCP/UDP を外部に公開する必要はありません。TLS と接続の維持は Cloudflare が処理します。
  • TLS 終端:Cloudflare がドメインやサブドメイン用の証明書を提供します。
  • 自動再接続:トンネルが切断されても、cloudflared が自動的に再接続します。
  • アクセス制御:必要に応じて Zero Trust と統合し、MCP サービスへのアクセスを制限できます。
1. cloudflared のインストールと認証
  1. ダウンロードしてインストール(Ubuntu Linux の例):

    wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
    sudo dpkg -i cloudflared-linux-amd64.deb
    
  2. ログイン(認証のためにブラウザーのタブが開きます):

    cloudflared tunnel login
    
    • Cloudflare アカウントを選択し、DNS レコードを作成するドメイン(例:mcp.example.com)を選択します。
    • この手順により、ホスト上に ~/.cloudflared/cert.pem ファイルが作成されます。
2. 名前付きトンネルを作成する
cloudflared tunnel create mcp-tunnel
  • これにより Tunnel ID(例:abcd1234-ef56-7890-ghij-klmnopqrstuv)が出力されます。
  • 認証情報ファイル(例:~/.cloudflared/abcd1234-ef56-7890-ghij-klmnopqrstuv.json)が自動的に作成されます。
3. DNS ルートを設定する

各 MCP サービスについて、<tunnel_id>.cfargotunnel.com を指す Cloudflare DNS CNAME レコードを作成します。サブドメインの例:

MCP サービスローカルポート希望するサブドメイン
Notion MCP8100notion-mcp.example.com
Magic MCP8101magic-mcp.example.com
Filesystem MCP8102filesystem-mcp.example.com
Discord MCP8103discord-mcp.example.com
Sequential Thinking MCP8104sequential-mcp.example.com
Brave Search MCP8105brave-mcp.example.com
Tavily MCP8106tavily-mcp.example.com
Firecrawl MCP8107firecrawl-mcp.example.com
Fetch MCP8108fetch-mcp.example.com
Playwright MCP8109playwright-mcp.example.com
GitHub MCP8110github-mcp.example.com
Desktop Commander MCP8111desktop-mcp.example.com
Supabase-Dev (Postgres MCP)8112supabase-mcp.example.com
Context7 MCP8113context7-mcp.example.com
YouTube Transcript MCP8114yt-transcript-mcp.example.com
Memory MCP8115memory-mcp.example.com
@magicuidesign/mcp8116magicuidesign-mcp.example.com

次のコマンドを実行します(<tunnel-id> を実際の Tunnel ID に置き換え、各サブドメインも適宜置き換えてください)。

cloudflared tunnel route dns mcp-tunnel notion-mcp.example.com
cloudflared tunnel route dns mcp-tunnel magic-mcp.example.com
cloudflared tunnel route dns mcp-tunnel filesystem-mcp.example.com
cloudflared tunnel route dns mcp-tunnel discord-mcp.example.com
cloudflared tunnel route dns mcp-tunnel sequential-mcp.example.com
cloudflared tunnel route dns mcp-tunnel brave-mcp.example.com
cloudflared tunnel route dns mcp-tunnel tavily-mcp.example.com
cloudflared tunnel route dns mcp-tunnel firecrawl-mcp.example.com
cloudflared tunnel route dns mcp-tunnel fetch-mcp.example.com
cloudflared tunnel route dns mcp-tunnel playwright-mcp.example.com
cloudflared tunnel route dns mcp-tunnel github-mcp.example.com
cloudflared tunnel route dns mcp-tunnel desktop-mcp.example.com
cloudflared tunnel route dns mcp-tunnel supabase-mcp.example.com
cloudflared tunnel route dns mcp-tunnel context7-mcp.example.com
cloudflared tunnel route dns mcp-tunnel yt-transcript-mcp.example.com
cloudflared tunnel route dns mcp-tunnel memory-mcp.example.com
cloudflared tunnel route dns mcp-tunnel magicuidesign-mcp.example.com

注:最初に Cloudflare のダッシュボード(DNS → Add record → Type “CNAME” → Name = subdomain → target = <tunnel-id>.cfargotunnel.com)で、対応する CNAME レコードを作成する必要があります。または、route dns コマンドを実行すると、Cloudflare が自動的に作成する場合があります。

4. cloudflared の設定を作成する

~/.cloudflared/config.yml にファイルを作成し、次の内容を記述します。<tunnel-id> を実際の Tunnel ID に置き換え、hostname の項目を選択したサブドメインに合わせて調整してください。

tunnel: <tunnel-id>
credentials-file: /home/<your-username>/.cloudflared/<tunnel-id>.json

ingress:
  - hostname: notion-mcp.example.com
    service: http://localhost:8100

  - hostname: magic-mcp.example.com
    service: http://localhost:8101

  - hostname: filesystem-mcp.example.com
    service: http://localhost:8102

  - hostname: discord-mcp.example.com
    service: http://localhost:8103

  - hostname: sequential-mcp.example.com
    service: http://localhost:8104

  - hostname: brave-mcp.example.com
    service: http://localhost:8105

  - hostname: tavily-mcp.example.com
    service: http://localhost:8106

  - hostname: firecrawl-mcp.example.com
    service: http://localhost:8107

  - hostname: fetch-mcp.example.com
    service: http://localhost:8108

  - hostname: playwright-mcp.example.com
    service: http://localhost:8109

  - hostname: github-mcp.example.com
    service: http://localhost:8110

  - hostname: desktop-mcp.example.com
    service: http://localhost:8111

  - hostname: supabase-mcp.example.com
    service: http://localhost:8112

  - hostname: context7-mcp.example.com
    service: http://localhost:8113

  - hostname: yt-transcript-mcp.example.com
    service: http://localhost:8114

  - hostname: memory-mcp.example.com
    service: http://localhost:8115

  - hostname: magicuidesign-mcp.example.com
    service: http://localhost:8116

  # Fallback for any unmatched request
  - service: http_status:404
5. cloudflared をシステムサービスとして実行する
Linux の場合(Ubuntu の例)
  1. システムの systemd ユニットファイルを作成します。保存先は /etc/systemd/system/cloudflared.service です。

    sudo tee /etc/systemd/system/cloudflared.service > /dev/null << 'EOF'
    [Unit]
    Description=Cloudflare Tunnel
    After=network.target
    
    [Service]
    Type=notify
    ExecStart=/usr/local/bin/cloudflared tunnel --config /home/<your-username>/.cloudflared/config.yml run
    Restart=on-failure
    RestartSec=5s
    
    [Install]
    WantedBy=multi-user.target
    EOF
    
  2. systemd を再読み込みし、サービスを有効化して起動します。

    sudo systemctl daemon-reload
    sudo systemctl enable cloudflared
    sudo systemctl start cloudflared
    sudo systemctl status cloudflared
    
  3. サービスが “active (running)” になっていることを確認します。そうなっていれば、Cloudflare Tunnel がパブリックなサブドメインから localhost への転送を開始しています。


OpenAI Agents SDK との統合

MCP サーバーがローカルで稼働したら(必要に応じて Cloudflare Tunnel 経由で公開したら)、MCPServerSse を使用して OpenAI Agent を接続できます。次の Python コード例では、複数の MCP エンドポイントを接続する方法を示します。

import os
import asyncio
from agents import Agent, Runner
from agents.mcp.server import MCPServerSse

# 1. Read MCP SSE URLs (either localhost or public via Cloudflare)
NOTION_MCP_URL       = os.getenv("NOTION_SSE_URL", "http://localhost:8100")
MAGIC_MCP_URL        = os.getenv("MAGIC_SSE_URL",  "http://localhost:8101")
FILESYSTEM_MCP_URL   = os.getenv("FILESYSTEM_SSE_URL", "http://localhost:8102")
DISCORD_MCP_URL      = os.getenv("DISCORD_SSE_URL", "http://localhost:8103")
SEQUENTIAL_MCP_URL   = os.getenv("SEQUENTIAL_SSE_URL", "http://localhost:8104")
BRAVE_MCP_URL        = os.getenv("BRAVE_SSE_URL", "http://localhost:8105")
TAVILY_MCP_URL       = os.getenv("TAVILY_SSE_URL", "http://localhost:8106")
FIRECRAWL_MCP_URL    = os.getenv("FIRECRAWL_SSE_URL", "http://localhost:8107")
FETCH_MCP_URL        = os.getenv("FETCH_SSE_URL", "http://localhost:8108")
PLAYWRIGHT_MCP_URL   = os.getenv("PLAYWRIGHT_SSE_URL", "http://localhost:8109")
GITHUB_MCP_URL       = os.getenv("GITHUB_SSE_URL", "http://localhost:8110")
DESKTOP_MCP_URL      = os.getenv("DESKTOP_SSE_URL", "http://localhost:8111")
SUPABASE_MCP_URL     = os.getenv("SUPABASE_SSE_URL", "http://localhost:8112")
CONTEXT7_MCP_URL     = os.getenv("CONTEXT7_SSE_URL", "http://localhost:8113")
YOUTUBE_MCP_URL      = os.getenv("YOUTUBE_SSE_URL", "http://localhost:8114")
MEMORY_MCP_URL       = os.getenv("MEMORY_SSE_URL", "http://localhost:8115")
MAGICUIDESIGN_MCP_URL= os.getenv("MAGICUIDESIGN_SSE_URL", "http://localhost:8116")

def make_sse_server(url: str, name: str):
    return MCPServerSse(params={"url": url}, name=name)

async def main():
    # 2. Instantiate MCP servers
    mcp_servers = [
        make_sse_server(NOTION_MCP_URL,       "NotionMCP"),
        make_sse_server(MAGIC_MCP_URL,        "MagicMCP"),
        make_sse_server(FILESYSTEM_MCP_URL,   "FileMCP"),
        make_sse_server(DISCORD_MCP_URL,      "DiscordMCP"),
        make_sse_server(SEQUENTIAL_MCP_URL,   "SequentialMCP"),
        make_sse_server(BRAVE_MCP_URL,        "BraveMCP"),
        make_sse_server(TAVILY_MCP_URL,       "TavilyMCP"),
        make_sse_server(FIRECRAWL_MCP_URL,    "FirecrawlMCP"),
        make_sse_server(FETCH_MCP_URL,        "FetchMCP"),
        make_sse_server(PLAYWRIGHT_MCP_URL,   "PlaywrightMCP"),
        make_sse_server(GITHUB_MCP_URL,       "GitHubMCP"),
        make_sse_server(DESKTOP_MCP_URL,      "DesktopMCP"),
        make_sse_server(SUPABASE_MCP_URL,     "SupabaseMCP"),
        make_sse_server(CONTEXT7_MCP_URL,     "Context7MCP"),
        make_sse_server(YOUTUBE_MCP_URL,      "YouTubeMCP"),
        make_sse_server(MEMORY_MCP_URL,       "MemoryMCP"),
        make_sse_server(MAGICUIDESIGN_MCP_URL,"MagicUIDesignMCP"),
    ]

    # 3. Build an Agent with multiple tool sources
    agent = Agent(
        name="MoodMNKYUnifiedAgent",
        instructions=(
            "You have access to multiple MCP servers over SSE. "
            "Use NotionMCP to query Notion data, FileMCP to read files, "
            "MemoryMCP to store/retrieve memory, etc."
        ),
        tools=[],           # No built-in local tools
        mcp_servers=mcp_servers
    )

    # 4. Run a simple example prompt
    runner = Runner(agent)
    response = await runner.complete(
        "List all Notion pages, then fetch the contents of README.md from the filesystem."
    )
    print(response)

if __name__ == "__main__":
    asyncio.run(main())
  • 環境変数:各 *_SSE_URL の値を、Cloudflare Tunnel 経由の URL(例:https://notion-mcp.example.com)に変更できます。
  • MCPServerSse:内部では、MCPServerSse.connect() が http://<url>/tools への永続的な HTTP GET を開始し、JSON ストリームを解析して各ツールを公開します。エージェントが CALL <tool> を実行すると、SDK が http://<url>/call に POST リクエストを送信し、サーバーが結果をストリーミングで返します。

SSE と Streamable HTTP:トレードオフ

  1. SSE(Server-Sent Events)

    • プロトコル:HTTP GET で /tools にアクセスすると、text/event-stream 形式で data: { ... } イベントの連続ストリームが返されます。

    • メリット:

      • 自動再接続の仕組みが標準で備わっています。
      • HTTP/2 や、ほとんどのプロキシ/ロードバランサー経由で動作します。
      • 「イベント」の区切りが明確です。
    • デメリット:

      • サーバーからクライアントへの通信に限られます。エージェントはツール呼び出しの送信に通常の POST を使用する必要があります。
  2. Streamable HTTP(チャンク化レスポンス)

    • プロトコル:クライアントが GET または POST を送信し、サーバーがチャンク転送エンコーディングを使用して応答します(明示的な event: による区切りはありません)。

    • メリット:

      • 言語によっては、実装がやや簡単です。
    • デメリット:

      • クライアントが生のチャンクを手動で解析する必要があります。
      • 「再接続」の仕組みは標準で備わっていません。

ほとんどの MCP サーバーで SSE が推奨される理由:

  • 参照実装で統一された、十分に文書化された形式です。
  • 中断後の再接続を自動的に処理します。
  • エージェント SDK(例:OpenAI Agents SDK)は SSE をネイティブにサポートしています(MCPServerSse 経由)。

トラブルシューティングとベストプラクティス

1. ヘルスチェック

各サービスにヘルスチェックを追加して、docker-compose.yml 内の /tools がステータス 200 を返すこと(SSE ハンドシェイクが成功すること)を確認します。例:

services:
  new-wave-protocol-notion:
    # … existing config …
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:${NOTION_HOST_PORT}/tools"]
      interval: 30s
      timeout: 5s
      retries: 3

ほかの重要なサービスについても同様に設定します。


2. ポートの競合
  • .env 内の ${*_HOST_PORT} がすべて一意であり、ほかのローカルサービスで使用されていないことを確認します。
  • ポートを割り当てる前に、ss -tulpn(Linux)または netstat -anb(Windows)を使用して、ポートが利用可能か確認します。

3. シークレットの保護
  • 実際の .env ファイルは決してコミットしないでください。.gitignore(提供済み)に追加します。

  • 本番環境では、次の方法を検討してください。

    • Docker Secrets:API キーは平文ではなく、Docker のシークレット管理に保存します。
    • Vault ソリューション:実行時に動的に注入するには、HashiCorp Vault、AWS Secrets Manager、Azure Key Vault を使用します。

4. Redis の永続化
  • redis サービスは、データの永続化に名前付きボリューム redis-data を使用します。バックアップまたは移行するには、次の手順に従います。

    • バックアップ:docker run --rm -v redis-data:/data -v $(pwd):/backup alpine:latest sh -c "cd /data && tar czf /backup/redis-backup.tar.gz ."
    • 復元:Redis を停止し、redis-data を展開済みデータに置き換えてから、再起動します。

5. MCP のバージョン更新
  • デフォルトでは、docker-compose.yml は mcp/<service>:latest を使用します。安定性を高めるには、特定のタグまたはダイジェストを固定してください。

    image: mcp/notion:0.2.1
    
  • MCP の上流リポジトリを監視して、新しいリリースを確認します。

新しいリリースが公開されたら、docker-compose.yml を適宜更新し、ローカルでテストしてから、Git のバージョンを更新します。


MCP スタックの拡張

新しい MCP サーバーやツールの実装が登場したら、次の方法でこのスタックを拡張できます。

  1. docker-compose.yml に新しいサービスを追加します(必要に応じて、別の Dockerfile を作成します)。
  2. .env.example に対応する変数を追加し(その後、ローカルの .env にも追加します)。
  3. curl -N http://localhost:<NEW_PORT>/tools を使ってローカルでテストします。
  4. 外部公開が必要な場合は、DNS ルートと cloudflared の設定を追加します。
例:「Slack MCP Server」の追加
  1. docker-compose.yml に追記します:

    slack-mcp:
      image: mcp/slack:latest
      container_name: mcp-slack
      restart: unless-stopped
      ports:
        - "${SLACK_HOST_PORT}:8080"
      environment:
        SLACK_BOT_TOKEN: "${SLACK_BOT_TOKEN}"
        SLACK_SIGNING_SECRET: "${SLACK_SIGNING_SECRET}"
    
  2. .env.example を更新します:

    ###############################################
    # 19. Slack MCP Server
    ###############################################
    SLACK_BOT_TOKEN=<YOUR_SLACK_BOT_TOKEN>
    SLACK_SIGNING_SECRET=<YOUR_SLACK_SIGNING_SECRET>
    SLACK_HOST_PORT=<YOUR_SLACK_HOST_PORT>  # e.g., 8117
    
  3. 変更を取得し(以前にクローンした場合)、それに応じて .env を拡張します。


ライセンス

このリポジトリは MIT License の下で配布されています。詳細は LICENSE を参照してください。


まとめ

このファーストプリンシプルに基づく README に従うことで、次のことができるようになります。

  • 各コンポーネント(MCP、SSE、Docker、Cloudflare Tunnel)がなぜ存在するのかを理解できます。
  • MCP サーバーの設定、起動、公開の方法がわかります。
  • SSE に対応したあらゆるクライアント(OpenAI Agents SDK、Node/Python スクリプトなど)を、豊富なツールのエコシステムに接続できます。
  • 将来の MCP サーバーや連携機能を追加するための、明確で拡張性のある基盤を得られます。

完全にコンテナ化された、安全で拡張性のある MCP サーバーの世界へようこそ。エージェントは必要な「ツール」を自由に呼び出せる一方で、環境は常に自分で完全に管理できます。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。