MCPサーバーの作り方 — 自作MCPサーバーをWeb版のChatGPT・Claudeから使えるようにする(後編)

自作MCPサーバーをWeb版のChatGPT・Claudeから使えるようにする手順を、実際に接続した画面つきで解説します。localhostのサーバーに公開URLとOAuth認証を付け、コードを1行も変えずにブラウザのAIから売上データベースへ日本語で聞けるようにします。

MCPサーバーの作り方 — 自作MCPサーバーをWeb版のChatGPT・Claudeから使えるようにする(後編)

こんにちは!Qualitegプロダクト開発部です!

前編では、PythonとFastMCPでMCPサーバーを自作し、手元のClaude Codeから売上データベースに日本語で聞けるところまで作りました。後編の今回は、予告どおりその続きです。

手元(localhost)で動いているこのMCPサーバーを、Web版のChatGPTとClaudeから使えるようにします。

先に結論を言うと、サーバーのコードは1行も変えずに、ブラウザのChatGPTとClaudeの両方から「職業別の売上トップ3を教えて」が通るようになりました。返ってきた数字は前編の実測値と完全に一致しています。到達性・HTTPS・OAuth認証という3つの壁は、当社のWireCanalで越えます。前編の最後に開示したとおり自社サービスですが、この記事の手順は無料(フリープラン)で使える機能だけでできています。クレジットカードの登録も要りません。

前編を読んでいない方はこちらからどうぞ。

MCPサーバーの作り方(前編)| PythonとFastMCPで売上DBをAIにつなぐ(当ブログ)

図1 この連載でつくるもの。前編は手元のAIまで、後編でWeb版のChatGPT・Claudeへつなぐ
図1 この連載でつくるもの。前編は手元のAIまで、後編でWeb版のChatGPT・Claudeへつなぐ

なぜ localhost のままでは Web版から使えないのか

前編のサーバーはHTTPモードで起動すると http://127.0.0.1:9904/mcp がMCPエンドポイントになります。CLI版のClaude Codeは同じPCの中にいるので、このURLで届きます。

Web版は事情がまったく違います。ChatGPTもClaudeも、コネクタへの接続リクエストを投げてくるのはあちら側のサーバーです。あなたのブラウザではありません。だから壁は3つあります。

図2 Web版のAIから localhost のMCPサーバーには届かない。到達性・HTTPS・認証の3つの壁がある
図2 Web版のAIから localhost のMCPサーバーには届かない。到達性・HTTPS・認証の3つの壁がある

ひとつめは到達性。一般的な家庭・社内ネットワークでは、手元のPCはNATやファイアウォールの内側にあって、そのままでは外から到達できません。ふたつめはHTTPS。コネクタに登録するURLは https:// が前提です。3つめが認証。外から届くようにしたということは、世界中の誰からも届くということなので、認証なしで社内データベースにつながるサーバーを置く選択肢はありません。

このうち3つめが、いちばん手ごわい相手です。

ChatGPTもClaudeも、構成によっては認証なしのリモートMCPに接続できます。ただ、社内データベースに到達するサーバーを無認証で公開する選択肢はないので、MCP Authorization仕様に沿ったOAuthで守ることになります。そうすると、認証情報のないアクセスに401を返し、認可サーバーの情報を公開し、クライアント情報を扱い、認可画面・トークン発行・リクエストごとの検証までを用意する必要があります。この一式を自前で実装すると、ツール本体(前編で書いた200行)よりはるかに大きな仕事になります。ここで力尽きて「Web版はあきらめてCLIだけで使う」となりがちなのが、リモートMCPの現実でした。

WireCanal がこの3つをまとめて引き受ける

そこで後編では、当社が提供しているセキュアトンネルサービスのWireCanalを使います。

図3 WireCanal経由の構成。OAuthの許可とツール許可リストの両方を通った呼び出しだけがMCPサーバーに届く
図3 WireCanal経由の構成。OAuthの許可とツール許可リストの両方を通った呼び出しだけがMCPサーバーに届く

仕組みは図3のとおりです。手元のPCでAgentという小さなプログラムを動かすと、AgentがWireCanalのサーバーへ外向きに接続してトンネルを張ります。受信ポートの開放もVPNも要りません。外の世界には https://<名前>.wirecanal.com という公開URLができて、そこへ届いたリクエストがトンネル経由で手元の 127.0.0.1:9904 に流れます。

OAuthも同じURLが引き受けます。認証なしのアクセスには401を返し、ChatGPT・Claudeからの接続はWireCanalの認可画面で持ち主が許可したものだけが通ります。

もうひとつ、MCPならではの仕掛けがあります。外のAIに見せてよいツールを、手元の設定ファイル(wirecanal.json)で選べます。 既定は全ツール拒否で、許可リストに書いたツールしか公開されません。この許可リストの正本は手元のファイルにあります。ダッシュボードからの変更は提案として扱われ、手元側で承認・反映しない限り公開ツールは増えません。

それでは、前編のサーバーが 127.0.0.1:9904 で動いている状態から始めます。

手順1: ダッシュボードで canal を作る

WireCanalのダッシュボード(app.wirecanal.com)にアカウント登録すると、「canal」という公開経路を作れます。作成ウィザードは5ステップです。

まず種類。「MCP 社内MCPサーバーをAIサービスへ公開」を選びます。

canal作成ウィザード。種類は「MCP」を選ぶ
canal作成ウィザード。種類は「MCP」を選ぶ

次に「どのAIから使いますか」。今回はClaudeとChatGPTの両方にチェックを入れました。ここで選んだAIに合わせて、OAuthの接続設定がcanalに自動で入ります。

「どのAIから使いますか」でClaudeとChatGPTにチェックを入れる
「どのAIから使いますか」でClaudeとChatGPTにチェックを入れる

公開アドレスは「おまかせサブドメイン」のまま進めます。転送先には、前編のサーバーが待っている 127.0.0.1:9904 を入れます。

転送先に前編のサーバーが待つ 127.0.0.1:9904 を指定する
転送先に前編のサーバーが待つ 127.0.0.1:9904 を指定する

確認画面で公開URLが決まります。筆者環境では https://mh1sjzat.ja100.wirecanal.com が発行されました。

確認画面。おまかせサブドメインの公開URLが発行される
確認画面。おまかせサブドメインの公開URLが発行される

「作成する」を押すと、canalの詳細画面に移ります。ここまででサーバー側の設定は終わりです。固定IPも証明書の取得も、何もしていません。

手順2: 見せてよいツールを wirecanal.json に書く

canal詳細の「セットアップ」タブに、接続ファイル(wirecanal.json)が表示されます。ダウンロードしてそのまま使えますが、MCPの場合はひとつだけ手を入れます。tools.allow に、外のAIへ見せてよいツール名を書きます。

wirecanal.jsontools.allow に2本を追記したもの)

{
  "access_key": "ck_(canalごとに発行される接続キー)",
  "forward_target": "127.0.0.1:9904",
  "mode": "mcp",
  "tools": {
    "default": "deny",
    "allow": ["execute_sql_query", "get_database_stats"]
  },
  "lang": "ja"
}

既定は "default": "deny" かつ allow が空、つまりつないだ直後は全ツール拒否から始まります。前編のサーバーはツールが2本だけなので全部書きましたが、たとえば社内のMCPサーバーに20本ツールがあっても、ここに書いた2本以外は外のAIからは見えません。一覧(tools/list)にも出ません。

この安全側に倒した初期値は、前編で書いた「AIに全部見せない」設計と同じ考え方です。公開範囲を決める台帳の正本が手元にあるので、ダッシュボード側の操作だけでは公開ツールは増えません。反映には手元での承認が要ります。

手順3: Agent を起動する

セットアップタブの案内どおり、公開したいサーバーが動いているマシンにAgentを入れて起動します。Windowsなら2コマンドです。

irm https://download.wirecanal.com/install.ps1 | iex
.\wirecanal.exe -config wirecanal.json

1行目がAgentのダウンロード(カレントフォルダに wirecanal.exe が置かれます)、2行目が起動です。組織のセキュリティポリシーでリモートスクリプトの直接実行が禁止されている場合は、install.ps1 をいったんファイルとして保存し、中身を確認してから実行してください。筆者環境の起動ログがこちらです。

Agentの起動ログ。公開URLへのアクセスを 127.0.0.1:9904 に届ける旨が表示される
Agentの起動ログ。公開URLへのアクセスを 127.0.0.1:9904 に届ける旨が表示される

ダッシュボード側にも数秒で「接続されました!」が出て、この時点でトンネルが開通しています。

セットアップタブ。「接続されました!」の表示と接続ファイル(wirecanal.json)
セットアップタブ。「接続されました!」の表示と接続ファイル(wirecanal.json)

認証なしのアクセスが 401 で止まることを確かめる

つなぐ前に、公開URLが「誰でも呼べる状態」になっていないことを確かめておきます。前編で「効いていない防御ほど怖いものはない」と書いたとおり、ここは実際に叩いて見るのが確実です。

curl -i -X POST https://mh1sjzat.ja100.wirecanal.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"initialize","id":1}'
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mh1sjzat.ja100.wirecanal.com/.well-known/oauth-protected-resource"

認証トークンなしのリクエストは、手元のサーバーに届く前に401で止まりました。あわせて WWW-Authenticate ヘッダに resource_metadata が付いています。これはRFC 9728で定義された「保護対象リソースのメタデータ文書」のURLで、認可サーバーそのもののURLではありません。ChatGPTやClaudeはまずこの文書を取得し、そこに書かれた authorization_servers をたどって認可サーバーを見つけ、OAuthの接続手続きを自動で始めます。

Claude から接続する

Web版Claudeの設定から、コネクタの画面を開いて「カスタムコネクタを追加」を選びます。入力するのは名前と、さきほどの公開URLに /mcp を付けたものだけです。クライアントIDやシークレットの欄は空のままでかまいません(末尾に挙げたWireCanal公式ガイドは、クライアントIDとシークレットを手入力する手順で書かれています。筆者環境の2026年8月6日時点では、URLを入れるだけで接続できました)。

Claudeのカスタムコネクタ追加。入力は名前と公開URLだけ
Claudeのカスタムコネクタ追加。入力は名前と公開URLだけ

「追加」して「連携」を押すと、WireCanalの認可画面に切り替わります。どのcanalへの接続を求められているかが表示されるので、内容を確認して許可します。

WireCanalの接続許可画面。どのcanalへの接続かを確認して許可する
WireCanalの接続許可画面。どのcanalへの接続かを確認して許可する

接続が済むと、コネクタの詳細にツール一覧が出ます。ここに注目してください。

並んでいるのは、wirecanal.json の allow に書いた2本だけです。

接続後のツール一覧。wirecanal.jsonのallowに書いた2本だけが並ぶ
接続後のツール一覧。wirecanal.jsonのallowに書いた2本だけが並ぶ

あとは前編のClaude Codeと同じように、チャットで日本語で聞くだけです。既定ではツールを使う前に承認を求められます。

ツール使用の承認。既定では実行前に確認を求められる
ツール使用の承認。既定では実行前に確認を求められる

許可すると、Claudeが売上データベースにSQLを投げて答えを返してきました。

Web版Claudeの回答。前編と同じ実測値が返ってきた
Web版Claudeの回答。前編と同じ実測値が返ってきた

経営者 25,621,641円、研究者 24,525,975円、公務員 23,685,112円。前編でClaude Codeが返した集計と同じ、固定シードのダミーデータの実測値どおりです。ブラウザのClaudeから、手元のPCで動くSQLiteまで、ちゃんと一本の道が通っています。

ChatGPT から接続する

ChatGPT側は、未検証のMCPサーバーをつなぐために開発者モードを先に有効にします。筆者環境では、設定の「セキュリティとログイン」にある「開発者モード」をオンにしました(設定の「プラグイン」画面の下にも同じ場所へのリンクがあります)。データを壊しうるコネクタを自己責任で追加する機能なので、リスクの説明をよく読んだうえで進めてください。画面構成はプランや提供時期によって変わることがあります。

次にサイドバーの「プラグイン」から「アプリを作成」。名前とサーバーURL(https://<名前>.wirecanal.com/mcp)を入れると、認証欄のOAuth設定は自動で検出されます。

ChatGPTの新規プラグイン作成。URLを入れるとOAuth設定は自動検出される
ChatGPTの新規プラグイン作成。URLを入れるとOAuth設定は自動検出される

「作成する」のあと「サインイン」に進むと、Claudeのときと同じWireCanalの認可画面が出るので許可します。

WireCanalの接続許可画面(ChatGPTから)。Claudeのときと同じ画面が出る
WireCanalの接続許可画面(ChatGPTから)。Claudeのときと同じ画面が出る

使うときは、ひとつだけコツがあります。チャット入力欄の「+」からいま作ったアプリを選んで、会話に添えてから質問してください。筆者環境では、アプリを添えずに「売上データベースを使って」と文章で頼んだところ、ChatGPTはコネクタではなくWeb検索を始めてしまいました。+から明示的に選べば確実にMCPサーバーが呼ばれます。

ChatGPTの回答。アプリを添えて質問すると同じ数字の表が返る
ChatGPTの回答。アプリを添えて質問すると同じ数字の表が返る

返ってきた表もClaudeと同じ数字です。ローカルのサーバーログにも、ChatGPT側からのリクエストが POST /mcp として記録されていました。

料金

この記事の手順(MCP canalの作成・OAuth認証・おまかせサブドメイン)は、WireCanalの料金ページ(wirecanal.com)の対応表のとおり、フリープランで使えます。クレジットカードの登録も不要です。

つまり、この記事でやったこと(自作MCPサーバーの公開からWeb版ChatGPT・Claudeとの接続まで)は、すべて無料でできます。

フリープランで発行される公開ホスト名は、使っている限り消えません。Agentの接続が生きている間は有効期限が自動延長されます。

逆にAgentを落とすなどして接続を切ると、最後の接続から72時間で失効します(失効しても作り直しはできますがURLが変更されます)。

MCPサーバーを常用するならAgentは動かしっぱなしにするはずなので、実用上はフリープランのままで同じURLを使い続けられます。

好きな名前のサブドメインを予約したい場合は、接続が途切れても消えない永続ホスト名を持てるライト以上が候補になります。ほかにプランで変わるのは、TCP公開(RDPやSSH)がプロ以上、独自ドメインの持ち込みがプレミアム、というあたりです。

なお、この記事のスクリーンショットの一部はライトプランのアカウントで撮っていますが、手順はどれもフリープランの機能だけでできています。

もうひとつ、組織で使うときの話をひとつだけ。今回はcanalの持ち主本人がOAuthの許可を出しましたが、ライト以上では会社の認証基盤(Google WorkspaceなどのOIDC IdP)と連携して、組織のメンバーが自分の会社アカウントで接続許可を受けられるようになります。メンバー全員でMCPサーバーを使う形は、この連載の後の回で実際にやります。

ChatGPTとつなぐときのOAuthは経路側で解決

今回のポイントは、前編のサーバーに1行も手を入れていないことです。localhost向けに書いたMCPサーバーがそのまま、Web版のChatGPTとClaudeの両方から使えました。到達性・HTTPS・OAuthという3つの壁は、サーバーのコードの問題ではなく経路の問題なので、経路側で解決するのが筋がいい、というのが今回の答えです。

公開経路の安全面は二重になっています。入口ではOAuthが認証なしのアクセスを401で止め、その先ではツール許可リストが「見せる2本」以外を隠す。許可リストの正本は手元のwirecanal.jsonにあり、ダッシュボード側の操作だけでは変わりません。変更を反映するには手元での承認が要ります。前編でサーバー内部に作った3段の安全弁(読み取り専用・SELECT検査・実行時間上限)は、そのまま最後の砦として生きています。

ひとつ引っかかったのは、ChatGPTがアプリを自動では選んでくれなかったことでした。最初に知らないと「つながっているのに使われない」ように見えます。同じところで止まる方が多いはずなので、本文に残しました。

検証していないことも書いておきます。今回つないだのは、2026年8月6日時点で開発者モードが表示された筆者のChatGPT Plusアカウントと、Claudeの有料アカウントです。ChatGPTの開発者モードやカスタムMCPアプリの提供対象・画面構成は、プランやアカウントへの展開状況によって変わることがあり、同じ項目がどのアカウントにも表示されるとは限りません。AIサービス側の無料プランでどこまで使えるかも確認していません。また、社内の実データベースへつなぐ場合は、前編で書いたとおり業務別ツールへの分割やアクセスログの監査など、この記事の先にやるべきことがあります。

それでは、また次回、お会いしましょう!

サンプルコード

前編のコードをそのまま使っています。cloneして、DB作成とHTTPモード起動までは次のコマンドです。

qualiteg/mcp-server-tutorial | サンプルコード一式とREADME(GitHub)

git clone https://github.com/qualiteg/mcp-server-tutorial.git
cd mcp-server-tutorial
python -m pip install -r requirements.txt
python db_setup.py
python mcp_server_sales.py --http --port 9904

参考

関連記事

MCPサーバーの作り方 — PythonとFastMCPでデータベースにAIが日本語で答えるようにする(前編)
MCPサーバーの作り方を、動くコードつきで最初から解説します。PythonとFastMCPでSQLiteの売上データベースをMCP化し、AIに日本語で聞くとAIが自分でSQLを書いて集計まで返すところまで作ります。
ngrokとWireCanalは何が違う?開発元が料金・運用・MCP設計を比較
ngrokと同じリバーストンネル方式の国産サービスWireCanalを、開発元が正直に比較します。違いは料金の考え方・運用の場所・AIにつなぐときの許可の置き場所の3つです。

Read more

TensorRT 10 × Blackwell 移行ガイド【中編】ビルドが通っても正しいとは限らない — 沈黙劣化 5 連発

TensorRT 10 × Blackwell 移行ガイド【中編】ビルドが通っても正しいとは限らない — 沈黙劣化 5 連発

こんにちは! 前回の記事「TensorRT 10 × Blackwell 移行ガイド【前編】RTX 50 で推論資産が動かない — 基本と最初の壁」では、Blackwell 世代への移行で既存の推論資産が動かなくなる理由と、TensorRT 10 化を最小構成で通す手順を扱いました。前編で出てきた問題には、実はひとつ共通点があります。 すべて、エラーで止まってくれたということです。 本当に怖いのはその先です。TensorRT への移行パイプラインには、 * ビルドが通る * 実行も通る * 速度もちゃんと出る * 出力の形も、値も、一見それらしい * なのに、中身が間違っている という失敗の仕方が存在します。 本記事では、TensorRT 本体の挙動だけでなく、export 時のミス・精度設定・エンジンの配布ミスまで含めて、エラーで停止せず誤った出力へ至る事象を便宜上 「沈黙劣化」 と呼びます。 テストが通り、ベンチマークが良い数字を出し、「◯倍速くなりました」と報告した後になって発覚するので、非常に厄介です。 本記事では、実際に踏んだ

By Qualiteg プロダクト開発部