mcpField
M
MCPSentinel

MCPSentinel

本地服务
github.com/gentaArnezzi安全15 周前更新

关于 MCPSentinel

MCPSentinel 扫描 MCP 服务元数据以发现安全信号,并结合静态规则与语义分流来减少误报,适用于安全审查和 CI 检查。默认只读;扫描结果不能证明服务安全或不安全。

主要功能

  1. 01针对 MCP 描述信息的静态规则
  2. 02基于离线启发式的语义分流
  3. 03可选的 OpenAI 审查
  4. 04已批准基线与描述信息差异
  5. 05终端、JSON、SARIF 和 HTML 报告
  6. 06CLI、GitHub Action 与 MCP 扫描器

适用场景

  1. 01审查本地或远程 MCP 服务
  2. 02在 CI 中拦截服务变更
  3. 03与已批准基线比较元数据

MCP 相关

支持通过 stdio 和 Streamable HTTP 发现 MCP 信息,也可通过 MCP 原生扫描器接口提供扫描能力;常规扫描不会调用发现的工具。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"gentaarnezzi-mcpsentinel": {
"command": "uvx",
"args": [
"mcp-guardian-scan"
],
"env": {
"MCPSENTINEL_ALLOWED_HOSTS": "<MCPSENTINEL_ALLOWED_HOSTS>",
"MCPSENTINEL_ALLOW_PRIVATE_HTTP_TARGETS": "<MCPSENTINEL_ALLOW_PRIVATE_HTTP_TARGETS>"
}
}
}
}
启动命令uvx mcp-guardian-scan
需要配置的环境变量
MCPSENTINEL_ALLOWED_HOSTSComma-separated MCP server hostnames, optionally with an exact port, that the MCP-native scanner may connect to.
MCPSENTINEL_ALLOW_PRIVATE_HTTP_TARGETSSet to true only to permit an explicitly allowlisted private or reserved HTTP address in a trusted local network.

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypimcp-guardian-scan0.8.8

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

MCPSentinel

+----------------------------------------------------------------+
|                          MCPSENTINEL                           |
|          模型上下文协议服务的安全审查                          |
|                     默认只读                                   |
+----------------------------------------------------------------+

发现 MCP 元数据。筛查可疑意图。信任变更前先进行审查。

CI PyPI Python License MCP Registry GitHub Action M8ven verification

MCPSentinel 是一款精确优先的安全扫描器,适用于 模型上下文协议 服务。它会将静态规则命中视为候选项,然后在报告之前进行语义意图分析。这样既能保留模式匹配的快速覆盖能力,又不会将每个看似正常的 fetch 或 delete 工具都判定为漏洞,造成大量误报。

默认判定器是离线、确定性的启发式方法,而不是大模型。可选的 OpenAI 审查会向 OpenAI 传输有界且经过脱敏的元数据。两种模式都不能证明 服务的实现是安全的。

版本范围:v0.8.8。 上方的 PyPI 徽章显示已发布的版本; 如果你安装的版本早于此处介绍的功能,请从源代码安装。M8ven 徽章对应其列表中链接的源代码修订版,并不代表当前工作树、 软件包来源或测得的检测准确率。请阅读 带日期的工程评估,了解相关证据和仍待满足的门槛。

60 秒快速开始

python -m pip install mcp-guardian-scan
mcpsentinel                    # safe, no-write onboarding
mcpsentinel scan http://localhost:8000/mcp

第一条命令会打开一份易读、可复制粘贴的入门指南。交互式 终端会显示彩色面板;json 和 sarif 输出不会包含装饰性文本, 方便自动化处理。

MCPSentinel 交互式终端入门指南

我想……从这里开始
不使用服务或 API 密钥进行尝试本地演示:正常、可疑、重复
检查一个本地或远程服务扫描服务
在 CI 中添加审查门禁GitHub Action
向 AI 客户端提供扫描功能原生 MCP 扫描器
在容器中运行容器镜像
了解适用范围和限制MCPSentinel 能告诉你什么——以及不能告诉你什么
审查流程
discover metadata  ->  static candidates --------> semantic triage  -> human review
         |                                               ^                    |
         +-> every server instruction (MCP-S001) --------+                    v
                                                     explicitly approve baseline

你将获得什么

  • 通过 stdio 和 Streamable HTTP 发现 MCP v2,优先协商 server/discover,并在必要时自动回退到旧版 initialize
  • 可配置的静态模式规则,适用于工具、提示词、资源、资源模板和服务器指令描述符,包括工具投毒、影子攻击、跨服务器和 OAuth 混淆代理信号
  • 语义分流:默认使用离线启发式方法,可选使用 OpenAI 结构化输出判定器并提供有限回退;每条服务器级指令都会接受专门的 MCP-S001 审查,即使没有匹配正则表达式
  • 显式批准基线、感知字段的描述符差异,以及稳定的服务器身份/协议漂移检测
  • 协议完整性检查:在基线获得信任之前拒绝重复的描述符身份
  • 品牌化 Rich 终端、JSON、SARIF 和独立 HTML 风险报告
  • 允许/拒绝策略配置
  • 显式验证自有工具,并在 Docker 沙箱中运行且不允许网络出口
  • GitHub Action 和 MCP 原生扫描器接口

静态扫描仅处理元数据。动态调用是单独的可选路径,详见下文;GitHub Action 和 MCP 原生服务绝不会运行动态调用。

安装和开始使用

安装已发布的包,然后使用 MCPSentinel CLI:

python -m pip install mcp-guardian-scan
mcpsentinel

不带命令运行 mcpsentinel,会启动一份简短、不写入任何内容的终端上手指南。它会说明只读扫描模式,提供可复制粘贴的首次扫描命令,并将 OpenAI 保持为可选项。使用 mcpsentinel onboard(或别名 mcpsentinel init)可再次显示指南,也可以自定义建议的命令,而不联系任何服务:

mcpsentinel onboard --target https://mcp.example.com/mcp
mcpsentinel onboard --target "python -m example_mcp_server" --transport stdio

在交互式终端中,指南会使用彩色面板和可复制粘贴的命令。如果终端、Shell 配置或输出捕获禁用了颜色检测,可使用 mcpsentinel --color always 强制启用颜色。

上手流程绝不会索取、存储或传输 API 密钥。使用 mcpsentinel --help 或 mcpsentinel scan --help 查看完整参考。

从源代码进行开发:

python -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[dev]'

扫描服务

对于 Streamable HTTP 服务:

mcpsentinel scan http://localhost:8000/mcp

对于 stdio 服务,将其命令作为目标并加上引号:

mcpsentinel scan "python -m example_mcp_server" --transport stdio

也可以将可执行文件和参数分开提供。以短横线开头的参数必须使用 --arg=value 形式:

mcpsentinel scan python --transport stdio --arg=-m --arg=example_mcp_server

Stdio 目标会作为不可信的子进程运行。默认情况下,MCPSentinel 只转发可执行文件路径和区域设置,不会转发 OPENAI_API_KEY、云凭据、HOME 或其他任何主机环境值。使用 --env KEY=VALUE 仅传递服务所需的值;报告和快照会显示键,但绝不会显示值。--inherit-env 仅用于受信任的兼容场景,并会明确标记为不安全,因为它会转发完整环境。

只读并不意味着已沙箱隔离。 为了枚举 stdio 元数据,MCPSentinel 必须在主机上以进程方式启动目标可执行文件。正常扫描期间,它绝不会调用发现的 MCP 工具,并且默认不会提供凭据,但恶意可执行文件在启动或发现期间仍可使用操作系统用户能够访问的文件系统和网络。只扫描你信任并愿意在本地启动的 stdio 可执行文件。交互式终端会在 stdio 扫描前再次提示此警告;非交互式 JSON/SARIF 输出不会提示,以便自动化使用。

交互式结果示例

下方截图使用 MCPSentinel 受控的本地测试夹具,其工具元数据被刻意设置得可疑。它展示了 stdio 信任边界警告和发现项的布局;这并非对第三方 MCP 服务的扫描结果。

带有 stdio 信任边界警告的 MCPSentinel 扫描结果

实用选项:

# Machine-readable report and CI failure gate
mcpsentinel scan http://localhost:8000/mcp --format sarif --output results.sarif --fail-on high

# Visual portfolio-ready report
mcpsentinel scan http://localhost:8000/mcp --format html --output risk-report.html

# Use OpenAI's structured-output semantic judge (OPENAI_API_KEY is required)
mcpsentinel scan http://localhost:8000/mcp --judge openai --judge-model gpt-4o-mini

# Scan using a repository-local baseline root (it contains baselines/ and judge-cache/)
mcpsentinel scan http://localhost:8000/mcp --baseline-dir .mcpsentinel

# After reviewing the scan's displayed fingerprint, rediscover and approve only that exact state
mcpsentinel baseline approve http://localhost:8000/mcp --baseline-dir .mcpsentinel \
  --fingerprint sha256:REPLACE_WITH_REVIEWED_FINGERPRINT

--baseline-dir 是根目录:默认值为 ~/.mcpsentinel,快照位于 baselines/,语义缓存条目位于 judge-cache/。其中还包含一个本地的、权限模式为 0600 的 HMAC 作用域密钥。该密钥用于区分同一端点的不同身份验证上下文,同时确保快照路径和内容不包含凭据;请妥善保管此目录,不要只将其中的快照复制到另一台机器。快照和缓存条目会通过唯一的临时文件、fsync 以及 POSIX 系统上的 0600 权限模式,以原子方式写入。

普通扫描绝不会更新基线。它会显示 SHA-256 定义指纹,而 baseline approve 会重新发现目标后再写入。只有重新发现的指纹与已审核指纹完全相同,批准才会成功。定义指纹 v2 和基线快照 v5 涵盖描述符状态以及稳定身份子集:服务名称、服务版本、协商后的协议版本和声明的能力名称。描述符的变更、添加或移除(包括服务指令)会标记为 MCP-B001;身份或协议变更则会单独标记为中危项 MCP-B002。先前已批准的快照会一直保留,直到明确批准新快照。

两个描述符具有相同的 kind:name 身份时会产生 MCP-N002,因为字典形式的基线无法明确表示此类目录。在服务返回唯一身份之前,不允许批准。较旧的基线需要一次性重新批准为 v5。对于不含凭据的旧版快照,仍可进行保守比较;但如果目标 URL 含有用户信息、查询参数中包含敏感键、显式环境变量值、看似凭据的参数,或可以访问继承的宿主环境,则绝不会自动信任或迁移旧版快照。

首次扫描会报告尚无已批准的基线。这属于初始设置状态,而非漏洞发现项。请仅基于你信任的服务版本和环境建立基线。

风险评分是一个上限为 0–100 的加权总分,权重取决于严重程度和语义置信度。它是用于确定优先级的信号,并不代表服务单独来看是安全或不安全的。

语义判定器

--judge heuristic 是默认选项,可完全离线运行。--judge openai 需要设置 OPENAI_API_KEY;--judge auto 会在该密钥存在时选择使用 OpenAI,否则使用启发式判定器。OpenAI 判定器使用 Python SDK 的 Responses 结构化输出 API,因此 API 响应无法绕过扫描器预期的判定结果架构。判定结果会按描述符哈希以及带版本号的判定器/提示词标识缓存在基线目录中,避免重复产生 API 费用,同时确保判定方法变更后不再保留旧判定结果。

每次 OpenAI 判定的客户端截止时间为 30 秒,SDK 最多重试两次。发起 OpenAI 请求前,MCPSentinel 会递归脱敏结构化字段中的机密值,随后脱敏文本中的常见 API 密钥、Bearer 凭据和私钥。提示词上限为 12,000 个字符,并使用感知字段的头尾摘录,因此长描述符无法仅靠填充内容来隐藏所有最终证据。候选项评估使用并发数上限为 4 的请求。脱敏是纵深防御措施,并不能保证发送任意敏感元数据都是安全的。如果元数据必须保留在本地,请选择 heuristic。

如果 --judge auto 遇到 OpenAI 服务中断或响应格式错误,扫描会使用离线启发式判定器完成,并在报告中显示提示;回退判定结果不会缓存为 OpenAI 判定结果。--judge openai 仍保持严格模式:如果配置的提供方不可用,就会失败,而不会静默切换。

语义阈值默认为 0.70。低于此阈值的候选发现项不会出现在报告中;只有在更重视召回率而非精确率时才降低阈值。

服务级指令分析

MCP 服务指令本身就是独立的攻击面,因此 MCPSentinel 不会等待英文静态正则表达式匹配后才进行检测。每个 SERVER_INSTRUCTIONS 描述符都会触发专门的 MCP-S001 语义审查。离线启发式判定器提供一条优先保证精确率的检测路径:将普通使用指南判定为安全,同时识别指令层级覆盖、隐瞒、凭据窃取、可疑的外部传输,以及部分英文、西班牙语、印度尼西亚语、葡萄牙语、法语和德语表达。针对 MCP-S001 的允许或拒绝选择器与其他策略决策的工作方式相同,且仍受语义阈值限制。

启发式判定器在本地运行,不会传输任何内容。选择 --judge openai 会向配置的 OpenAI 模型发送经过递归脱敏且长度受限的元数据摘录;为内部服务指令启用此功能前,请先评估这一隐私边界。

自定义静态规则

传入 --rules path/to/rules.json 可在内置规则基础上添加规则对象。每条规则的格式如下:

{
  "id": "ORG001",
  "title": "Example organization policy",
  "category": "tool_poisoning",
  "severity": "high",
  "description": "Why this candidate deserves semantic review.",
  "patterns": ["(?i)example pattern"],
  "fields": ["description", "schema"]
}

支持的类别包括 prompt_injection、tool_poisoning、tool_shadowing、ssrf、secret_exfiltration、command_execution、destructive_operation、cross_server_attack、oauth_confused_deputy、rug_pull、resource_exhaustion 和 protocol_integrity。

进行正则评估前,扫描器会对分析专用视图应用 Unicode NFKC 规范化、移除零宽字符等格式控制字符,并折叠空白。扫描器有意不改写跨文字系统的形近字符,因为这可能导致合法元数据被错误表示;在声称支持这些字符之前,请使用基准测试跟踪覆盖缺口。描述符字段也设有字节数上限(名称 4 KiB、描述 64 KiB、架构和元数据各 192 KiB、总计 512 KiB)。超出上限的描述符会产生 MCP-N001,其中包含原始字节数和 SHA-256;但只有有界数据会进入报告、规则、基线或可选的语义判定器。

请将自定义规则视为可信的安全配置:对于病态模式,Python 正则表达式可能消耗大量 CPU。不要在特权 CI 工作流中执行未经审查的规则变更;应像保护和审查策略变更一样保护和审查这些文件。

策略配置

--policy path/to/policy.json 用于提供组织专属的允许/拒绝控制。允许选择器会抑制匹配的静态候选项或专用服务器指令候选项;拒绝选择器则会生成由策略强制执行的发现项,而无需依赖语义判定器。选择器可以是规则 ID,也可以是限定到描述符名称正则表达式的对象。

{
  "allow": [{"rule_id": "MCP003", "subject_pattern": "^controlled_fetch$"}],
  "deny": ["MCP002"],
  "semantic_threshold": 0.75
}

完整文件请参见 examples/policy.json。请将策略文件纳入源代码管理,并将变更视为安全敏感配置进行审核。

Docker 动态验证

动态测试需明确选择启用,且仅限于你拥有的服务或本地测试夹具。它需要明确确认、预先构建的本地镜像、明确指定的高置信度工具名称以及 JSON 参数。运行器会创建全新的 Docker 容器,不提供网络、不挂载主机目录、将根文件系统设为只读、移除功能、使用非特权用户、设置资源限制和调用超时。它绝不会将扫描进程的环境变量转发到容器中。

mcpsentinel scan "python -m my_server" --transport stdio \
  --dynamic --i-own-this-target \
  --dynamic-image my-mcp-server:test \
  --dynamic-entrypoint "python -m my_server" \
  --dynamic-invoke 'unsafe_tool={"fixture": true}'

动态服务镜像必须已存在于本地;MCPSentinel 使用 --pull=never。每次显式工具调用都会获得独立的全新容器/会话,因此一个选定工具的状态不会影响另一个工具。常规元数据扫描无需 Docker。动态响应仅以 SHA-256 摘要和内容类型摘要的形式保留。计算摘要之前,MCP SDK 仍需解码动态响应,因此只能调用你拥有且信任其响应行为的夹具/服务。

对于每次自有目标调用,MCPSentinel 会记录调用前后 Docker 进程数量,以及写时复制文件系统变更,格式为 before → after 并附带差值。如果 Docker 输出达到收集上限,则会将遥测数据标记为已截断;同时绝不保留进程参数或文件系统路径。调用结束后仍在运行的额外进程会产生 MCP-D002;这只是后台工作的审核信号,并非主机逃逸的证据。类似凭据的响应内容会产生 MCP-D001,且不会将响应文本写入磁盘。这种有界遥测不会跟踪系统调用、检查任意环境变量读取,也无法证明没有尝试建立网络连接——容器的 --network=none 边界仍是网络控制措施。

仓库包含一个特意限制为仅在本地运行的 Docker 夹具,用于端到端验证此边界。它不包含在常规测试套件中,因为它需要正在运行的 Docker 守护进程并会构建镜像:

MCPSENTINEL_RUN_DOCKER_TESTS=1 pytest tests/test_dynamic_docker_e2e.py

GitHub Action

仓库根目录是一个复合 GitHub Action。它会安装 MCPSentinel、恢复限定作用域的基线缓存、生成 SARIF,并在达到所选严重级别时失败。它不会启用动态测试。从其他仓库引用某个发布标签;为加强供应链控制,建议固定到完整的提交 SHA。

- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
  with:
    python-version: "3.12"
- uses: gentaArnezzi/[email protected]
  id: mcpsentinel
  with:
    target: https://mcp.example.com/mcp
    transport: http
    fail-on: high
    policy: .mcpsentinel/policy.json
- uses: github/codeql-action/upload-sarif@d6317709a54fd87078d323eeb0e48ec331c8e621 # v3
  if: always()
  with:
    sarif_file: ${{ steps.mcpsentinel.outputs.sarif }}

该 Action 使用 ${{ github.base_ref || github.ref_name }} 限定缓存作用域。因此,在 main 上推送会使用 main 信任作用域,而向 main 发起的拉取请求会恢复同一已批准基线,而不是创建合成的 42/merge 作用域。拉取请求只能恢复缓存,绝不能保存替代的受信任基线;成功的受信任推送/工作流运行可以保存不可变的按运行划分的缓存。缓存只是工作流便利状态,不能替代受保护分支或代码审查。通常情况下,即使 fail-on 的结果导致失败,也仍会写入 SARIF 报告并输出 definition-fingerprint,然后返回状态码 1;因此,必须使用 if: always() 上传步骤,以便在安全门禁失败时保留证据。

若要批准基线,先审查扫描输出的 definition-fingerprint。然后,在受保护分支上单独运行受信任的工作流,并传入该确切值。该 Action 会重新发现服务;如果其定义已更改,就会拒绝批准。不要为贡献者发起的拉取请求启用批准功能。

- uses: gentaArnezzi/[email protected]
  if: github.event_name == 'push' && github.ref == 'refs/heads/main'
  with:
    target: https://mcp.example.com/mcp
    transport: http
    fail-on: none
    approve-baseline-fingerprint: "sha256:<fingerprint-you-reviewed>"

该 Action 默认拒绝 stdio 目标,因为扫描此类目标会在 GitHub runner 上启动进程。只有在受信任的受保护推送工作流中,扫描你控制的源代码时,才启用此类目标;绝不要在不受信任的拉取请求或 fork 中启用:

- uses: gentaArnezzi/[email protected]
  if: github.event_name == 'push' && github.ref == 'refs/heads/main'
  with:
    target: python server.py
    transport: stdio
    allow-stdio-execution: "true"

仅当选择 judge: openai 或 auto 时,才在工作流中设置 OPENAI_API_KEY;默认仍为 heuristic。例如,只向扫描步骤提供 GitHub Actions 密钥:env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}。

MCP 原生扫描器

运行 mcpsentinel-mcp,即可通过 stdio 将扫描器作为 MCP 工具 scan_mcp_server 提供。它的限制有意多于 CLI:只能扫描由运维人员加入允许列表的 HTTP 目标。它会拒绝目标 stdio 命令、动态执行和基线批准,因此 MCP 客户端无法将扫描请求转变为本地进程执行,也无法悄然更改信任快照。其结构化响应采用与 JSON 和 HTML 报告相同的凭据安全序列化方式。

export MCPSENTINEL_ALLOWED_HOSTS="mcp.example.com,localhost"
mcpsentinel-mcp

允许列表接受 host 或精确的 host:port。不允许 HTTP 重定向;每个发现会话的时限为 30 秒;MCP 解码前的原始 HTTP 响应大小上限为 2 MiB;默认拒绝私有或保留地址。经过验证的 DNS 地址集合会固定用于 HTTP 传输,同时原始主机名仍用作 HTTP Host 和 TLS SNI 名称;即使明确允许受信任的私有网络,此规则也同样适用,可防止再次进行 DNS 查询后更改连接地址。

可选的运维人员设置包括 MCPSENTINEL_MCP_BASELINE_DIR、MCPSENTINEL_RULES_PATH、MCPSENTINEL_POLICY_PATH、MCPSENTINEL_MCP_JUDGE 和 MCPSENTINEL_MCP_JUDGE_MODEL。MCP 调用方无法选择任意策略文件或基线路径,MCP 原生扫描也绝不会批准基线。对于受信任的 stdio 服务,请使用人工操作的 CLI:审查其扫描指纹,然后使用 mcpsentinel baseline approve 和该指纹进行批准。

注册表发布

MCPSentinel 已发布到 PyPI,包名为 mcp-guardian-scan,也已发布到官方 MCP 注册表。由于 mcpsentinel 不可用,PyPI 包使用了不同名称;产品名称、导入包和 CLI 仍为 MCPSentinel 和 mcpsentinel。

具体的 registry/server.json 与包版本保持锁定。发布工作流会构建并审核构件,通过可信发布将其发布到 PyPI,然后通过 GitHub OIDC 提交匹配的注册表元数据。有关发布详情,请参阅 registry/README.md 和官方包类型文档。

容器镜像

每次非预发布的 GitHub Release 都会向 GitHub Container Registry 发布带版本号的镜像和 latest:

docker pull ghcr.io/gentaarnezzi/mcpsentinel:0.8.8
docker run --rm ghcr.io/gentaarnezzi/mcpsentinel:0.8.8 scan https://mcp.example.com/mcp --transport http

首个 GHCR 包可能需要由仓库所有者在 GitHub Packages 中将其可见性设为公开。对于本地开发,请直接构建扫描器镜像:

docker build -t mcpsentinel:local .
docker run --rm mcpsentinel:local scan https://mcp.example.com/mcp --transport http

该镜像有意不包含 Docker socket,因此无法运行动态层。请在配置了 Docker 的可信主机上运行动态验证。

数据集

datasets/vulnerable_by_design 保存了受控的描述符级基准真值,可用于覆盖每条默认静态规则的回归测试。它可确定性地扩展为 200 个合成描述符:35 个手工整理的对照项和 165 个模板生成的变体。数据集包含安全的硬负例、Unicode/零宽字符规避、非英语对照项、元数据/架构变体,以及有意未覆盖的对照项;不包含真实的第三方目标或可运行的破坏性载荷。标注协议记录了数据来源和审核约定。

使用离线评判器运行可复现的准确度和耗时测量:

mcpsentinel benchmark datasets/vulnerable_by_design/manifest.json --format json --output benchmark.json

基准测试会根据数据集预期应报告的规则,同时衡量原始静态候选项和语义发现结果。报告包括精确率、召回率、误报率、F1、混淆矩阵计数、阶段耗时、语义评估调用次数、分类别明细、数据来源计数,以及估算的 API 成本(离线启发式方法为 $0;未配置服务提供商定价时为 n/a)。其 JSON 和终端报告包含源清单 SHA-256 和扫描器版本,以便追溯。有 10 个有界抓取对照项会被有意计为静态误报、语义真负例,因此在 CI 或发布审核中可以发现降噪能力回退。

报告会明确给出两个分母:精确的描述符/规则对,以及包含任意发现结果的描述符。规则对的负例包含不适用于特定描述符的规则,因此该误报率并不代表开发者收到嘈杂结果的概率。在 60 个合成负例描述符中,静态分析会标记 10 个(16.7%);启发式分诊不会标记任何一个。描述符指标较为粗略:对阳性描述符,即使检测到的是错误规则,也仍计为检测到该描述符。这两个指标都不代表独立测试过的服务数量。请参阅可复现的 JSON 结果。

在包含 200 个用例的数据集上,使用离线启发式方法和默认阈值(0.70)时,静态候选项的精确率为 0.932、召回率为 0.958、F1 为 0.944、误报率为 0.005(TP=136、FP=10、TN=1848、FN=6)。语义分诊的精确率为 1.000、召回率为 0.965、F1 为 0.982、误报率为 0.000(TP=137、FP=0、TN=1858、FN=5)。专用的服务端指令路径找回了一个静态分析单独无法产生的信号。有意设置的 5 个漏检项——4 个非英语通用提示词注入对照项和 1 个元数据位置相关的破坏性操作对照项——仍会显示出来,而不是被排除。SSRF 类别说明了为何要同时报告两个阶段:其受控用例的静态精确率为 0.545,而语义精确率为 1.000。

这是可复现的回归信号,并不代表公开 MCP 服务的准确度、召回率、现实世界误报率,也不表示优于其他扫描器。165 个生成的变体有助于覆盖测试,但不是 165 个独立的现实世界观测样本。

精选公开元数据 v2

datasets/curated_public_metadata_v2 新增了 428 个字面工具描述符,来自固定源代码版本、采用宽松许可证的 MCP 实现:329 个来自 AWS Labs 的 Apache-2.0 许可证仓库,99 个来自 GitHub 的 MIT 许可证 MCP 服务。每个案例都记录了仓库、完整提交 SHA、许可证、源文件路径、行号和源文件 SHA-256。提取器只读取本地检出内容,从不联系或调用上游 MCP 服务。

这是一个负对照基准:预计普通的文档化工具元数据不会产生任何无限风险发现。能够执行范围受限的云端删除或写入操作的工具,并不会自动构成漏洞,因此语料不会将源项目标记为不安全。在 v0.8.8 的十信号基准契约下,启发式方法在 4,280 个描述符/规则负样本对中产生了零个候选项,误报率为 0.000。由于没有带标签的正样本,精确率、召回率和 F1 正确显示为 n/a,而不是 1.000。

mcpsentinel benchmark datasets/curated_public_metadata_v2/manifest.json \
  --judge heuristic --format json --output benchmark-v2.json

v2 语料经过一位维护者审核,并明确标记为 independent-review-pending。它强化了公开元数据误报方面的证据;但不能证明公开服务的召回率、现实世界漏洞的普遍程度,或优于其他扫描器。

已授权元数据正样本 v3

datasets/authorized_positive_metadata_v3 新增了 16 个字面且具有恶意意图的元数据样例,来自 Cisco 采用 Apache-2.0 许可证的 MCP Scanner 评估语料。Cisco 第一方场景标签涵盖提示词注入和未经授权的代码执行;MCPSentinel 将它们映射为 18 个规则/案例对。每个案例都固定了源文件路径、函数行号、文件摘要和完整提交。提取器只读取本地检出内容。

mcpsentinel benchmark datasets/authorized_positive_metadata_v3/manifest.json \
  --judge heuristic --format json --output benchmark-v3.json

V3 是校准回归对照,并非留出准确性研究:其标签为 0.7.0 中新增的窄范围元数据规则提供了依据。在这一冻结配置下,它报告了全部 18 个带标签的案例对,而 428 个案例的 v2 公开负对照仍为零候选项。这是有用的证据,表明此次细化没有在这些确切的公开快照中造成误报;但不能证明现实世界的召回率。一位维护者已审核 v3 映射;引用时若超出回归覆盖范围,请参阅独立审核协议。

服务指令 v4

datasets/server_instructions_v4 为专用的 MCP-S001 路径新增了 28 个精选的纯元数据对照:五条良性英语指令和五条恶意英语指令、五条良性非英语指令和五条恶意非英语指令、四个 Unicode/零宽混淆案例,以及四个含糊的外部传输案例。

mcpsentinel benchmark datasets/server_instructions_v4/manifest.json \
  --judge heuristic --format json --output benchmark-server-instructions.json

在 v0.8.8 启发式配置下,整体语义测量结果为精确率 1.000、召回率 1.000、F1 1.000,误报率 0.000(TP=27、FP=0、TN=253、FN=0)。专用的 MCP-S001 英语和非英语分段的精确率/召回率/F1 均为 1.000,各包含五个良性案例和五个恶意案例。静态分析单独只能召回语料中 27 个带标签案例对的 0.333,这说明了独立语义路径存在的原因。这些是精选的回归对照,并非关于现实世界普遍程度或准确性的独立证据。

MCPSentinel 可以和不可以告诉你的内容

MCPSentinel 可作为以下三种工作流的预检信号:个人开发者决定是否深入检查 MCP 服务;维护者在发布前自行审核元数据;安全团队添加非阻断式或需审核的 CI 门禁。

它会发现 MCP 服务公开的元数据;但不会读取服务的源代码、证明授权边界,也无法保证运行时行为与如实的描述一致。报告干净并不能证明服务安全。动态验证的范围则刻意更窄:它只能调用你拥有的镜像中明确指定的高置信度工具,并使用你提供的参数。其进程和文件系统计数器只能提供有限的审核证据,并非完整的行为监测。它不适合用来探测任意公开服务。

默认扫描器为只读。它绝不会调用发现的工具、跟随 HTTP 重定向,或通过 GitHub Action 或 MCP 原生服务启用动态执行。请将结果作为审核证据,并结合源代码审核、依赖项审核、权限和出站流量控制,以及常规事件响应流程。

开发

pytest
ruff check .

本项目刻意减少依赖:mcp 负责协议发现,Rich 用于呈现交互式终端视图,而核心规则引擎、快照存储和报告编写器使用标准库。

安全

有关漏洞报告和受支持版本的信息,请参阅 SECURITY.md。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。