MCP安全代理
一个可配置的代理 模型上下文协议(MCP) 服务器。位于MCP客户端(如Claude Desktop)和一个或多个上游MCP服务器之间,应用插件管道来记录、过滤和重写请求和响应。
作为MCP代理,它具有您所期望的所有功能。当你将其与Claude Code技能结合使用以生成更好的过滤器时,它的真正优势就来了。
预期工作流程: 将代理指向MCP服务器,然后使用内置的Claude Code技能(/probe-mcp 和 /propose-filters)让Claude分析服务器的安全表面并生成适当的缓解措施——从简单的YAML配置到自定义的内容感知插件。代理和插件提供运行时机制;Claude负责分析和代码生成的繁重工作。
如果您的服务器敏感或有生产数据(在生产中测试? _真的?_),您可以使用MCP代理生成日志。一旦你有足够的日志,运行 /propose-filters 克劳德会这么做的。如果你的日志中有缺口,Claude会尝试识别它们,这样你就可以生成更多的日志并缩小缺口。
快速开始
需要Python 3.12+和 紫外线。您将对代码库进行大量更改,因此请为自己克隆它。
git clone
cd mcp-security-proxy-maker
uv run mcp-proxy --config examples/basic_proxy.yaml然后将Claude Code重新打开到此存储库,以便它获取 .mcp.json 文件并连接到服务器。每次重新启动服务器时,请重新运行 /mcp 并重新连接到MCP服务器。
配置
配置文件是YAML。字符串值支持 ${ENV_VAR} 扩张。
proxy:
name: my-proxy # Name advertised to MCP clients
transport: stdio # "stdio" | "http" | "streamable-http"
host: "127.0.0.1" # HTTP only
port: 8000 # HTTP only
global_plugins: # Applied to all upstreams (outermost layer)
- type: logging
log_file: logs/all.jsonl
upstreams:
- name: filesystem
namespace: fs # Tools exposed as "fs_read_file", etc.
transport:
type: stdio
command: uvx
args: ["mcp-server-filesystem", "/home/user/docs"]
env:
SOME_VAR: "${ENV_VALUE}"
cwd: /optional/working/dir
plugins:
- type: filter
block_tools: ["write_*", "delete_*"]
- type: rewrite
tool_renames:
read_file: read_document
argument_overrides:
read_file:
encoding: "utf-8"
- type: logging
log_file: logs/fs.jsonl
- type: inventory
inventory_file: logs/fs_inventory.json
- name: remote
namespace: api
transport:
type: http
url: "https://example.com/mcp"
headers:
Authorization: "Bearer ${API_TOKEN}"
plugins:
- type: filter
allow_tools: ["search", "get_*"]
- name: notion
transport:
type: http
url: "https://mcp.notion.com/mcp"
oauth:
client_id: "${NOTION_CLIENT_ID}"
client_secret: "${NOTION_CLIENT_SECRET}"
scopes: []OAuth 2.0
HTTP上游可以使用OAuth代替(或除了)静态标头。添加一个 oauth 使用以下命令阻止传输配置 client_id, client_secret,以及 scopes。令牌将持久化到 .oauth2// 因此,它们能够在代理重启后幸存下来。在第一次连接时,代理将打开OAuth授权流的浏览器。
所有三个字段都是可选的,默认为 null --上游服务器的OAuth发现端点确定需要什么。
如果客户端通过网络主机名访问您的代理,例如 gateway.local,不需要是OAuth回调URL。回调仅在上游登录流程中由代理计算机使用。对于像Notion这样的提供商,注册一个环回重定向URI,例如 http://localhost:54321/callback,在代理计算机上完成一次OAuth流,然后让客户端继续使用正常的代理端点 http://gateway.local: /mcp.
无头服务器设置
如果代理在无头远程机器上运行,请使用SSH端口转发,以便笔记本电脑上的浏览器可以代表服务器完成localhost回调:
ssh -L 54321:127.0.0.1:54321 user@gateway.local然后:
- 在配置了Notion OAuth上游的远程计算机上启动代理。
- 保持SSH隧道打开。
- 启动代理的OAuth流程。
- 在笔记本电脑上完成浏览器登录。
- 让提供者重定向到
http://localhost:54321/callbackSSH隧道将该回调转发到代理计算机。
首次成功登录后,代理将令牌存储在 .oauth2//,因此客户端可以继续正常使用远程代理,而无需重复浏览器流程,除非刷新令牌过期或被撤销。
插件执行顺序
插件按所列顺序运行。对于请求,plugin\[0\]首先运行;对于响应,plugin\[0\]也会首先运行(它会在plugin\[1\]之前看到响应)。全局插件包裹了每个上游插件,因此全局运行在最外层。
插件
logging
每次操作向文件追加一行JSON。
| 字段 | 默认值 | 描述 |
|---|---|---|
log_file | required | JSONL输出文件的路径。父目录是自动创建的。 |
include_payloads | true | 在日志条目中包含请求参数和响应文本。 |
methods | all | 将日志记录限制为特定的MCP方法,例如。 ["tools/call"]. |
max_bytes | none | 当日志文件超过此字节大小时,请旋转日志文件。如果未设置,则不旋转。 |
max_backups | 5 | 要保留的轮换备份文件数(.1, .2, ...). |
日志输入字段:
在收到响应后,每个调用(工具/资源/提示)都会被记录为一个成对的条目,结合请求和响应数据。
| 字段 | 描述 |
|---|---|
schema_version | 总是 2 |
ts | ISO 8601 UTC时间戳(响应) |
method | MCP方法(tools/call, resources/read等等) |
tool_name | 工具名称(仅限工具操作) |
resource_uri | 资源URI(仅限资源操作) |
prompt_name | 提示名称(仅提示操作) |
arguments | 请求参数(如果为null include_payloads: false) |
is_error | 响应是否为错误(仅限工具调用) |
content_blocks | 响应的内容块数量(仅限工具调用) |
content_length_chars | 响应的总文本长度(仅限工具调用) |
duration_ms | 往返时间(毫秒) |
items | 工具/资源/提示名称列表(仅列出事件) |
item_count | 项目计数(仅列出事件) |
filter
阻止或隐藏工具、资源和提示。在两个列表中都执行了策略(隐藏 tools/list)在呼叫时(引发错误)。
每个类别有两种互斥模式:
- 允许列表 (
allow_tools):只能访问匹配的名称;其他一切都被封锁了。 - 拒绝列表 (
block_tools):匹配的名称被阻止;其他一切都会过去。
价值观是 通配符模式 (* 匹配名称中的任何内容, ? 匹配一个字符)。
- type: filter
allow_tools: ["read_*", "list_*"] # allow-list mode
block_resources: ["secret://*"] # deny-list mode for resources
block_prompts: ["admin_*"]rewrite
修改工具名称和调用参数。所有重命名都是对称的:插件在两个方向上都可以转换,因此客户端始终可以看到公开的名称。
- type: rewrite
tool_renames:
upstream_name: exposed_name # upstream -> what client sees
argument_overrides:
upstream_name: # keyed by upstream name
arg_key: forced_value # merged after user args; overrides win
response_prefix: "Source: " # prepended to all text content blocks注: 如果 filter 插件堆叠在 rewrite 插件在同一列表中,过滤器应使用 暴露 (重命名后)工具名称,因为重命名后会看到列表。
notion_access
Notion MCP上游的基于内容的访问控制。使用嵌入在每个页面第一行的表情符号标记,强制每个页面、每个页面的读/写权限。权限被透明地检查和缓存,子页面必须继承父标记行,图像更改通过专用的图像工具进行。看 README_NOTION.md 了解全部细节。
- type: notion_access
bot_name: OcelliBothive_access
Hive MCP上游的工作空间和项目范围实施。将代理限制为已配置的 workspaceId 以及一个明确的项目ID列表。验证写入工具 actionIds 使用从填充的会话生存期缓存属于允许的项目 getActions 响应。看 README_HIVE.md 了解全部细节。
- type: hive_access
workspace_id: "EXAMPLE_WORKSPACE_ID"
allowed_project_ids:
- "EXAMPLE_PROJECT_ID_1"
- "EXAMPLE_PROJECT_ID_2"inventory
编写一个打印精美的JSON文件,其中包含最新已知的工具、资源和提示清单。每次列表钩子触发时,文件都会被重写,因此它总是反映最新的状态。
| 字段 | 默认值 | 描述 |
|---|---|---|
inventory_file | required | JSON输出文件的路径。父目录是自动创建的。 |
快照格式:
{
"ts": "2026-03-07T12:00:00.000000+00:00",
"tools": [
{
"name": "fetch",
"description": "Fetches a URL from the internet.",
"parameters": { "type": "object", "properties": { "url": { ... } } }
}
],
"resources": [
{ "uri": "file:///docs", "name": "docs", "description": "...", "mime_type": "text/plain" }
],
"prompts": [
{ "name": "summarize", "description": "Summarize a document." }
]
}部分以递增方式显示-- tools 在第一个之后出现 tools/list, resources 首先之后 resources/list等等。
Claude代码技能
该项目包括以下两项技能 克劳德代码 使MCP安全分析自动化。预期的工作流程是:
- 设置代理 --创建一个指向上游MCP服务器的配置,并启用日志和清单插件。
- 跑
/probe-mcp--Claude交互式地探测服务器:发现工具,使用安全输入对其进行测试,并(在您的批准下)测试SSRF、路径遍历和其他安全问题。生成结构化报告。 - 跑
/propose-filters--Claude分析了探测结果和审计日志,然后提出了缓解措施。这些范围从简单的YAML过滤器/重写配置到检查请求参数或响应内容的自定义Python插件(例如URL域分配表、PII编辑、元数据门)。Claude编写插件代码、配置模型、服务器连接和测试。
/probe-mcp
系统地探测MCP代理,以映射其功能和安全表面。在运行任何潜在危险的测试(SSRF向量、file://scheme、云元数据端点等)之前,要求明确批准。输出一份结构化的报告,其中包含调查结果和建议。
/propose-filters
分析库存、审计日志和探测结果,从三个层面提出安全缓解措施:
- 级别1-YAML过滤器配置:按glob模式阻止或允许工具/资源/提示
- 级别2——YAML重写配置:将特定参数锁定为安全值
- 第三级——自定义插件:检查请求参数或响应体的内容感知Python插件(例如限制
fetch工具到批准的域,从响应中编辑PII,通过工作区ID读取Notion)
在实施之前,与您一起审查每个提案。对于自定义插件,遵循完整的项目约定:配置模型、插件类、服务器连接和测试。
代理功能
底层代理基于FastMCP,并具有所有预期的功能:
- 多上游聚合 --使用命名空间工具将多个MCP服务器代理到单个端点中
- 插件管道 --按上游或全局堆栈日志记录、过滤和重写插件
- 过滤器插件 --按glob模式允许列表或拒绝列表工具、资源和提示
- 重写插件 --重命名工具、注入固定参数、前缀响应文本
- 日志记录插件 --所有操作的结构化JSONL审计日志,带有定时
- Notion访问插件 --使用页面内权限标记对每个bot、每个页面进行读/写访问控制;权限被透明地获取和缓存
- Hive访问插件 --Hive上游的工作空间+项目分配列表执行,带有操作所有权验证
- 库存插件 --所有可用工具、资源和离线分析提示的JSON快照
- Stdio和HTTP传输 --上游和代理传输是独立配置的
- OAuth 2.0支持 --HTTP上游可以通过OAuth进行身份验证,并使用持久令牌存储
- 环境变量扩展 —
${VAR}配置值中的引用
示例
| 文件 | 描述 |
|---|---|
| examples/basicproxy.yaml | 透明的单一上游代理 |
| 示例/multi_upstream.yaml | 两个具有命名空间和共享审计日志的上游 |
| examples/security_filter.yaml | 全栈:日志+过滤+重写 |
发展
# Install dev dependencies
uv sync --group dev
# Run tests
uv run pytest tests/ -v
# Run a specific example
uv run mcp-proxy --config examples/basic_proxy.yamlCLI参考
Usage: mcp-proxy [OPTIONS]
Options:
-c, --config PATH Path to proxy YAML config file. [required]
--transport [stdio|http|streamable-http]
Override the transport from the config file.
--host TEXT Override the host for HTTP transport.
--port INTEGER Override the port for HTTP transport.
--help Show this message and exit.全部
- \[\]Claude交互式过滤和简化日志的一些方法。
