記事一覧
MCPセキュリティ

このMCPサーバーは安全?導入前にできる第三者製MCPサーバーの見極め方と12のサイン【MCP Security 2026】

第三者製MCPサーバーを導入前に見極める方法。公式MCP Registryが確認していること・いないこと、15分でできる8ステップ、怪しいサーバーの12のサイン、バージョン固定で本当に固定されるもの(検証:依存12個中4個、81個中5個にしかprovenanceなし)、設定ファイルの点検スクリプト、チームの承認フローまで。

最終更新:2026年10月22日 / 対象:MCP仕様 2026-07-28版(Security Best Practices)、MCP公式ドキュメント「Local Server Security」(2026-07-28版)、公式MCP Registry(プレビュー版)、SEP-1024、npm provenance、OWASP MCP04:2025

結論(30秒で読める要約)

MCPサーバーの見極め(vetting)とは、そのサーバーを一度も動かす前に「公開者・パッケージそのもの・依存関係を信頼してよいか」を判断し、判断が外れたときのために渡す権限をどこまで絞るかを決めることです。第三者製MCPサーバーに対するMCP Securityの「導入前」の部分にあたります。導入後の部分は、サンドボックス化とツール定義の固定が担います。

「このMCPサーバーは安全か?」という問いに、検査で「安全だ」と証明する方法はありません。MCP公式ドキュメント自身が「サーバーが何をするかを証明できるチェックは存在しない」と書いています。そのうえで、15分ほどでできることは次の5つです。

  1. レジストリに載っていることを「審査済み」と読まない。公式MCP Registryが確認するのは、名前空間とパッケージの持ち主だけです。モデレーションポリシーには「モデレーションはほぼ無いものと考えるべき」とあり、脆弱性のあるサーバーも削除対象外です(3章)。
  2. 3つの名前を突き合わせる。レジストリの名前空間、ソースリポジトリ、パッケージ名が同じ公開者を指しているか確認します。初めて見つかった悪意あるMCPサーバー postmark-mcp は、本物のベンダーと同じ名前を名乗っていました(2章)。
  3. 思っているより深く固定する。今回の検証では、バージョンを指定して npm install しても package.json には ^ 付きの範囲で保存されました。npm provenanceが付いていたのは、公式ファイルシステムサーバーの依存ツリー12個中4個、mcp-remote は81個中5個だけでした(6章)。
  4. パッケージだけでなく設定ファイルも点検する。短いスクリプトで10件のサンプル設定を調べたところ、6件で問題が見つかりました。バージョン未固定、トークンの直書き、Dockerソケットのマウント、シェル経由の実行、平文HTTPです(7章)。
  5. 動かし方は導入前に決める。リモートのAPIを包むだけのサーバーなら、そもそも手元のPCで動かす必要はありません。

目次

  1. MCPサーバーを見極めるとは
  2. なぜ見極めが必要か:第三者製MCPサーバーが触れられる範囲
  3. レジストリや一覧サイトが確認していること・していないこと
  4. 15分でできる見極め手順(8ステップ)
  5. 怪しいMCPサーバーの12のサイン
  6. バージョン固定で実際に固定されるもの(検証)
  7. 検証:MCPクライアントの設定ファイルを点検する
  8. リモートMCPサーバーの見極め(パッケージではなくURLの場合)
  9. スキャナーとツール:何が見つかり、何が見つからないか
  10. チームでの承認フロー
  11. チェックリスト(15項目)
  12. よくあるハマりどころ(症状→原因→対処)
  13. NodeFlareならこう解決できる
  14. FAQ

1. MCPサーバーを見極めるとは

MCPサーバーを見極めるとは、出どころ(誰が、どのソースから公開したか)、正体(インストールするパッケージが、ドキュメントの指すものと同一か)、依存関係、求められる権限を確認し、「承認」「条件付き承認」「却下」のいずれかを記録することです。

このブログで扱ってきた他の対策との位置関係は次のとおりです。

段階 問い 対策 関連記事
導入前 そもそも信頼してよいか 見極め(この記事) —
実行時(毎セッション) ツール定義が変わっていないか、指示が隠れていないか ツール定義の固定、説明文の確認 MCPのtool poisoning対策ガイド
信頼が外れたとき どこまで届いてしまうか サンドボックス、Egress許可リスト、スコープを絞ったトークン MCPサーバーのサンドボックス化ガイド

MCP公式ドキュメントは、この関係を一文でまとめています。「見極めは誤った信頼判断の確率を下げ、封じ込めは誤った判断の代償を決める」。

2. なぜ見極めが必要か:第三者製MCPサーバーが触れられる範囲

ローカルのMCPサーバーは、ネットからダウンロードして自分のユーザー権限で動かす普通のソフトウェアです。2026-07-28版の「Local Server Security」ガイドは、ローカルサーバーが環境変数を引き継ぎ、アカウントが読めるものは何でも読め、どこへでも外向き通信を開けると書いています。さらに、設定したサーバーはすべてLLMのコンテキストを共有するため、「1つ追加するたびに、他のすべてのサーバーがさらされる攻撃面が広がる」とも指摘しています。

サプライチェーンの経路ごとに、すでに公開事例があります。

経路 公開事例 何が起きたか(出典の記述どおり) 導入前に効いたはずの確認
なりすましパッケージ npmの postmark-mcp(2025年9月) Postmark公式ライブラリと同じ名前を名乗り、バージョン1.0.16で送信メールすべてを公開者宛てにBCCする1行が追加された。Koi Securityが発見した時点で1,643ダウンロード。Postmarkは自社の開発・許可を否定 ベンダー自身のリポジトリやドキュメントとパッケージを突き合わせる
依存パッケージの侵害 npmワーム「Shai-Hulud」(2025年9月) CISAによれば500以上のパッケージが侵害された。GitHubトークンやクラウドの鍵を収集し、乗っ取ったメンテナーのアカウントで自己増殖した ロックファイルやイメージのダイジェストで依存ツリーごと固定する。外向き通信は既定で拒否する
悪意ある設定 OX SecurityによるSTDIOの開示(2026年4月) CSAのリサーチノートによると、公式SDKのstdio起動経路で設定値がOSのシェルに渡るため、MCPの設定を書き換えられる人はコマンドを実行できる。下流のツールで少なくとも14件のCVE。Anthropicはこの挙動を「想定どおり」とした command と args はコードとして扱い、設定の変更はすべてレビューする
脆弱なブリッジ CVE-2025-6514(mcp-remote 0.0.5〜0.1.16未満) 信頼できないサーバーへの接続時に、細工された authorization_endpoint からOSコマンドインジェクション(CVSS 3.1:9.6) 勧告とバージョンを照合する。知らないサーバーにブリッジを向けない
便利そうに見える悪意あるサーバー Kasperskyの検証用PoC(2025年9月) 開発者向けの機能が本当に動くサーバーで、検知できたのはネットワークセンサーが不審な外向き通信を捉えたときだけだった 新しいサーバーはEgressを絞って動かし、接続先を見る

OWASPはこのリスクを、MCP Top 10の中で MCP04:2025「Software Supply Chain Attacks & Dependency Tampering」として挙げています。

3. レジストリや一覧サイトが確認していること・していないこと

公式MCP Registry(registry.modelcontextprotocol.io、現在プレビュー版)が確認しているのは持ち主であって、安全性ではありません。各チェックが何を証明するかを表にまとめます。

チェック 仕組み(レジストリのドキュメントより) 証明できること 証明できないこと
GitHub名前空間 io.github.<user>/* 公開者が mcp-publisher からGitHubのOAuthでログイン そのGitHubアカウントや組織を公開者が管理している そのアカウントが、想定しているベンダー本人であること
ドメイン名前空間 com.example/* DNSのTXTレコード、または /.well-known/mcp-registry-auth にEd25519かECDSA P-384の公開鍵を置く そのドメインを公開者が管理している コードについては何も
npmパッケージ package.json の mcpName がサーバー名と一致すること(MUST) レジストリの登録とnpmパッケージの持ち主が同じ パッケージや依存関係が安全であること
PyPI・NuGet・Cargo READMEに mcp-name: <サーバー名> の文字列 同上 同上
OCIイメージ io.modelcontextprotocol.server.name アノテーション 同上 同上。タグは後から付け替えられる
MCPBバンドル server.json の fileSha256。レジストリはこのハッシュを「検証しない」、検証するのはクライアント ダウンロードしたファイルが登録されたファイルと同一 誰が書いたか、何をするか
リモートサーバー remotes[].url は公開アクセス可能であること(MUST) URLが応答する 公開手順のページには、URLのドメインと名前空間を結びつける確認の記述がない
モデレーション 違法コンテンツ、マルウェア、スパム、動かないサーバーを削除 既知の悪質なものの一部は消える 「モデレーションはほぼ無いものと考えるべき」。脆弱性のあるサーバーは削除しない

ここから言えることは3つです。

  • 名前空間がいちばん頼れる身元の手がかりです。io.github.github/... や com.stripe/... は偽装しにくい一方、io.github.randomuser/stripe-mcp は、READMEがどれだけ立派でもStripeではありません。
  • 削除されても消えてはいません。削除されたサーバーは status: "deleted" になりますが、メタデータはAPIから読めるままです。社内カタログに同期している場合は、_meta["io.modelcontextprotocol.registry/official"].status を確認してください。
  • 踏み込んだモデレーションは上流が担います。レジストリ自身が、npm、PyPI、Docker、下流のサブレジストリに頼っていると書いています。MCP公式ドキュメントも、厳選型のカタログですら自らの審査を「ベストエフォート」と説明していると指摘しています。比較的強い手がかりとしては、Dockerのカタログがあります。ドキュメントによると、mcp/ 配下のイメージはDockerがビルドと署名を行い、SBOMを同梱しています。

4. 15分でできる見極め手順(8ステップ)

上から順に進め、失敗したステップで止めます。

  1. ローカルで動かす必要があるか考える。MCP公式ドキュメントは、リモートのAPIを包むだけのサーバーは「PCで動かしても何も得をしない」と書いています。ベンダーのリモートサーバーを使うか、自分で手元のPC以外にホストします。
  2. 公開者を特定する。パッケージをソースリポジトリと実在のメンテナーや組織に結びつけます。リポジトリに最近のもっともらしい更新があるか、ベンダー自身のドキュメントがそのリポジトリを案内しているかを確認します。
  3. 3つの名前を突き合わせる。レジストリの名前空間、リポジトリの持ち主、パッケージ名が一致するかを1文字ずつ比べます。MCP公式ドキュメントの言葉では、タイポスクワッティングは「最も安上がりな攻撃」です。
  4. 要所のコードを読む。全部を監査する必要はありません。外向き通信、環境変数やホームディレクトリの読み取り、子プロセスやシェルの実行、インストール時スクリプトをソースから検索し、どれもサーバーの役割で説明がつくかを見ます。
  5. provenanceを確認する。npmなら npm view <pkg>@<version> dist.attestations で証明書(attestation)の有無がわかり、npm audit signatures(npm 9.5.0以降)でインストール済みパッケージの署名と証明書を検証できます。provenanceが示すのは、どのリポジトリ・コミット・ワークフローでビルドされたかです。コードが安全かどうかは示しません。
  6. 確認したバージョンで固定する。パッケージは厳密なバージョン、コンテナイメージはダイジェストで固定します(6章)。
  7. LLMに見せる前にツール一覧を読む。MCP Inspectorで接続し、ツール名・説明文・入力スキーマをすべて読みます。説明文にツールの役割と無関係な指示があれば、そのサーバーは外します。
  8. 動かし方を決めて記録する。固定したバージョン、渡すトークン(サーバーごとに1つ、最小のスコープ)、見せるディレクトリ、通信してよいホスト、承認者を書き残します。

ステップ2・5・6をnpmで行うコマンド例です。

# 誰が、どこから公開し、最後にいつ変わったか
npm view @modelcontextprotocol/server-filesystem@2.0.0 repository.url maintainers time.modified
# このバージョンにprovenanceの証明書があるか
npm view @modelcontextprotocol/server-filesystem@2.0.0 dist.attestations.provenance.predicateType
# そのバージョンを厳密に、インストール時スクリプトを実行せずに入れてから検証
npm install --save-exact --ignore-scripts @modelcontextprotocol/server-filesystem@2.0.0
npm audit signatures

5. 怪しいMCPサーバーの12のサイン

1つでも当てはまれば慎重に。2つ以上なら別のサーバーを探すことをおすすめします。

サイン なぜ問題か 対処
有名ベンダーに似た名前なのに、公開者が違う postmark-mcp と同じパターン ベンダー自身のドキュメントが示すものだけを入れる
名前空間がベンダーと一致しない(例:io.github.someone/<vendor>-mcp) 名前空間はレジストリが行う唯一の身元確認 ベンダーのドメイン名前空間のものを優先する
リモートのAPIを呼ぶだけなのに、ローカルのstdio版しかない ローカルに入れると、得るものなしにPCへの権限だけが増える リモート版を使うか、PC以外でホストする
導入手順が npx -y <pkg> や @latest 起動のたびに最新版が実行される 厳密なバージョンで固定する
狭い用途なのに ~ や / などの広いルートを求める 過剰収集。設定上の許可リストは「協力的な境界」にすぎない プロジェクトのディレクトリ1つを読み取り専用で渡す
アカウント全体に効くトークンを求める 1回の漏えいで、そのトークンが届く範囲すべてが漏れる サーバー専用でタスクに絞ったトークンを発行する
インストール時スクリプト(preinstall、postinstall)が通信する ツールを目にする前にコードが動く --ignore-scripts で入れ、スクリプトを読む
ソースリポジトリが無い、アーカイブ済み、非公開、パッケージと無関係 動かすものを確認できない。npmでもリポジトリが削除・非公開になるとprovenanceを「確認できなくなる」 却下するか、自分で管理するフォークからビルドする
最近持ち主が変わった、長く止まっていたのに急に更新された 放置プロジェクトの乗っ取りはMCP公式ドキュメントが挙げる脅威 前回信頼した版との差分を読む
ツールの説明文に、他のツールについての指示や、操作を隠す指示がある tool poisoningやshadowing そのサーバーを外す
設定が bash -c を経由する、ダウンロードしたものをシェルに流し込む 設定そのものが攻撃の本体になる 固定のバイナリと引数に置き換える
認証なしでローカルのHTTPを待ち受ける MCP公式ドキュメントいわく、127.0.0.1へのバインドは「認証の境界ではない」 stdioにするか、トークンを必須にする

6. バージョン固定で実際に固定されるもの(検証)

固定できるのは、指定した層だけです。MCP公式ドキュメントは、npx や uvx でのバージョン指定は「最上位のパッケージだけを固定する」もので、推移的な依存関係はインストールのたびに解決され、「そこがまさに侵害された依存パッケージが入り込む場所だ」と注意しています。

固定の方法 固定されるもの 固定されないもの
npx -y pkg 何も すべて
npx -y pkg@2.0.0 最上位のパッケージ 依存関係(範囲内で変わる)
uvx pkg==2026.10.19 最上位のパッケージ 推移的な依存関係
ロックファイルをコミットしたプロジェクトで npm ci npmの依存ツリー全体 ランタイム自体、ネイティブのダウンロード
コンテナイメージをタグで指定(:1.2.3) 保証されない。タグは付け替えられる すべて
コンテナイメージをダイジェストで指定(@sha256:...) 依存関係を含むファイルシステム全体 イメージの中では何も残らない

2026年10月22日に、npm 10.9.4とNode.js 22で、よく使われる3つのパッケージを空のプロジェクトへ --ignore-scripts 付きで入れて確かめました。

パッケージ(入れたバージョン) 依存ツリーのパッケージ数 npm provenanceあり 直接の依存関係の指定
@modelcontextprotocol/server-filesystem@2.0.0 12 4 すべて ^ の範囲(例:diff ^8.0.3、glob ^13.0.6)
@playwright/mcp@0.0.83 3 3 厳密なバージョン
mcp-remote@0.15.2 81 5 すべて ^ の範囲(例:express ^4.21.2、undici ^7.12.0)

わかったこと:

  • 「2.0.0を入れた」は固定ではありません。npm install pkg@2.0.0 を普通に実行すると、package.json には "^2.0.0" と書かれました。--save-exact を付け、ロックファイルをコミットし、npm ci で入れてください。
  • 最上位のprovenanceは、ツリー全体についてほとんど何も語りません。3つとも最上位にはSLSAのprovenanceがありましたが、mcp-remote 配下の81個の大半にはありませんでした。今のnpmでは珍しいことではなく、だからこそ個々の証明書よりロックファイルやダイジェストが効きます。
  • 依存関係を厳密に固定しているのは良いサインです。@playwright/mcp は2つの依存を厳密なバージョンで指定しており、インストールのたびにツリーが変わることがありません。
  • 固定には更新の習慣が要ります。MCP公式ドキュメントが言うとおり、勧告が出たときは「固定こそが脆弱なままにする原因」になります。固定したサーバーごとに勧告を追ってください。

計測について2点補足します。証明書の数はレジストリのメタデータから npm view で数えました。npm audit signatures は、検証環境のネットワーク制限でSigstoreのTUFエンドポイントに届かず完了できませんでした。数値はこの日時点のもので、メンテナーの対応が進めば変わります。

7. 検証:MCPクライアントの設定ファイルを点検する

設定ファイルもサプライチェーンの一部です。どのパッケージを、どの引数・トークン・マウントで動かすかを決めているからです。次の読み取り専用スクリプトは、mcpServers 形式のJSON(Claude DesktopやCursorなどが使う形式)から、よくある危険なパターンを洗い出します。2026年10月22日にPython 3で動作を確認しました。

#!/usr/bin/env python3
"""Flag risky entries in an MCP client config (mcpServers JSON). Read-only."""
import json, re, sys

SECRET = re.compile(r"(ghp_|github_pat_|sk-|xox[bp]-|AKIA|AIza)[A-Za-z0-9_\-]{8,}")
SHELLS = {"sh", "bash", "zsh", "cmd", "powershell", "pwsh"}

def pkg_arg(args):
    return next((a for a in args if not a.startswith("-") and a != "run"), "")

def unpinned(spec, launcher):
    if launcher == "npx":
        name = spec[1:] if spec.startswith("@") else spec
        return "@" not in name or spec.endswith("@latest")
    if launcher in ("uvx", "pipx"):
        return ("==" not in spec and "@" not in spec) or spec.endswith("@latest")
    return False

def audit(cfg):
    out, cmd, args = [], cfg.get("command", ""), [str(a) for a in cfg.get("args", [])]
    exe = cmd.rsplit("/", 1)[-1]
    if exe in ("npx", "uvx", "pipx") and unpinned(pkg_arg(args), exe):
        out.append("HIGH unpinned package")
    if exe in SHELLS or "-c" in args:
        out.append("HIGH runs through a shell")
    if exe == "docker":
        if "@sha256:" not in " ".join(args):
            out.append("MED image not pinned by digest")
        if any("docker.sock" in a for a in args):
            out.append("HIGH Docker socket mounted")
        mounts = [b.split(":")[0] for a, b in zip(args, args[1:]) if a in ("-v", "--volume")]
        if any(m in ("~", "/", "$HOME") for m in mounts):
            out.append("HIGH home or root directory mounted")
        if "--network" not in " ".join(args):
            out.append("LOW no --network restriction")
    if SECRET.search(json.dumps(cfg)):
        out.append("HIGH literal secret in config")
    url = cfg.get("url", "")
    if url.startswith("http://") and not re.match(r"http://(127\.0\.0\.1|localhost)", url):
        out.append("HIGH remote server over plain HTTP")
    return out

if __name__ == "__main__":
    for name, cfg in json.load(open(sys.argv[1])).get("mcpServers", {}).items():
        print(f"{name}: " + ("; ".join(audit(cfg)) or "OK"))

危険な設定5件と、それぞれを堅くした設定5件、計10件のサンプルで実行した結果です。

エントリ 内容 検出結果
filesystem npx -y @modelcontextprotocol/server-filesystem HIGH バージョン未固定
filesystem-pinned 同じものを @2.0.0 で指定 OK
github some-github-mcp@latest、env に ghp_... のトークン HIGH バージョン未固定、HIGH 秘密情報の直書き
fetch uvx mcp-server-fetch HIGH バージョン未固定
fetch-pinned uvx mcp-server-fetch==2026.10.19 OK
db Dockerの :latest、-v /var/run/docker.sock:...、-v ~:/data MED ダイジェスト未固定、HIGH Dockerソケット、HIGH ホームをマウント、LOW ネットワーク制限なし
db-hardened ダイジェスト指定、--network none、--read-only OK
helper bash -c でスクリプトをダウンロードして sh に流し、サーバーを起動 HIGH シェル経由で実行
crm http://crm.example.com/mcp HIGH 平文HTTP
crm-tls HTTPS、トークンは ${CRM_TOKEN} から参照 OK

10件中6件で問題を検出し、堅くした4件はすべて通過しました。限界もあります。ここでの「OK」は、上のパターンが見つからなかったという意味にすぎません。バージョンを固定した uvx でも推移的な依存関係は毎回解決されますし(6章)、パッケージそのものの良し悪しは判断できません。共有している設定ファイルにはCIで、端末管理ツールで集めた設定ファイルには定期的に実行するのがおすすめです。

8. リモートMCPサーバーの見極め(パッケージではなくURLの場合)

リモートMCPサーバーは手元でコードを動かさないので、問いが「このコードは何に触れるか」から「このエンドポイントを誰が運用し、自分は何を渡すのか」に変わります。

確認すること 理由 確かめ方
ドメインはベンダーのものか レジストリの公開手順ページには、リモートURLと名前空間を結びつける確認の記述がない 一覧サイトだけでなく、ベンダー自身のドキュメントでURLを確認する
HTTPSで、認証があるか トークンもツールの結果もネットワークを通る 平文HTTPや、社内データに触れるのに認証のないものは却下する
標準のMCP認可に対応しているか OAuthなら、長期トークンをローカルの設定ファイルに置かずに済む Protected Resource Metadata(RFC 9728)の有無と、要求スコープの狭さを見る
同意画面でどんなスコープや権限を求めるか 広すぎる付与は、1回の誤った呼び出しを大きな漏えいにする タスクに不要な書き込み・管理スコープは断る
ツールの引数や結果にどんなデータが載るか 引数に顧客データや秘密情報が入りうる ベンダーのデータの扱いと保存期間の規約を読む
コミュニティ製なら、誰が運用しているか 第三者のホストはすべてのリクエストを見られる ベンダー公式を選ぶか、自分でデプロイする

コミュニティ製のstdioパッケージで、APIを包んでいるだけの場合は中間の選択肢もあります。一度レビューしたうえで、自分で管理する基盤で動かし、コードを開発者のPCに一切置かない方法です。HTTPブリッジの比較はstdioのMCPサーバーをリモートで動かすチュートリアルにまとめています。

9. スキャナーとツール:何が見つかり、何が見つからないか

スキャナーは役に立ちますが、それぞれ1つの層しか見ていません。

ツール 確認するもの 注意点
MCP Inspector サーバーが公開するツール名・説明文・スキーマをLLMを介さずに一覧表示 MCP公式ドキュメントがステップ7で推奨。Inspector自体も更新を(CVE-2025-49596は0.14.1未満が対象)
Snyk Agent Scan(旧Invariantのmcp-scan) エージェントの設定を自動で見つけ、MCPサーバーやスキルのプロンプトインジェクション、機密データの扱い、マルウェアを検査 uvx snyk-agent-scan@latest で実行。SNYK_TOKEN が必要。検査のため構成要素の情報を解析APIへ送る(秘密情報は送信前に伏せると説明)
npm audit signatures インストール済みnpmパッケージのレジストリ署名とprovenance 出どころを検証するもので、振る舞いは見ない
SBOM生成ツール(Syft、Trivy) 成果物の中身。MCP SDKのバージョンも含む MCP公式ドキュメントは、公開されたSBOMを信じるより自分で生成することを勧めている
設定ファイルの点検(7章) バージョン未固定、秘密情報、マウント、シェル、平文HTTP CIで安く回せる

スキャナーが何も報告しないのは、「知っているパターンが見つからなかった」というだけです。サンドボックス化の記事で紹介した封じ込めは、いずれにしても外さないでください。

10. チームでの承認フロー

個人の見極めは、会社全体にはそのまま広げられません。MCP公式ドキュメントの組織向けの指針は、次の5つに集約できます。

  1. 承認済みサーバーの許可リストを公開する。固定バージョンと、受け入れ基準(公開者が特定できる、ソースが読める、provenanceのメタデータがある、SBOMがある)をセットにします。
  2. 承認された経路をいちばん楽な経路にする。利用者は、エディタの拡張機能と同じ感覚で、断りなくサーバーを入れるものだと考えておきます。
  3. 既定の動かし方を決める。たとえば「第三者製サーバーはホームディレクトリをマウントしないコンテナで動かす」。
  4. ローカルの権限が不要なものは集中してデプロイする。リモートの1インスタンスなら、パッチも監査も数百台ではなく1か所で済みます。
  5. 全社規模のインシデントに備える。設定の棚卸しから該当インスタンスをすべて見つけ、Egressを遮断し、渡していた認証情報をすべてローテーションし、修正済みの固定バージョンを配布します。

サーバーごとの承認記録は、1ページで十分です。

項目 記入例
サーバーと固定バージョン @modelcontextprotocol/server-filesystem@2.0.0
公開者の根拠 名前空間、リポジトリURL、provenanceあり
動かす場所 コンテナ、プロジェクトディレクトリを読み取り専用、--network none
認証情報 不要
承認したツール read_text_file、list_directory
担当と日付 プラットフォームチーム、2026-10-22
再審査のきっかけ 新バージョン、持ち主の変更、勧告

11. チェックリスト(15項目)

導入前

  • [ ] ローカルの権限が本当に必要か確認した。不要ならリモート版を使う
  • [ ] 公開者を特定し、ベンダーのドキュメントがそのリポジトリを案内している
  • [ ] 名前空間・リポジトリの持ち主・パッケージ名が一致している
  • [ ] 外向き通信、環境変数やホームディレクトリの読み取り、シェル実行、インストール時スクリプトをソースで確認した
  • [ ] provenanceや署名があり、対応しているエコシステムでは検証した
  • [ ] MCP Inspectorでツール名と説明文を読んだ

固定

  • [ ] 厳密なバージョンで保存(--save-exact)しロックファイルをコミットした、またはイメージをダイジェストで固定した
  • [ ] どの設定にもバージョンなしの npx -y や @latest がない
  • [ ] 固定したサーバーごとに勧告を追っている

動かし方

  • [ ] 第三者製サーバーは隔離して動かし、素のプロセスでは動かさない
  • [ ] サーバーごとに絞ったトークンを1つ、サーバー単位で渡している。個人の広いトークンは使い回さない
  • [ ] 見せるのはプロジェクトディレクトリ1つ、できれば読み取り専用。~ やDockerソケットは渡さない
  • [ ] 外向き通信は既定で拒否し、想定する接続先を列挙している

組織

  • [ ] 受け入れ基準つきの承認済みサーバー許可リストがある
  • [ ] 設定ファイルの棚卸しと、試験済みの緊急停止手順(Egress遮断、認証情報のローテーション)がある

12. よくあるハマりどころ(症状→原因→対処)

症状 原因 対処
「公式レジストリに載っているから安全」と判断した レジストリが確認するのは持ち主でコードではない。ポリシー上もモデレーションは最小限 他のパッケージと同じく公開者とコードを確認する
固定したはずのサーバーが、入れ直したら挙動が変わった 固定していたのは最上位のパッケージだけ ロックファイルと npm ci、またはコンテナのダイジェスト
「固定」したのに package.json が ^2.0.0 npm install pkg@2.0.0 は既定で範囲を保存する --save-exact を使う
不要なはずの鍵をサーバーが読んでいた シェルのプロファイルでexportした秘密情報を引き継いだ 秘密情報はサーバーごとの設定で渡す
承認済みのサーバーが知らないホストに通信し始めた 悪い更新、依存パッケージの侵害、またはインジェクション Egress許可リストと、新しい接続先へのアラート
チームの設定ファイルに本物のトークンが入っている env やヘッダーに直接貼った シークレットストアや環境変数から参照する
脆弱なサーバーがどのPCで動いているかわからない 棚卸しがない 端末管理ツールでクライアントの設定を収集する
スキャナーは通ったのにインシデントが起きた スキャナーは既知のパターンを見るだけで、意図は判断できない 隔離とEgress制限は外さない

13. NodeFlareならこう解決できる

NodeFlareはリモートMCPサーバーのホスティングサービスです。GitHubリポジトリからデプロイすると、各サーバーは専用のFirecracker microVMで動き、手前のプロキシがすべてのリクエストを認証・認可・記録します。ただし、パッケージの見極めを代わりに行うものではありません。依存関係のスキャン、署名の検証、コミットの固定はドキュメントに記載がないため、4章のステップ1〜7はご自身で行う必要があります。変わるのは「動かし方」です。承認したサーバーを開発者のPCから離し、一般的なローカル導入より厳しい制限の中で動かせます。この記事で挙げたリスクと、ドキュメントに記載された機能の対応は次のとおりです。

この記事のリスク NodeFlareの機能 内容
第三者製サーバーが開発者のファイルや鍵を読む(2章) サーバーごとのFirecracker microVM サーバーはPCではなく専用のmicroVMで動くため、~/.ssh やブラウザのプロファイルがそもそも存在しない
レビューしていないコードが動く 自分で選んだGitHubリポジトリからデプロイ レビューしたリポジトリ(自分のフォークなど)を指定できる。entry_command と build_command を明示すれば自動検出より優先され、不足しているビルドツールは許可リスト(git、unzip、build-essential など)からのみ入る
悪い更新や依存パッケージが外部に送信する(2章・6章) Egress制御 モードは off(既定)、observe、enforce。登録は最大100件(完全一致のホスト名、先頭1つのワイルドカード *.example.com、IP)。ホスト側でDNSとnftablesにより適用。Logs > Egress で観測された接続先を確認し、許可してから enforce に切り替える
設定ファイルやイメージにトークンが残る(5章・7章) 暗号化されたシークレット 環境変数は保存時に暗号化され、VMの起動時にだけ注入される。ビルド引数、イメージのレイヤー、ログには入らず、ビルドログでは既知のトークン形式が伏せられる
タスクに不要なツールまで公開される ツール単位のスコープと絞り込まれたツール一覧 tools:call:<ツール名>(例:tools:call:read_text_file)などのスコープをプロキシが確認し、拒否した呼び出しはJSON-RPCエラーを返してサーバーに届かない。tool_list_filter_by_scope で、呼び出し元ごとに使えるツールだけを見せる
認証のない、または知らない呼び出し元が届く 既定で非公開、ハッシュ化されたキー、ロックアウト、IP許可リスト サーバーは共有・公開を選ばない限り非公開。mcp_* キーはハッシュ化して保存。同じIPから誤ったキーが繰り返されると、そのIPを10分間ロック。restricted のネットワークポリシーはIPv4/IPv6のCIDRで指定し、認証より前に確認される(ネットワークアクセス制限はPro・Teamプラン)
承認したサーバーが何をしたかわからない(10章) リクエストログ リクエストごとに mcp_method、tool_name、arg_keys(名前のみ)、http_status、outcome(scope_denied など)、caller_kind、client_ip を記録。保存期間はFreeで7日、Pro・Teamで30日

NodeFlareでできないこと:パッケージが安全かの判定、provenanceの検証、依存関係の固定、ツール説明文に仕込まれた毒の検知、LLM内部でのプロンプトインジェクションの防止はできません。Egress制御はオンにするまで無効で、チームがローカルで動かし続けるサーバーには効きません。

最小の始め方:

  1. 4章の手順で一度レビューし、承認したリポジトリをフォークしてそのフォークをデプロイします。APIトークンは暗号化された環境変数として登録します。
  2. 呼び出し元ごとに mcp_* キーを1つ発行し、承認した tools:call:<ツール名> のスコープだけを付けます。
  3. Egress制御を1週間 observe で動かし、観測した接続先を登録して enforce に切り替えます。

1サーバーまでは無料で試せます。NodeFlareで始める

14. FAQ

MCPサーバーが安全かどうかはどうやって判断しますか?

事前に安全だと証明することはできません。MCP公式ドキュメントも、サーバーが何をするかを証明するチェックは無いと明言しています。できるのはリスクを下げることです。公開者を確認し、名前空間・リポジトリ・パッケージ名を突き合わせ、通信・環境変数・シェルに触れるコードを読み、確認したバージョンで固定し、Egressを絞って隔離して動かします。

公式MCP Registryはセキュリティの審査をしていますか?

していません。確認しているのは名前空間とパッケージの持ち主です。モデレーションポリシーには「モデレーションはほぼ無いものと考えるべき」とあり、削除されるのは違法コンテンツ、マルウェア、スパム、動かないサーバーだけです。脆弱性のあるサーバーは削除されません。

MCP Registryの名前空間は何を証明しますか?

公開者がそのGitHubアカウント(io.github.<user>/*)またはドメイン(com.example/*。DNSのTXTレコードか /.well-known/mcp-registry-auth で確認)を管理していることです。誰が公開したかはわかりますが、コードが安全かどうかはわかりません。

npx -y でMCPサーバーを動かしても大丈夫ですか?

バージョンを指定しないなら避けてください。npx -y pkg は起動のたびに最新の公開版を実行します。最低でも厳密なバージョンを付け、できればプロジェクトに --save-exact で入れてロックファイルをコミットし npm ci で入れるか、ダイジェストで固定したコンテナイメージを使います。

MCPのサプライチェーンセキュリティとは何ですか?

MCP Securityのうち、サーバーのコードの出どころを扱う領域です。パッケージ、依存関係、コンテナイメージ、設定ファイルが対象になります。OWASPは MCP04:2025「Software Supply Chain Attacks & Dependency Tampering」として挙げています。対策は公開者の確認、バージョン固定、provenanceの確認、隔離、Egress制限です。

最初に見つかった悪意あるMCPサーバーは何ですか?

Koi Securityが「実環境で初めての悪意あるMCPサーバー」とした、2025年9月にnpmで見つかった postmark-mcp です。Postmark公式ライブラリと同じ名前を名乗り、バージョン1.0.16で送信メールすべてを公開者にBCCする1行が追加されました。削除までに1,643ダウンロードされています。

npm provenanceがあればMCPサーバーは安全ですか?

いいえ。provenanceが示すのは、どのリポジトリ・コミット・ビルドワークフローで作られ、権限のあるアカウントが公開したかです。本物のリポジトリからビルドされた悪意あるコードでも、provenanceは有効になります。今回の検証では、mcp-remote の依存関係の大半にはprovenance自体がありませんでした。

AIクライアントにつなぐ前に、MCPサーバーのツールを確認するには?

MCP Inspectorで接続すると、LLMを介さずにすべてのツール名・説明文・入力スキーマを一覧できます。説明文にツールの役割と無関係な指示があればサーバーを外し、ツール定義が変わったときに再確認を求めるクライアントを選んでください。

ローカルではなくリモートのMCPサーバーを使うべきですか?

リモートのAPIを包むだけのサーバーなら、リモートをおすすめします。MCP公式ドキュメントは、そうしたサーバーをPCで動かしても得るものはないとしています。リモートなら手元でコードが動かず、設定ファイルにトークンを置く代わりに標準のOAuthを使えます。ファイル、ローカルのツール、ハードウェアが必要なサーバーだけをローカルに残してください。

MCPのセキュリティスキャナーだけで十分ですか?

十分ではありません。Snyk Agent Scanなどのスキャナーは、説明文の中のプロンプトインジェクションやマルウェアといった既知のパターンを調べます。意図の判断や、侵害されたすべての依存パッケージの発見はできません。バージョン固定、隔離、Egress制限と組み合わせてください。

会社のMCPサーバー許可リストには何を載せればよいですか?

承認したサーバーごとに、固定バージョン、公開者の根拠、動かす場所と方法、承認した認証情報とツール、担当者、再審査のきっかけを載せます。MCP公式ドキュメントは、受け入れ基準(公開者が特定できる、ソースが読める、provenanceのメタデータがある、SBOMがある)を公開することを勧めています。

まとめ

MCPサーバーの見極めは、サーバーを動かす前に下す信頼の判断です。MCP公式ドキュメントのとおり、確率を下げることはできても、安全を証明することはできません。公式MCP Registryが教えてくれるのは「誰が公開したか」であって「安全か」ではないので、名前空間・リポジトリ・パッケージ名は自分で突き合わせ、通信・環境変数・シェルに触れるコードを読み、provenanceがあれば確認します。そのうえで、最上位のパッケージより深く固定してください。今回の検証では、バージョン指定の npm install でも ^ 付きで保存され、依存関係の大半にはprovenanceがありませんでした。設定ファイルもサプライチェーンの一部として点検し、ローカルの権限が要らないサーバーはリモートか集中管理の基盤で動かし、信頼していたサーバーが悪くなる日に備えて隔離とEgress制限を外さないことが大切です。導入後の対策は、MCPサーバーのサンドボックス化ガイドに続きます。

参考資料(一次情報)

NodeFlare

MCP専用ホスティングサービス

GitHubにあるMCPを簡単デプロイ・簡単運用で最適化
無料で始める

他の記事

MCPホスティング2026年10月22日

MCP Hostingでデータが消える理由と対策:memory・SQLite・filesystemサーバーの永続ストレージ実践ガイド【2026年】

memory・SQLite・filesystemのMCPサーバーをホスティングすると、なぜ再起動でデータが消えるのか。server-memory 2.0.0で、npxキャッシュへの既定保存、相対パスのMEMORY_FILE_PATH、ロックファイルのENOENT、ファイル単体マウントのEBUSY、WALで1,000行が消えたSQLiteを検証。Cloud Run・Lambda・Workers・Railway・Renderの制約、書き込み手を1つにするルール、Docker手順、バックアップまで解説。

MCPトークン2026年10月21日

長いエージェントセッションのMCPトークン消費:古いツール結果をcontext editing・compaction・サブエージェントで片付ける方法【2026年コスト試算】

長いエージェントセッションでMCPのトークン消費が毎ターン増える理由と抑え方。Claude Sonnet 5.5で40リクエストを試算し、context editing(clear_tool_uses)の設定、Claude API・OpenAIのcompaction、Claude Codeの/compact・/clear・サブエージェント、消すと逆に高くつく条件を解説します。

MCPセキュリティ2026年10月21日

MCPのEnterprise-Managed Authorization・Client Credentials・通常OAuthの使い分け:呼び出し元別の選び方とID-JAG検証【MCPセキュリティ 2026】

MCP公式の認可拡張であるEnterprise-Managed Authorization(ID-JAG/Cross-App Access)とOAuth Client Credentialsの仕組み、社員・CI・サービスごとの方式の選び方、テスト済みのID-JAG検証コード(不正な許可証14件中11件を拒否)、2026年10月時点の対応クライアント、共有APIキーからの移行手順を解説します。

このMCPサーバーは安全?導入前にできる第三者製MCPサーバーの見極め方と12のサイン【MCP Security 2026】 | Blog | Nodeflare