Skip to content

About

Dockerized read-only MCP server for securely exposing local workspace files to ChatGPT through OpenAI Secure MCP Tunnel, with optional Amazon Cognito OAuth authentication.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Secure MCP Tunnel MCP Server PoC

ローカルワークスペース内のテキストファイルおよび明示許可された画像ファイルを読み取り専用で参照するための MCP サーバー PoC です。

Docker コンテナ内で Python 製の MCP サーバーを streamable HTTP で起動し、tunnel-client を通じて Secure Tunneling のトンネルに接続します。 公開される操作はワークスペースのファイル一覧・検索・読み取り・テキスト検索と、任意設定の共有 workflow ファイルの読み取りに限定されています。

主な機能

  • 任意設定による Amazon Cognito アクセストークン検証
  • ワークスペース配下のファイルとディレクトリの一覧取得
  • ワイルドカードによるファイル検索
  • UTF-8 テキストファイルの行単位読み取り
  • 明示許可された画像ファイルの無変換読み取り(MCP ImageContent)
  • UTF-8 テキストファイル内の文字列検索
  • .cmd / .bat ファイルの CP932 フォールバック読み取り
  • 任意設定の共有 workflow ディレクトリからのテキストファイル読み取り
  • シンボリックリンク、親ディレクトリ参照、絶対パスの拒否
  • 秘密情報やバイナリに該当しやすいパスの hard deny
  • .mcpignore による MCP 公開対象の allow / ignore 制御
  • MCP ツール呼び出しの構造化アクセスログ

ディレクトリ構成

.
├── Dockerfile
├── build.cmd
├── run.cmd
├── env_local.cmd.sample
├── requirements.txt
├── requirements.lock
├── app
│   ├── auth.py
│   ├── entrypoint.sh
│   ├── logmcp.py
│   └── server.py
└── bin
    └── tunnel-client (別途ダウンロードしてください)
パス 説明
app/auth.py Cognito 認証の設定とアクセストークン検証を定義します。
app/logmcp.py MCP ツール呼び出しのアクセスログ出力とログ値の秘匿・制限を定義します。
app/server.py MCP サーバー本体です。読み取り専用のファイル操作ツールを定義します。
app/entrypoint.sh MCP サーバーの起動、ヘルスチェック、tunnel-client の実行を行うコンテナ起動スクリプトです。
bin/tunnel-client Secure Tunneling 接続に使用する実行ファイルです。
Dockerfile Python 3.12 slim ベースのコンテナイメージを定義します。
build.cmd Windows 環境向けの Docker イメージビルド用スクリプトです。
run.cmd Windows 環境向けの Docker コンテナ起動用スクリプトです。
env_local.cmd.sample ローカル環境固有の設定例です。共有 workflow ディレクトリを使用する場合は env_local.cmd としてコピーして設定します。
requirements.txt Python 依存関係を定義します。
requirements.lock Docker build が実際に使用する解決済み依存定義。

前提条件

  • Docker
  • Secure Tunneling のトンネル ID
  • Secure Tunneling の API キー
  • Windows で build.cmd / run.cmd を使用する場合は、コマンドプロンプトから実行できる Docker 環境

セットアップ

1. tunnel-client の配置

tunnel-client はリポジトリに含めません。GitHub Releases から Linux 用の実行バイナリを取得し、展開後の実行ファイルを bin/tunnel-client として配置してください。 動作が確認されているバージョンは 0.0.9 です。 tunnel-client はこのリポジトリには含まれないため、OpenAI の公式 Releases から取得してください。

tunnel-client --version
0.0.9+62b9b42f698ec5319d2115e0c0ff1dcf6557d7ae (git sha: 62b9b42f698ec5319d2115e0c0ff1dcf6557d7ae)

取得元:

配置後の構成は次のとおりです。

bin/
└── tunnel-client

2. Docker イメージのビルド

Windows では次のコマンドを実行します。

build.cmd

実行される Docker コマンドは次のとおりです。

docker build -t smt-local-files-mcp .

3. 環境変数の設定

app/entrypoint.sh は、次の環境変数を必須として扱います。

環境変数 必須 説明
CONTROL_PLANE_API_KEY はい Secure Tunneling の API キーです。
TUNNEL_ID はい 接続先トンネルの ID です。
MCP_ROOT いいえ MCP サーバーが参照するワークスペースのルートです。既定値は /workspace です。
MCP_HTTP_HOST いいえ MCP サーバーの待ち受けホストです。既定値は 127.0.0.1 です。
MCP_HTTP_PORT いいえ MCP サーバーの待ち受けポートです。既定値は 8000 です。
MCP_HTTP_PATH いいえ MCP サーバーの streamable HTTP パスです。既定値は /mcp です。
TUNNEL_LOG_LEVEL いいえ tunnel-client のログレベルです。既定値は warn です。
MAX_READ_BYTES いいえ read_file で読み取り可能な最大ファイルサイズです。既定値は 262144 です。
MCP_IMAGE_EXTS いいえ read_image で受け付ける拡張子のカンマ区切りリスト。既定値は .png,.jpg,.jpeg,.webp。空文字列は無効化。公開には .mcpignore の明示許可が別途必要です。
MAX_IMAGE_BYTES いいえ read_image で読み取る最大ファイルサイズです。既定値は 4194304(4 MiB)です。
MAX_IMAGE_PIXELS いいえ read_image の最大画素数です。既定値は 16000000 です。
MAX_SCAN_BYTES いいえ search_text で走査可能な最大ファイルサイズです。既定値は 1048576 です。
MAX_RESULTS いいえ 検索系ツールの最大結果件数です。既定値は 100 です。
MCP_AUTH_ENABLED いいえ Cognito 認証を有効化するかどうかを指定します。1、true、yes、on のいずれかで有効になります。既定値は無効です。
COGNITO_REGION 認証有効時ははい Cognito ユーザープールの AWS リージョンです。
COGNITO_USER_POOL_ID 認証有効時ははい Cognito ユーザープール ID です。
COGNITO_CLIENT_ID 認証有効時ははい 受け入れるアクセストークンの Cognito アプリクライアント ID です。
COGNITO_REQUIRED_SCOPES 認証有効時ははい アクセストークンに要求するスコープです。空白区切りまたはカンマ区切りで指定します。
COGNITO_ISSUER いいえ JWT の issuer として検証する URL です。未指定時は COGNITO_REGION と COGNITO_USER_POOL_ID から組み立てられます。
COGNITO_JWKS_URL いいえ 署名検証に使用する JWKS URL です。未指定時は COGNITO_ISSUER 配下の /.well-known/jwks.json が使用されます。
COGNITO_ALLOWED_USERNAME いいえ 受け入れる Cognito ユーザー名を 1 件に制限します。
COGNITO_ALLOWED_SUB いいえ 受け入れる Cognito subject を 1 件に制限します。
COGNITO_ALLOWED_GROUP いいえ 受け入れる Cognito グループを 1 件に制限します。
COGNITO_EXPECTED_AUDIENCE いいえ aud クレームがある場合に期待する audience を指定します。
JWT_DECODE_ALGORITHMS いいえ JWT decode で受け入れる署名アルゴリズムです。空白区切りまたはカンマ区切りで指定します。未指定時はアルゴリズムを制限しません。Cognito を使用する場合は RS256 の指定を推奨します。
MCP_RESOURCE_SERVER_URL いいえ MCP 認証設定で使用する resource server URL です。既定値は http://127.0.0.1:${MCP_HTTP_PORT} です。外部クライアントから利用する場合は公開 URL を明示してください。
MCP_DUMP_TOKEN いいえ トークン検証のデバッグログを出力します。1、true、yes、on のいずれかで有効になります。トークン内容を含むため通常運用では使用しないでください。

run.cmd は、%HOME%\smt-mcp-server-poc.env が存在する場合に --env-file として優先的に読み込みます。存在しない場合は、リポジトリルートの .env を読み込みます。

%HOME%\smt-mcp-server-poc.env または .env の例は次のとおりです。

CONTROL_PLANE_API_KEY=your_api_key
TUNNEL_ID=your_tunnel_id

認証を有効化する場合の環境変数ファイル例は次のとおりです。

CONTROL_PLANE_API_KEY=your_api_key
TUNNEL_ID=your_tunnel_id
MCP_AUTH_ENABLED=1
COGNITO_REGION=ap-northeast-1
COGNITO_USER_POOL_ID=ap-northeast-1_example
COGNITO_CLIENT_ID=your_cognito_app_client_id
COGNITO_REQUIRED_SCOPES=mcp/read
JWT_DECODE_ALGORITHMS=RS256
MCP_RESOURCE_SERVER_URL=https://your-public-mcp-endpoint.example.com

4. 共有 workflow ディレクトリの設定(任意)

プロジェクトごとのワークスペースとは別に、複数のプロジェクトから共通して参照する workflow や instruction を公開できます。

使用する場合は env_local.cmd.sample を env_local.cmd としてコピーし、ホスト側のディレクトリを WORKFLOW_PATH に設定してください。

set "WORKFLOW_PATH=C:\Projects\chatgpt-workflows"

env_local.cmd が存在し、WORKFLOW_PATH が設定されている場合、run.cmd はそのディレクトリをコンテナ内の /workflow に読み取り専用で bind mount します。

env_local.cmd はローカル環境固有のパスを含むため、リポジトリへコミットしないでください。

workflow 例

作者は highlight_scene_image.md を workflow に設置しています。 この workflow は Phase A/B/C からなり、このスレッドでの会話を題材にしたハイライトシーン画像を段階的に作成します。

  • Phase A — Scene Design 現在の会話内容や日付・服装カテゴリをもとに、本番画像の場所、行動、構図、季節感、視覚的焦点などを Scene Brief として設計します。この Phase では画像は生成しません。

  • Phase B — Character Consistency Sheet Phase A の Scene Brief と canonical identity reference をもとに、今回のシーンで使用する人物デザインを決定し、同じ人物・同じ衣装の6ビューを配置した character consistency sheet を1枚生成します。

  • Phase C — Final Highlight Image Phase A の Scene Brief と Phase B の character consistency sheet を参照し、会話内容を背景や小物にも自然に取り入れた最終的なハイライトシーン画像を1枚生成します。

各 Phase は同じチャット内で順番に実行します。例えば次のように依頼します。

workflow highlight_scene_image.md の phase A を実行してください。

Phase A の結果を確認した後、

workflow highlight_scene_image.md の phase B に進んでください。

最後に、

workflow highlight_scene_image.md の phase C を実行してください。

と依頼します。

期待される結果は次のとおりです。

  • Phase A: 本番画像の設計情報である Scene Brief
  • Phase B: 今回の人物・衣装を固定する character consistency sheet 1枚
  • Phase C: 会話のハイライトを表現した最終画像 1枚

通常は workflow 名を指定するだけで read_workflow が選択されます。 うまく参照されない場合は、使用する MCP サーバーを ChatGPT に登録したときのプラグイン名と tool を明示して、例えば次のように依頼してください。

home-mcp-service の read_workflow を使用して
highlight_scene_image.md を読み、phase A を実行してください。

workflow の内容は read_workflow を通じて参照されるため、プロジェクトごとのワークスペースとは独立して、同じ workflow を複数のプロジェクトやチャットから再利用できます。

実行方法

Windows では次のコマンドを実行します。

run.cmd

run.cmd は、現在のディレクトリを /workspace に読み取り専用でマウントし、app ディレクトリを /app に読み取り専用でマウントします。

さらに env_local.cmd の WORKFLOW_PATH が設定されている場合は、そのディレクトリを /workflow に読み取り専用で bind mount します。

docker run --rm -it --init -v "%~dp0\app:/app:ro" --env-file "%HOME%\smt-mcp-server-poc.env" -e MCP_ROOT=/workspace -v "%ABS_PATH%:/workspace:ro" --tmpfs /tmp:rw,nosuid,nodev,noexec,size=64m smt-local-files-mcp

workflow を有効にした場合は、さらに次のオプションが追加されます。

--mount "type=bind,src=%WORKFLOW_PATH%,dst=/workflow,readonly"

実際の run.cmd では、スクリプトの配置場所に基づいて app ディレクトリをマウントします。また、追加の Docker オプションは run.cmd の引数として渡せます。

app/entrypoint.sh は MCP サーバーを起動後、http://127.0.0.1:${MCP_HTTP_PORT}/healthz で起動確認を行います。起動確認に成功すると、tunnel-client run に http://127.0.0.1:${MCP_HTTP_PORT}${MCP_HTTP_PATH} を MCP サーバー URL として渡します。

tunnel-client のログは struct-text 形式で出力されます。ログレベルは TUNNEL_LOG_LEVEL で指定できます。

MCP ツール呼び出しごとに、mcp.access ロガーから JSON 形式のアクセスログが出力されます。ログにはツール名、リクエスト ID、MCP クライアント ID、引数、処理結果、処理時間が含まれます。認証済みの呼び出しでは OAuth クライアント ID、エラー時には例外クラス名も記録されます。ツールの戻り値自体は記録されず、戻り値の型名のみが記録されます。

.mcpignore 設定の確認

.mcpignore と既定ポリシーを適用した後に MCP から公開されるパスは、--list で確認できます。出力はヘッダーなしで、公開対象の相対パスを 1 行ずつ表示します。ディレクトリは末尾に / を付けて表示します。

Windows では次のコマンドを実行します。

run.cmd --list

Docker で直接実行する場合は、entrypoint を python に差し替えて server.py に --list を渡します。

docker run --rm -it --init -v "%~dp0\app:/app:ro" -e MCP_ROOT=/workspace -v "%ABS_PATH%:/workspace:ro" --tmpfs /tmp:rw,nosuid,nodev,noexec,size=64m --entrypoint python smt-local-files-mcp /app/server.py --list

ワークフローディレクトリのアクセス設定確認は、ワークフローディレクトリでこのプロジェクトの run.cmd を --list オプションを付けて起動すると、アクセス可能なファイルがリストアップされます。

.mcpignore による公開ポリシー

MCP サーバーから公開するファイルは、各ファイルルートごとに既定の allow policy と .mcpignore で制御されます。 .mcpignore は gitwildmatch 形式の pathspec として解釈され、配置されたディレクトリ以下に適用されます。

各行では、次の明示構文を使用できます。接頭辞のない行は後方互換のため ignore として扱われます。

ignore build/
ignore **/*.log
ignore !node_modules/
allow **/*.el
allow docs/**/*.md
allow node_modules/**/*.ts

ワークスペースルートには仮想の default ignore policy と default allow policy が存在します。default ignore policy では .git、node_modules、仮想環境、ビルド出力などが非公開になります。default allow policy では、ソースコード、設定ファイル、ドキュメント系の一般的な拡張子と Dockerfile、Makefile、CMakeLists.txt、LICENSE が許可されます。default allow policy の拡張子判定は pathspec として評価されるため、.MD や .CMD などの大文字拡張子は既定では許可されません。これらの仮想 policy はルートの .mcpignore より先に評価されるため、ルートの .mcpignore で ignore **/*.md のように指定すると、既定で許可される README.md も非公開にできます。

ignore 側の pattern には pathspec の negation を使用できます。たとえば、ルートの .mcpignore に ignore !node_modules/ と allow node_modules/**/*.ts を指定すると、default ignore の node_modules/ を打ち消したうえで、該当する TypeScript ファイルを公開できます。

ファイル単位の判定では、下位ディレクトリの .mcpignore から上位へ fallback します。下位の .mcpignore で allow または ignore が確定した場合は、その結果が使用されます。最後まで allow されないファイルは非公開です。

ディレクトリが ignore に一致した場合、その配下全体は非公開となり、子孫ディレクトリの .mcpignore による allow では復活できません。また、.env、秘密鍵、証明書、データベースファイル、.mcpignore などの hard deny 対象は、.mcpignore の allow では公開できません。

.mcpignore は MCP サーバーの公開対象だけを制御します。Git の追跡状態や .gitignore には影響しません。サーバーは .mcpignore をキャッシュしないため、ファイルの追加、変更、削除は次回の MCP ツール実行時に反映されます。

例:

# 生成物を除外します。
ignore dist/
ignore coverage/

# ローカルメモを除外します。
notes.local.md

# サブプロジェクトで必要なファイルを公開します。
allow packages/editor/**/*.el

Cognito 認証

MCP_AUTH_ENABLED を有効化すると、MCP サーバーは bearer token を Cognito の JWT として検証します。検証では JWKS による署名、issuer、有効期限、token_use=access、アプリクライアント ID、必須スコープを確認します。Cognito を使用する場合は JWT_DECODE_ALGORITHMS=RS256 の指定を推奨します。

任意で COGNITO_ALLOWED_USERNAME、COGNITO_ALLOWED_SUB、COGNITO_ALLOWED_GROUP、COGNITO_EXPECTED_AUDIENCE を指定すると、受け入れるトークンを追加で制限できます。

トークン検証に失敗した場合は、クライアントには認証失敗として扱われます。サーバーログには例外クラス名のみを出力します。MCP_DUMP_TOKEN を有効化すると payload を含む詳細ログが出力されるため、通常運用では無効にしてください。

MCP ツール

list_files

ワークスペース配下のファイルとディレクトリを一覧表示します。

主な引数:

  • path: 一覧表示する相対パスです。既定値は空文字です。
  • recursive: 再帰的に走査するかどうかを指定します。既定値は false です。
  • max_entries: 最大件数です。1 から 1000 の範囲に丸められます。

find_files

シェル形式のワイルドカードパターンでファイルを検索します。

主な引数:

  • pattern: 検索パターンです。
  • path: 検索対象の相対パスです。既定値は空文字です。
  • max_results: 最大件数です。

read_file

UTF-8 テキストファイルを行単位で読み取ります。.cmd / .bat ファイルは、UTF-8 として読み込めない場合に CP932 として読み込みます。

主な引数:

  • path: 読み取り対象の相対パスです。
  • start_line: 読み取り開始行です。既定値は 1 です。
  • max_lines: 読み取り最大行数です。1 から 2000 の範囲に丸められます。

read_image

.mcpignore で明示的に allow された画像ファイルを、変更せずに MCP の画像コンテンツとして返します。

{"path": "docs/images/architecture.png"}
  • MCP_ROOT からの相対パスのみ。既存のシンボリックリンク、hard deny、.mcpignore の制限を適用します。
  • MCP_IMAGE_EXTS はカンマ区切りの拡張子(大文字・小文字、前後の空白、先頭ドットの有無は正規化)で、既定値は .png,.jpg,.jpeg,.webp です。空文字列に設定すると画像読み取りを無効にします。
  • 拡張子の設定は公開許可ではありません。 画像は既定の allow policy に追加されません。ワークスペースの .mcpignore などで個別に許可してください。
  • 設定した拡張子が Pillow でサポートされない、または画像の内容と形式が一致しない場合、読み取り時にエラーとなります。MCP SDK が適切な画像 MIME タイプを生成できない場合もエラーとします。
  • MAX_IMAGE_BYTES(既定 4194304 バイト)と MAX_IMAGE_PIXELS(既定 16000000 ピクセル)で読み取り上限を制限します。画像変換・縮小・メタデータ削除は行いません。
  • GIF 等のアニメーションでは、Pillow による検証は最初のフレームに限定されます。MCP クライアントが各画像形式を表示・認識できるかは別途確認してください。

.mcpignore の例:

allow docs/images/**/*.png
allow docs/images/**/*.jpg
allow docs/images/**/*.webp

必要な場合、MCP_IMAGE_EXTS=.png,.jpg,.jpeg,.webp,.gif,.bmp,.tiff,.avif のように拡張できます。追加指定した画像形式が実環境のPillowに対応していることを確認してください。

read_inbox_image

共有 Inbox ディレクトリ内の画像を読み取ります。

ホスト側の Inbox ディレクトリは、env_local.cmd の INBOX_PATH で指定します。run.cmd がコンテナ内の /inbox に読み取り専用でマウントします。

INBOX_PATH が未設定の場合、Inbox はマウントされません。

path は Inbox ルートからの相対パスです。

既存の read_image と同じ画像形式、サイズ制限、 アクセス制御を使用します。

Inbox 内の .mcpignore で公開対象を明示的に許可してください。

read_workflow

共有 workflow ディレクトリ内のテキストファイルを行単位で読み取ります。

プロジェクト固有のファイルには read_file、複数プロジェクトで再利用する workflow や instruction には read_workflow を使用します。

ホスト側のディレクトリは env_local.cmd の WORKFLOW_PATH で指定し、コンテナ内では /workflow として参照されます。

主な引数:

  • path: workflow ディレクトリからの相対パスです。
  • start_line: 読み取り開始行です。既定値は 1 です。
  • max_lines: 読み取り最大行数です。1 から 2000 の範囲に丸められます。

search_text

UTF-8 テキストファイル内の文字列を検索します。.cmd / .bat ファイルは、UTF-8 として読み込めない場合に CP932 として読み込みます。

主な引数:

  • query: 検索文字列または正規表現です。
  • path: 検索対象の相対パスです。既定値は空文字です。
  • regex: query を正規表現として扱うかどうかを指定します。既定値は false です。
  • case_sensitive: 大文字小文字を区別するかどうかを指定します。既定値は false です。
  • max_results: 最大件数です。

セキュリティ制限

このサーバーは読み取り専用として設計されています。次の制限により、意図しないファイル参照を抑制します。 これらのファイル公開制限は、通常の /workspace と共有 workflow の /workflow の双方に適用されます。それぞれのルートは独立して評価され、一方の .mcpignore や相対パス解決が他方へまたがることはありません。

  • 絶対パスは許可されません。
  • .. による親ディレクトリ参照は許可されません。
  • シンボリックリンクは追跡されません。
  • .env、秘密鍵、証明書、データベースファイル、.mcpignore などの hard deny 対象は公開されません。
  • .mcpignore の公開ポリシーで allow されないファイルは公開されません。
  • .git、node_modules、仮想環境、ビルド出力などは default ignore policy により非公開になります。
  • UTF-8 としてデコードできないファイル、NUL バイトを含むファイル、サイズ上限を超えるファイルは読み取られません。ただし、.cmd / .bat ファイルは CP932 での読み込みも試行されます。
  • Cognito 認証を有効化する場合は、MCP_RESOURCE_SERVER_URL に外部クライアントから到達可能な公開 URL を設定してください。
  • アクセスログの引数に含まれる authorization、access_token、api_key、apikey、password、secret、token の値は、キー名の大文字・小文字を区別せず秘匿されます。
  • アクセスログ内の文字列は 500 文字、配列とタプルは 50 件を超える部分が省略されます。

Secure Tunneling 側の準備

Secure Tunneling 側では、サービスアカウントと API キーを作成し、トンネルの利用権限を付与する必要があります。

準備例:

  • Secure Tunneling 用のプロジェクトを作成します。
  • トンネル利用用のサービスアカウントを作成します。
  • サービスアカウントにトンネルの Read/Use 権限を付与します。
  • 組織またはプロジェクトで API キーを発行します。
  • サービスアカウントに必要なロールを設定します。

具体的なロール名や権限設定は、利用している Secure Tunneling 環境の管理画面に合わせて確認してください。

注意事項

  • Dockerfile では app/server.py と app/entrypoint.sh をイメージ内へコピーしていません。現状の run.cmd は app ディレクトリを /app にマウントして実行する構成です。
  • MCP サーバーはコンテナ内の 127.0.0.1 で待ち受け、tunnel-client が同一コンテナ内から接続します。通常はホスト側へポートを公開する必要はありません。
  • Linux や macOS で利用する場合は、run.cmd と同等の docker run コマンドまたはシェルスクリプトを用意してください。
  • bin/tunnel-client は実行ファイルのため、配布・更新方法や対応プラットフォームを別途管理してください。
  • %HOME%\smt-mcp-server-poc.env や .env には API キーなどの秘密情報が含まれるため、リポジトリへコミットしないでください。
  • このリポジトリでは原則として事前相談のない Pull Request は受け付けていません。変更提案がある場合は、まず Issue でご相談ください。README 等の翻訳のみを目的とした Pull Request は受け付けていません。
  • 脆弱性の報告方法については SECURITY.md を参照してください。

備考

ChatGPT App、Secure MCP Tunnel、Amazon Cognito の構築手順は docs/chatgpt-app-cognito-setup.md を参照してください。

About

Dockerized read-only MCP server for securely exposing local workspace files to ChatGPT through OpenAI Secure MCP Tunnel, with optional Amazon Cognito OAuth authentication.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages