MCPサーバーをstdioでローカル利用しているだけなら、Claude CodeやClaude Desktopが自分のPC上で子プロセスを起動し、そのプロセスと直接通信できます。
しかし、
社内の複数ユーザーから使いたい クラウド上のデータベースへ接続したい 自作MCPサーバーをSaaSとして提供したい PCごとにMCPサーバーをインストールしたくない
といった用途では、MCPサーバーをネットワーク越しに公開する必要があります。この場合に利用するのがStreamable HTTPです。現在のMCP Python SDKでも、stdioはローカル向け、Streamable HTTPはデプロイするMCPサーバー向けとして案内されています。stdioとStreamable HTTPの基本的な違いはMCPのstdioとStreamable HTTPの違いで解説しているため、この記事ではリモート公開に必要なHTTPSと認証にしぼって解説します。
ただし、ローカルで動いているMCPサーバーを、
mcp.run(
transport="streamable-http",
host="0.0.0.0"
)
へ変更しただけでインターネットへ公開するのは危険です。Remote MCPでは、
HTTPS 認証 Host・Origin検証 TokenのAudience確認 Reverse Proxy Rate Limit 秘密情報管理
など、通常のWeb APIと同じSecurity設計が必要になります。2026年7月28日のMCP仕様ではProtocol CoreがStateless化され、Remote MCPは一般的なHTTPインフラへ載せやすくなりました。一方でAuthorizationも強化され、OAuthやOpenID Connectに沿ったSecurity設計がより重要になっています。
この記事では、ローカルMCPサーバーをRemote MCPとして公開する基本構成と、Streamable HTTP、HTTPS、OAuth 2.1 Bearer Token、Reverse Proxy、Host Allowlistなどを解説します。OAuth 2.1の認可フロー全体やToken Passthrough禁止などのルールはClaude Code + MCP セキュリティ設計完全ガイドで体系的に解説しているため、この記事ではPython SDKでの実装手順を中心にします。
- リモートMCPではstdioではなくStreamable HTTPを使う
- 0.0.0.0でListenするだけではRemote公開は完成しない
- 本番URLは公開Domainの形にする
- HTTPS終端後のX-Forwarded-*を正しく扱う
- HTTPSからHTTPへのRedirectはMCP Clientに拒否される
- Remote MCPではHost Allowlistを設定する
- TransportSecuritySettingsで公開Domainを許可する
- OriginとHostは別物
- Internet公開するMCPは認証なしにしない
- MCPサーバーはOAuthのResource Serverとして保護する
- APIキー1本だけでもいいのか
- 2026-07-28ではRemote MCPを通常のHTTP APIに近く運用できる
- Mcp-MethodとMcp-NameをGatewayで利用できる
- Reverse ProxyでMCP Endpointだけを公開する
- nginxでHTTPS終端する場合のイメージ
- Browserから使うならCORSも必要
- 独自HTTP Routeは自動的に認証されるとは限らない
- Health Checkには秘密情報を返さない
- Error Responseに秘密情報を含めない
- APIキーをTool Argumentに渡さない
- ユーザーごとの外部サービスTokenはServer側で関連付ける
- Rate Limitも入れておく
- TimeoutとRequest Sizeも制限する
- Tool自体にもAuthorizationを入れる
- Read系ToolとWrite系Toolを分ける
- 破壊的操作にはユーザー確認も検討する
- まずVPNやPrivate Networkだけで公開する方法もある
- IP制限だけを認証の代わりにしない
- Public URLへAPIキーをQuery Stringで付けない
- 本番ではDebug Modeを無効にする
- ログにはUserとToolを追跡できる情報を残す
- OpenTelemetryも利用できる
- 最初は1台でも2026-07-28を前提にしておくと拡張しやすい
- ローカルMCPをRemote化するときに変わるのはTransportだけではない
- 最初に作るならReverse Proxy + HTTPS + OAuthの構成が分かりやすい
- MCPサーバーのリモート公開に関するよくある質問
- リモートMCPでは「URLを公開する」より「Web APIとして守る」ことが重要
リモートMCPではstdioではなくStreamable HTTPを使う
stdioはMCP HostがServer Processを直接起動する方式です。概念的には次の構成です。
Claude Code ↓ python server.py ↓ stdin / stdout ↓ MCP Server
この方式ではServerがClientと同じPC上に存在するため、URLやPortは必要ありません。Remote MCPではServerが別Machine上に存在します。
Claude Code ↓ HTTPS ↓↓ MCP Server https://mcp.example.com/mcp
そこでStreamable HTTPを利用します。Python SDKなら、ローカルでまず次のように動作確認できます。
from mcp.server import MCPServer
mcp = MCPServer("RemoteExample")
@mcp.tool()
def search(query: str) -> str:
return f"Search result: {query}"
if __name__ == "__main__":
mcp.run(
transport="streamable-http",
port=8000
)
デフォルトでは、http://127.0.0.1:8000/mcpへMCP Endpointが公開されます。この状態ではまだローカルServerです。本番ではこれをDomainとHTTPSの背後へ配置します。
0.0.0.0でListenするだけではRemote公開は完成しない
DockerやVPSへ配置するとき、
mcp.run(
transport="streamable-http",
host="0.0.0.0",
port=8000
)
のようにすれば、Network InterfaceからRequestを受け取れるようになります。しかし、http://203.0.113.10:8000/mcpのようなEndpointをそのままInternetへ公開するのは避けたほうがよいでしょう。
HTTPではBearer TokenやTool ArgumentなどがNetworkを流れるため、本番ではHTTPSを基本にします。一般的にはMCP Server自身へTLS証明書を持たせるより、
Internet ↓ HTTPS ↓ Reverse Proxy / Load Balancer ↓ HTTP ↓ MCP Application
という構成にします。Reverse Proxyにはnginx、Caddy、Cloud Load Balancer、Cloudflare、AWS ALBなどを利用できます。MCP Python SDK自身はProtocol Implementationを提供するもので、TLSやProcess Manager、Load BalancerなどのProduction InfrastructureはASGI Serverや周辺Infrastructure側で管理する設計になっています。
本番URLは公開Domainの形にする
Remote MCPでは、Clientが接続するPublic URLを明確に決めます。たとえば、https://mcp.example.com/mcpです。内部的には、127.0.0.1:8000で動いていても構いません。外部Clientから見えるのは、https://mcp.example.com/mcpだけにします。概念的には次の構成です。
Claude Code ↓↓ Reverse Proxy ↓ https://mcp.example.com/mcp↓ MCP Server http://127.0.0.1:8000/mcp
TLS証明書はReverse ProxyやCloud Load Balancerで管理します。Let’s Encryptを使える環境ならCaddyやCertbotなどで自動更新する構成も作れます。
HTTPS終端後のX-Forwarded-*を正しく扱う
HTTPSをReverse Proxyで終端すると、内部MCP Serverへ届く通信はHTTPになることがあります。
Client ↓ HTTPS Reverse Proxy ↓ HTTP Uvicorn
このときApplication側が「自分はhttp://で公開されている」と誤認すると、Redirect URLまでhttp://で生成する場合があります。Python SDKのDeployガイドでは、TLSをProxyで終端する場合にUvicornへProxy Headerを信頼させるよう案内されています。たとえば、
uvicorn server:app \ --proxy-headers \ --forwarded-allow-ips='127.0.0.1'
のようにします。Proxyが別Hostなら、そのProxyのIPを指定します。安易に--forwarded-allow-ips='*'とすると、直接Uvicornへ到達できる環境では偽造したX-Forwarded-* Headerを信頼する可能性があります。Proxy以外からApplication Portへ直接接続できないNetwork構成にしておくことも重要です。
HTTPSからHTTPへのRedirectはMCP Clientに拒否される
たとえばClientがhttps://mcp.example.com/mcpへ接続したとします。ServerがSlash付きURLへRedirectする際に、http://mcp.example.com/mcp/を返してしまうと問題です。Python SDKのClientはHTTPS EndpointからHTTPへのDowngrade Redirectを拒否します。そのため「HTTPSで入ってきたRequestはHTTPSとして認識させる」ことが必要です。
Reverse Proxy構成では、X-Forwarded-Proto: httpsなどが正しくApplicationへ渡され、ASGI Serverがそれを信頼する設定になっているか確認してください。
Remote MCPではHost Allowlistを設定する
MCP Python SDKのStreamable HTTPにはDNS Rebinding対策があります。ローカルではデフォルトで、localhost・127.0.0.1・::1などのHostだけが許可されます。これは悪意あるWebページからLocal MCP ServerへRequestを送られるDNS Rebinding Attackを防ぐためです。
そのため、ローカルで動いたServerをhttps://mcp.example.comへDeployすると、何も変更していない場合、
403 Forbidden Invalid Host header
になることがあります。これはMCP Toolの問題ではありません。MCP ApplicationへRequestが到達する前のTransport Securityで拒否されています。
TransportSecuritySettingsで公開Domainを許可する
Python SDKでは、実際に公開するHostを明示できます。概念的には次のようになります。
from mcp.server import MCPServer
from mcp.server.transport_security import TransportSecuritySettings
mcp = MCPServer("RemoteExample")
security = TransportSecuritySettings(
allowed_hosts=[
"mcp.example.com"
],
allowed_origins=[
"https://app.example.com"
],
)
app = mcp.streamable_http_app(
transport_security=security
)
Port付きHostも利用するなら、運用環境に合わせて許可範囲を設定します。Python SDKのDeployガイドでは、本番Hostを利用する場合にtransport_security=でHost Allowlistを明示することが推奨されています。単純にSecurity Checkそのものを無効化するより、可能であれば実際のDomainをAllowlistへ指定するほうが安全です。
OriginとHostは別物
Web開発ではHostとOriginを混同しやすいので注意してください。HostはRequestの宛先です。
Host: mcp.example.com
Originは、そのRequestを発生させたWeb Originです。
Origin: https://app.example.com
Claude CodeやDesktop ApplicationなどBrowser以外のClientでは、Origin Headerが送られない場合があります。一方、BrowserからMCP Endpointへ接続するならOriginやCORS設定も必要になります。Python SDKのASGIガイドでも、Browser ClientではMCP用Headerを許可するCORS設定が必要になると説明されています。Remote MCPを通常のDesktop Clientだけから使う場合と、Browser Applicationから直接使う場合では、必要なSecurity設定が異なります。
Internet公開するMCPは認証なしにしない
Local MCPでは、「自分のPCからしか起動できない」こと自体がSecurity Boundaryとして機能します。Remote MCPの場合、認証なしでInternetへ公開すると、URLを知っている第三者がToolを実行できる可能性があります。
たとえばToolが、
データベース検索 ファイル操作 GitHub操作 メール送信 顧客情報取得
などを提供していれば大きな問題になります。したがってRemote MCPでは、原則として認証・認可を入れます。
MCPサーバーはOAuthのResource Serverとして保護する
現在のMCP Python SDKでは、Streamable HTTPのAuthorizationにOAuth 2.1 Bearer Tokenを利用する構成が用意されています。MCP ServerはOAuth上のResource Serverとして動作し、Tokenを発行するのではなく、RequestのAuthorization Headerに含まれるTokenをTokenVerifierで検証します。ログイン画面やToken発行処理をMCP Server自身へ実装する必要はなく、Auth0、Microsoft Entra ID、Keycloak、社内Identity Providerなどの既存Authorization Serverへ任せます。
実装ではTokenの署名だけでなくAudience(このMCP Server向けのTokenか)やScope(何が許可されているか)も確認し、Access Tokenをログやデータベースへ無条件に保存しない、外部APIへそのまま転送しない(Token Passthrough)といった注意も必要です。TokenVerifierの実装コード、Audience・Scopeの検証方法、Token保存・ログの扱い、Refresh Tokenの扱いはMCPでOAuth認証を実装する方法で詳しく解説しています。OAuth 2.1の認可フロー自体やPKCE、Client ID Metadata Document、Token Passthrough禁止といった基礎はClaude Code + MCP セキュリティ設計完全ガイドを参照してください。
APIキー1本だけでもいいのか
小規模な社内MCPなどでは、Authorization: Bearer <固定APIキー>のような簡易方式を使いたくなることがあります。限られたNetwork内で少人数だけが使うServerなら、実装上は固定Tokenを検証することもできます。
ただしInternetへ公開する本番Serverでは、
全ユーザーで1つのToken 有効期限なし スコープなし 失効機能なし 利用者識別なし
という設計は管理しにくくなります。複数ユーザーや外部提供を想定するなら、OAuthベースのAccess Tokenを使ったほうがToken失効、Scope、ユーザー識別、Audit Logなどを実装しやすくなります。
2026-07-28ではRemote MCPを通常のHTTP APIに近く運用できる
2026-07-28ではProtocol Level Sessionが削除されました。以前のStreamable HTTPでは、Mcp-Session-Id・Sticky Session・Session Storeなどが問題になるケースがありました。現在のProtocolでは各RequestがSelf-containedになり、通常のRound-robin Load Balancerへ載せやすくなっています。つまり、
Internet ↓ Load Balancer ↓ MCP Server A MCP Server B MCP Server C
という一般的なHTTP Serviceの構成へ近づいています。Remote MCPをProduction運用するうえで大きなメリットです。
Mcp-MethodとMcp-NameをGatewayで利用できる
2026-07-28のStreamable HTTPでは、RequestにMCP-Protocol-Version・Mcp-Method・Mcp-NameなどのHeaderが利用されます。たとえばTool Callなら、
MCP-Protocol-Version: 2026-07-28 Mcp-Method: tools/call Mcp-Name: search_products
のようになります。これによりAPI GatewayやWAF、Rate LimiterがJSON Bodyを解析しなくても、どのMCP Methodか、どのToolかを判断しやすくなります。たとえば高コストToolだけRate Limitを厳しくするなど、Gateway Layerでの制御にも利用できます。
Reverse ProxyでMCP Endpointだけを公開する
MCP Server本体のPortをInternetへ直接Exposeするより、Reverse ProxyだけをPublicにする構成が扱いやすくなります。たとえば、
Internet ↓ 443 ↓ nginx / Caddy / Load Balancer ↓ 127.0.0.1:8000
とします。Firewallでは8000番Portを外部から遮断します。これにより、TLS・Access Log・Rate Limit・IP制限・Request Size制限・WAFなどをProxy側へ集約できます。MCP Python SDK自身も、TLSやConnection LimitなどはMCPServerではなくASGI ServerやDeployment Infrastructure側で設定する設計です。
nginxでHTTPS終端する場合のイメージ
たとえば概念的には次のような構成にできます。
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location /mcp {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
実際には利用するMCP SDKの通信形式、Timeout、Request Size、Streaming要件などに合わせてProxy設定を調整します。またUvicorn側でも、信頼できるProxyからのForwarded Headerを認識する設定が必要です。
Browserから使うならCORSも必要
Claude CodeのようなDesktop / CLI Clientから接続するだけなら、一般的なBrowser CORSは問題になりません。しかしWeb Application内のJavaScriptからRemote MCPへ直接アクセスする場合はCORS設定が必要です。Python SDKのASGIガイドでも、Browser Clientを利用する場合はMCPのRequest HeaderをCORS Allow Headerへ追加する必要があるとされています。
ただし、
Access-Control-Allow-Origin: *
を無条件に指定し、Credential付きRequestまで広く許可するような構成は避けます。Browserから利用するFrontend Originが決まっているなら、https://app.example.comだけに限定するほうが安全です。
独自HTTP Routeは自動的に認証されるとは限らない
MCP Serverへ/health・/status・/callbackなど独自HTTP Routeを追加する場合も注意してください。高レベルAPIのFastMCPレイヤーには@mcp.custom_route()のように通常のHTTP Routeを簡単に追加できる機能がありますが、こうして追加したRouteはMCPのOAuth Auth Middlewareの対象外になります。低レベルAPIでASGI Routeを直接追加する場合も同様に、MCP Endpoint用のAuth Middlewareは自動的には適用されません。
Health Checkなら認証不要でも問題ない場合があります。しかし、内部状態・ユーザー情報・管理機能を返すRouteを同じ感覚で追加すると情報漏えいにつながる可能性があります。MCP Endpointが認証済みだからといって、同じApplicationのすべてのURLが自動で保護されるとは考えないでください。
Health Checkには秘密情報を返さない
Load Balancer向けに/healthを作る場合は、
{
"status": "ok"
}
程度にします。次のような内容まで返す必要はありません。
Database Password API Key 内部Host名 Token Detailed Stack Trace Environment Variable
Health Checkは認証なしで外部Infrastructureから利用されることがあるため、公開されても問題ない最小情報だけ返します。
Error Responseに秘密情報を含めない
Remote MCPではServer ErrorがNetwork越しにClientへ返ります。たとえば例外処理を、
except Exception as e:
return str(e)
だけにすると、Database接続文字列や内部File Pathなどが含まれる可能性があります。Clientへは必要最小限のError Messageを返し、詳細なStack TraceはServer Logへ記録します。特にOAuth TokenやAPI KeyをTool Argumentとして扱う場合は、Loggingにもそのまま出力しないよう注意してください。
APIキーをTool Argumentに渡さない
Remote MCPが外部APIへ接続する場合、
{
"api_key": "sk-..."
}
のように毎回Tool ArgumentへAPI Keyを渡す設計は避けたほうがよいでしょう。API CredentialはServer側のSecret ManagerやEnvironment Variableへ保存します。Clientからは、
{
"query": "example"
}
だけを送ります。Serverが自分のCredentialを使って外部APIへ接続します。これならLLM ContextやTool Call履歴へ秘密情報が混入する範囲を減らせます。
ユーザーごとの外部サービスTokenはServer側で関連付ける
GitHubやGoogleなどユーザーごとのAccess Tokenが必要な場合もあります。この場合、
MCP Clientが認証 ↓ ServerがUser Identityを取得 ↓ Server側Storageから対象UserのCredentialを取得 ↓ 外部APIを呼ぶ
という構成にします。MCP Tool Argumentへ生のRefresh Tokenなどを入れてモデルに扱わせる必要はありません。Tokenは暗号化StorageやSecret Management Serviceなどで管理します。
Rate Limitも入れておく
Remote MCPはURLへ到達できるClientから大量にTool Callされる可能性があります。特にToolが高額な外部API・LLM API・検索API・Database・大量ファイル処理などを呼ぶ場合、Costや負荷が増える可能性があります。Reverse ProxyやAPI Gateway側で、Client単位・User単位・Tool単位・IP単位などのRate Limitを検討します。2026-07-28ではMcp-MethodやMcp-Name Headerが使えるため、GatewayでTool単位のRoutingや制御もしやすくなっています。
TimeoutとRequest Sizeも制限する
MCP Serverだからといって、巨大なRequestを無制限に受け取る必要はありません。Tool Argumentに大量の文字列を渡される可能性もあります。Application ServerやReverse Proxyで、最大Request Size・最大実行時間・Connection Timeoutを設定します。MCP Python SDKにもStreamable HTTPのRequest Body Sizeに関連する設定がありますが、ProductionではProxyやASGI Serverを含む複数層で制限する構成も検討します。
Tool自体にもAuthorizationを入れる
Network Layerが安全でも、Toolが危険な操作を無制限に許可していれば問題です。たとえばread_file・delete_file・run_sql・send_email・deployなどです。認証済みUserだからといってすべてを許可するのではなく、Tool側でも対象Resource・Tenant・Role・Scope・操作内容を確認します。特に複数企業が同じMCP Serverを利用するMulti-tenant構成では、UserAがTenant BのデータへアクセスできないことをServer側で保証する必要があります。モデルへのInstructionだけに依存しないでください。
Read系ToolとWrite系Toolを分ける
Remote MCPではTool設計自体もSecurityに影響します。たとえばmanage_customerという1つのToolで検索・追加・更新・削除をすべて行わせるより、get_customer・create_customer・update_customer・delete_customerのように分けたほうがAuthorizationを設定しやすくなります。読み取りToolにはRead Scopeだけを許可し、破壊的操作にはより強いScopeを要求できます。AIモデルにとってもToolの副作用が分かりやすくなります。
破壊的操作にはユーザー確認も検討する
たとえば本番DB削除・ユーザー削除・メール送信・デプロイ・課金処理などは、Tokenを持っているだけで即実行するのではなく、追加確認を挟む設計も検討できます。2026-07-28 MCPではMulti Round-Trip Requestsが導入され、追加情報や確認が必要な処理をStateless HTTP上で扱いやすくなっています。ただし確認画面だけをSecurity Boundaryにせず、Server側のAuthorizationも必ず行います。
まずVPNやPrivate Networkだけで公開する方法もある
社内利用だけなら、いきなりInternetへ公開する必要はありません。たとえばTailscale・WireGuard・Cloud VPC・社内VPN・Private Networkの内側だけでMCP Serverを公開できます。この場合もHTTPSや認証を省略してよいとは限りませんが、Attack Surfaceをかなり狭められます。特に初期段階では、VPN内+HTTPS+Bearer Token程度から始めると、Public Internetへ直接Exposeするより安全に検証できます。
IP制限だけを認証の代わりにしない
社内IPだけ許可するAllow 203.0.113.0/24といった制限はDefense in Depthとして有効です。しかしIP AddressだけをUser Identityの代わりにはしないほうがよいでしょう。NATやVPN環境では複数Userが同じIPを共有します。IP AllowlistとOAuth Authenticationは目的が異なります。
IP制限 = 接続元Networkを制限 OAuth = 利用者・Clientを識別
として組み合わせます。
Public URLへAPIキーをQuery Stringで付けない
認証Tokenを、https://mcp.example.com/mcp?token=secretのようにURLへ入れるのは避けます。URLはAccess Log・Browser History・Proxy Log・Monitoring・Refererなどへ残る可能性があります。Bearer Tokenは、
Authorization: Bearer <token>
としてHeaderへ送ります。OAuth対応MCPでもこの方式が前提です。
本番ではDebug Modeを無効にする
開発中はDebug Modeが便利ですが、本番ではDetailed ErrorやInternal Stateを露出する可能性があります。Remote MCPでは、DEBUG Logging・Verbose Stack Trace・Development Server・Auto Reloadなどをproduction設定のまま残さないようにします。ログはServer側へ保存し、Clientには必要最小限の情報だけ返します。
ログにはUserとToolを追跡できる情報を残す
Remote MCPは複数Userが利用するため、問題発生時に、誰が・いつ・どのToolを・どのくらい実行し・成功したか失敗したかを追えると便利です。たとえばrequest_id・user_id・client_id・tool_name・duration_ms・statusなどを構造化Loggingへ残します。
ただし、Access Token・Refresh Token・Password・API Key・Tool Argument全文を無条件に保存しないようにします。個人情報や秘密情報がLogへ残る可能性があります。
OpenTelemetryも利用できる
複数Serverや外部APIをまたぐRemote MCPでは、単純なText Logだけでは原因を追いにくくなります。2026-07-28ではMCPのTrace Contextについても整理されており、OpenTelemetryなどのDistributed Tracingと組み合わせやすくなっています。stderrとOpenTelemetryをどちらもどう使い分けるかはMCPのProtocol Loggingが非推奨になった理由で詳しく解説しています。本番運用するRemote MCPでは検討する価値があります。
最初は1台でも2026-07-28を前提にしておくと拡張しやすい
小規模なMCPなら最初はServer 1台で十分です。
mcp.example.com ↓ MCP Server × 1
しかし利用者が増えたら、
Load Balancer ↓ MCP Server × N
へ増やせます。MCP 2026-07-28ではProtocol CoreがStatelessになったため、以前のようなProtocol Sessionを共有する必要がなく、通常のRound-robin Load Balancerへ載せやすくなっています。新しくRemote MCPを作るなら、古いSession前提の記事より2026-07-28対応SDKの実装を参考にしたほうが将来的な拡張が容易です。
ローカルMCPをRemote化するときに変わるのはTransportだけではない
Tool Logicだけを見ると、
@mcp.tool()
def search(query: str):
...
はstdioでもStreamable HTTPでもほぼ同じです。しかし運用面は大きく変わります。stdioなら「Local Process」だったものが、Remoteでは、
Public URL TLS Identity Token Network Proxy Monitoring Rate Limit Authorization
を持つWeb Serviceになります。つまり、mcp.run("streamable-http")へ変えるだけでProduction-readyになるわけではありません。
最初に作るならReverse Proxy + HTTPS + OAuthの構成が分かりやすい
一般的なRemote MCPなら、次の構成から考えると分かりやすいでしょう。
MCP Client ↓ HTTPS ↓ Reverse Proxy / Load Balancer ↓ Bearer Token検証 ↓ Streamable HTTP MCP Server ↓ Tool ↓ Database / External API
Public URLはhttps://mcp.example.com/mcpにします。Reverse ProxyでTLSを終端し、MCP Server本体のPortはInternetへ直接公開しません。MCP ServerではBearer Tokenを検証し、AudienceやScopeも確認します。さらにTool実行時にもUserやTenantのAuthorizationを確認します。この形なら通常のWeb APIで使われてきたSecurityとDeploymentの知識をそのまま活用できます。
MCPサーバーのリモート公開に関するよくある質問
Qstdioで作ったMCPサーバーのToolはそのままリモート公開できますか
ATool自体の定義(名前・説明・入力スキーマ・処理内容)はTransportと分離されているため、基本的にそのまま利用できます。変わるのはmcp.run()の引数などTransportの指定と、認証情報の受け取り方です。ただしローカルファイルパスをそのまま扱うToolは、Remote環境からアクセスできないため設計を見直す必要があります。
QHost Allowlistを設定しないとどうなりますか
A本番Domainへデプロイしても、ローカル向けのデフォルト設定(localhost・127.0.0.1・::1のみ許可)が残っているため、Requestを受け付ける前に403 Forbiddenで拒否されることがあります。TransportSecuritySettingsのallowed_hostsへ実際の公開Domainを追加してください。
Q固定のAPIキーだけでもRemote MCPを運用できますか
A限られたネットワーク内の少人数利用であれば技術的には可能です。ただしInternetへ公開する場合、有効期限やScope、失効機能、利用者識別がない固定Tokenは運用上のリスクが大きくなります。複数ユーザーや外部提供を想定するなら、OAuth 2.1ベースのAccess Tokenを使ったほうが安全に運用できます。
QMCP Server自身でログイン機能を実装する必要がありますか
A必要ありません。MCP ServerはOAuthのResource Serverとして実装するのが基本で、Tokenの発行はAuth0やEntra ID、社内Identity ProviderなどのAuthorization Serverに任せます。MCP Server側はTokenVerifierでAuthorization HeaderのTokenを検証するだけです。
Q独自に追加したHTTP RouteもMCPの認証で保護されますか
A自動的には保護されません。FastMCPの@mcp.custom_route()や低レベルAPIで追加したASGI RouteはMCPのOAuth Auth Middlewareの対象外です。/healthのように認証不要にしたいRoute以外は、必要に応じて個別に認証・認可を実装してください。
QReverse Proxyは必須ですか
A必須ではありませんが、TLS終端やAccess Log、Rate Limit、IP制限などを一か所に集約できるため、多くの構成で扱いやすくなります。MCP Server本体のPortをInternetへ直接公開せず、Reverse Proxyの背後へ配置する構成が一般的です。
リモートMCPでは「URLを公開する」より「Web APIとして守る」ことが重要
ローカルMCP ServerをRemote化するだけなら、Streamable HTTPへ変更してPortを公開すれば通信自体はできます。しかし本番で重要なのは、通信できることではなく、許可されたClientだけが安全にToolを実行できる状態を作ることです。
Remote MCPではHTTPSを利用し、MCP Applicationの生Portを直接InternetへExposeするのではなく、Reverse ProxyやLoad Balancerの背後へ配置する構成が扱いやすくなります。Python SDKを実際のDomainへDeployする場合は、localhost向けに有効になっているDNS Rebinding ProtectionのHost Allowlistも変更する必要があります。設定しなければ403 Forbiddenで拒否されることがあります。
認証にはOAuth 2.1 Bearer Tokenを利用でき、MCP ServerはTokenを発行するAuthorization Serverではなく、Tokenを検証するResource Serverとして実装できます。そしてTokenの署名だけでなく、Audience・Resource・Scope・User・Tenantまで確認し、ToolごとのAuthorizationを行います。
2026-07-28ではRemote MCPがStatelessなHTTP Workloadとして運用しやすくなり、通常のLoad Balancer、Gateway、Rate Limiter、Observability基盤へ載せやすくなっています。
MCPサーバーをRemote公開するときは、「ローカルServerへURLを付ける」のではなく、「外部から利用されるWeb APIへ昇格させる」と考えるのが重要です。最初は、Streamable HTTP・HTTPS・Host Allowlist・Bearer Token・Reverse Proxy・Server側Authorizationまでを基本構成とし、その後利用者数や用途に応じてRate Limit、Audit Log、OpenTelemetry、複数Workerなどを追加すると、安全に拡張しやすくなります。

