現在のaio-probe-mcpは、ローカルのstdio接続に限定したread-onlyの補助サーバーです。これをそのままリモート公開できる状態とは判断していません。transportをHTTPへ変えると、接続相手、資格情報、ログ、継続費用という新しい境界が生まれるからです。

この記事はremote MCPの構築手順ではありません。現行コードで確認できたことと、公開前に追加で必要な証拠を分けるための移行判定記録です。資格学習の概念を最初の実装判断へ変えた経緯はB-01、現在のread-only実装とテストはA-01に分けています。

結論:transportの変更は、trust boundaryの変更である

MCP公式仕様のtransport overviewでは、stdioはclientが起動したsubprocessとの標準入出力、Streamable HTTPは単一のMCP endpointへmessageごとにHTTP POSTするtransportです。serverは各requestへ単一JSONまたはrequest単位のSSE streamで応答します。2026-07-28版では、以前の版にあった独立したGET stream endpointは削除されました。同じMCP messageを運ぶ方法でも、誰が接続できるかという境界は同じではありません。

現行実装はserver.run()で起動し、v2.0.0に固定しているSDKが示すstdioの起動方法を使っています。HTTP endpointは設けていません。MCP callerのlogin、利用者別のauthorization、tenant分離もありません。ローカルでは、実行プロセスとSQLite fileを読めるOS userの権限が事実上の境界です。この状態でHTTPだけを有効にしても、remote利用者を安全に識別できることにはなりません。

いま確認できる範囲と未検証範囲は次のとおりです。

観点現行実装で確認したことremote公開前に不足している証拠
Transport / Identitylocal processから起動する構成。固定3 toolだけを公開HTTP endpoint、接続元検証、caller認証、tool単位認可、identityに基づくアクセス制御
Secret / Data boundaryMCP経路で外部API credentialを要求しない。SQLiteはread-only接続、固定query、限定返却tokenの安全な保管と検証、query前の利用者別data分離、credential lifecycle
Observability計測CLIは成功・失敗・欠測、run ID、exit codeを区別。MCP応答は件数、truncated、redactedを返すMCPのactor、tool call、latency、拒否理由を追える監査ログ・trace・alert
CostMCP照会は追加のDataForSEO requestを行わず、DB・query・並列・返却件数に上限があるcloud runtime、network、log、認証基盤の実測費用、rate limit、停止条件

4つのgateにまとめるため、SecretとData boundaryは1つのgateで扱います。ただし、ここで最も強く確認できたのはread-onlyのData boundaryだけです。Identity、Secret、Observability、Costは「本番機能を実装した証拠」ではなく、「まだ境界へ入れていないこと」と「次に何を検証すべきか」を示しています。

Gate 1:接続できる人を識別し、許可範囲を分けられるか

Streamable HTTP仕様は、すべての接続でOriginを必ず検証する一方、ローカル実行時は0.0.0.0ではなく127.0.0.1へbindし、適切なauthenticationを実装することを推奨しています。これはDNS rebindingを含む、stdioにはなかった接続経路の脅威を扱うためです。

また、MCP Authorization仕様はHTTP-based transport向けのauthorization flowを定義しています。protected MCP serverはOAuth 2.1のresource serverとしてProtected Resource Metadataを公開し、受け取ったaccess tokenが自分向けに発行されたことと必要scopeを検証します。MCP clientはaccess tokenをHTTPのAuthorization headerで送り、URI query stringへ入れてはいけません。

現行のreadOnlyHintは、このgateを通す証拠にはなりません。toolの性質をclientへ伝えるannotationであって、callerのidentityやpermissionを検査する処理ではないからです。

このgateを通したと言える最小条件は、次のとおりです。

  • 許可されたOriginと拒否すべきOriginをtestで分ける
  • tokenなし、期限切れ、異なるaudienceを401で拒否する
  • scope不足を403で拒否し、toolごとの最小権限を定義する
  • URI query stringへaccess tokenを入れたrequestを拒否する
  • caller identityに応じたDBまたはresultのアクセス制御をtestする
  • 認証に失敗してもtool処理を開始しないことを確認する

この証拠がない間は、remote公開はNo-Goです。

Gate 2:秘密情報を持ち込む範囲と、返すデータを分けられるか

現行MCP companionは、計測用DataForSEO adapterを呼びません。MCP toolの引数へAPI credentialを渡さず、保存済みの内部error本文とraw_pathも応答対象から外しています。URLはuserinfo、query、fragmentを除去して返します。

ただし、これは一般的なsecret検出や安全なsecret管理を実装した証拠ではありません。URL path、keyword、domain、provider metadataなど、DB由来の任意文字列が安全だと保証するものでもありません。リポジトリ全体では計測CLIが外部APIを使うため、「システム全体に秘密情報がない」とも言えません。

Authorization security considerationsは、tokenを意図したaudienceへ結び付けること、token passthroughを避けること、安全に保管すること、短命なaccess tokenを使うことを挙げています。remote化でcredentialを持つなら、少なくとも次を新しい設計対象にします。

  • tokenをtool argument、URL、application logへ残さない
  • tokenの発行先と利用先を検証し、下流serviceのtokenをそのまま通さない
  • secretの保管、rotation、失効、閲覧権限、監査を定義する
  • DBを共有する場合も、利用者ごとの返却範囲をquery前に絞る
  • sanitize後の出力だけでなく、保存・export・logを含むdata lifecycleを確認する

read-only接続は書き込みを抑える境界です。誰に何を読ませてよいかというauthorizationの代わりにはなりません。

Gate 3:正常・欠測・攻撃・運用障害を区別して追えるか

現在の実装は、計測のokとfailedを分け、欠測を成功データへ混ぜません。計測CLIはrun IDを最初のAPI requestより前に表示し、完了件数とexit codeでローカル計測の成否を区別します。MCP応答は保存済みrunの対象件数、観測件数、失敗件数、truncated、redactedを返します。これは別々の経路であり、MCP tool call自体のaudit logや終了codeを持つという意味ではありません。

一方、これはcentralized logging、distributed tracing、alert、SLO、per-tool audit logではありません。caller identityがないため、「誰が、いつ、どのtoolを、どのscopeで呼んだか」も記録できません。

remote公開前に必要なのは、ログを増やすことではなく、何を残し、何を残さないかを先に決めることです。MCP Tools仕様がserver側に入力検証、access control、rate limit、出力sanitizeを求めるのと同様に、観測データ自体にも境界が必要です。

  • request ID、actor、tool名、result status、latencyを相関できる
  • credential、query string、返却本文の機微情報をlogへ残さない
  • 401、403、rate limit、server error、timeoutを分ける
  • logの閲覧権限、保持期間、削除方法を定義する
  • alertを出す条件と、alert後に止める処理を分ける

redacted: trueを返せることと、安全な監査logを持つことは別の証拠です。

Gate 4:増える処理を数え、費用の上限と停止条件を分けられるか

現行MCP tool pathはSQLiteを読むだけで、追加のDataForSEO requestを発生させません。DBとWALの合計512 MiB、query 5秒、同時query 4件、返却一覧100件などの上限もあります。これはローカルresourceを無制限に使わないためのguardrailです。

しかし、金額の上限ではありません。remote化すれば、少なくともruntime、network、log保存、認証、secret管理の継続費用が加わります。将来LLMまたは外部APIをtoolから呼ぶなら、retryも含めたrequest数とprovider側の課金条件が必要です。現在のdry-runが示す対象数は、最大request数や最大課金額の保証ではありません。

このgateでは、予算通知だけでなく、アプリケーション側の停止条件まで決めます。

  • 1回のtool callで増えるrequest、token、保存量を数える
  • 利用者別・tool別のrate limitと同時実行上限を置く
  • 日次・月次の通知閾値とhard stopの条件を分ける
  • retryと失敗requestを費用見積もりへ含める
  • 課金処理を初めて有効にする時は、実行前の承認gateを設ける

費用をまだ測っていない段階では、「低コスト」や「無料」とは書かず、「何を測れば判断を変えられるか」までに留めます。

変更要求ごとのGo / No-Go判定

変更要求現在の判定判定の前提/判断を変えるために必要な証拠
同じ端末で、既存SQLiteを固定3 toolから読むGo。ただし現行のローカル境界内だけ現行のread-only test、返却制限、resource limitを維持する
localhostのHTTPで試作する実験のみ条件付きGo(隔離環境限定)127.0.0.1 bind、Origin検証、外部interface非公開をtestする
Internetから1人で利用するNo-GoHTTPS、caller認証、audience検証、最小scope、失敗時拒否をtestする
複数利用者へ公開するNo-Gotenant分離、利用者別authorization、監査、利用量配賦をtestする
MCP toolから外部APIまたはLLMを呼ぶNo-Gosecret lifecycle、出力境界、retry上限、課金条件、実行前承認を確認する
クラウドで常時稼働させるNo-Goruntime・network・log費用、alert、hard stop、障害時の運用手順を実測する

この表は、remote化を避け続けるためのものではありません。実装前にNo-Goの理由を明確にし、必要なtestと運用証拠が揃った時だけ判断を変えるためのものです。

次に行うなら、公開ではなく隔離した移行実験から始める

次の最小実験は、現在のserverをInternetへ公開することではありません。既存のstdio版を基準として残し、隔離したlocalhost-onlyの試作で次を順に確かめます。

  1. 固定3 toolの結果がstdio版と一致する
  2. 127.0.0.1以外へbindせず、不正Originを拒否する
  3. 認証前にtoolが実行されず、401と403を分ける
  4. token、error本文、DB由来の機微情報がlogへ残らない
  5. rate limit、timeout、同時実行、停止条件を失敗testで確認する
  6. 外部APIと課金処理を無効のまま保つ

この段階を通して初めて、限定したremote環境へ進むかを再判断できます。

次の一歩は、4つの移行ゲートからremote化を止めている未検証の証拠を1つ選び、隔離したlocalhost-only実験の失敗testへ落とすことです。

この記事の限界

現行実装はMCP Python SDK v2.0.0へ固定されています。この記事で参照した2026-07-28版MCP仕様は、将来のremote化で必要になる判断項目を整理するための一次情報です。固定SDKが同仕様を実装済みであることも、現行のstdio実装が同仕様へ完全準拠していることも検証していません。

また、認証provider、secret manager、centralized observability、cloud runtimeは選定・実装していません。production traffic、障害対応、複数利用者、費用の実測もありません。ここで確定できるのは、現在のread-only MCPはローカル境界までであり、remote公開には別の設計とtestが必要だということです。