openai-agents-python MCP 工具过滤实战:用静态白名单/黑名单限制 Filesystem Server 暴露的工具

发布时间:2026/9/12 18:10:45
openai-agents-python MCP 工具过滤实战:用静态白名单/黑名单限制 Filesystem Server 暴露的工具 openai-agents-python MCP 工具过滤实战用静态白名单/黑名单限制 Filesystem Server 暴露的工具【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python导读本文基于 openai-agents-python 仓库中的 MCP Tool Filter 示例examples/mcp/tool_filter_example/README.md完整讲解如何在多 Agent 工作流中接入基于 stdio 传输的 MCP 文件系统服务器通过create_static_tool_filter静态工具过滤器只向模型暴露指定的安全工具并配合require_approvalalways与代码内自动批准机制实践 Human-in-the-LoopHITL审批流程。读完本文你将掌握 MCP 服务器的启动参数、静态工具过滤的底层实现原理、拦截被屏蔽工具的验证方法以及一套可直接复制运行的最小可运行示例。一、示例概览这个示例要解决什么问题该示例是 JS 版examples/mcp/tool-filter-example.ts的 Python 移植聚焦四个目标通过npx在本地启动官方 filesystem MCP 服务器modelcontextprotocol/server-filesystem应用静态工具过滤器只允许read_file、list_directory两个只读工具暴露给模型通过实际对话验证被屏蔽的写工具write_file确实不可用开启require_approvalalways审批策略并在代码中自动批准所有中断interruption从而跑通 HITL 审批路径。示例目录结构如下见 examples/mcp/tool_filter_exampleexamples/mcp/tool_filter_example/ ├── README.md # 示例说明 ├── main.py # 可运行的主程序 └── sample_files/ ├── books.txt # 供 filesystem 服务器读取的样例文件 └── favorite_songs.txt二、运行方式与前置条件直接运行uv run python examples/mcp/tool_filter_example/main.py前置条件有两个npx必须位于PATH中示例启动时也会用shutil.which(npx)做显式检查缺失时抛出RuntimeError提示先执行npm install -g npx必须设置OPENAI_API_KEY环境变量供模型调用使用。示例运行时会打印 Trace 链接基于gen_trace_id()生成的trace_id方便在 platform.openai.com/logs/trace 上回放整个 MCP 工具调用过程。三、逐段解析 main.py3.1 自动批准工具调用的辅助函数async def run_with_auto_approval(agent: Agent[Any], message: str) - str | None: Run and auto-approve interruptions. result await Runner.run(agent, message) while result.interruptions: state result.to_state() for interruption in result.interruptions: print(fApproving a tool call... (name: {interruption.name})) state.approve(interruption, always_approveTrue) result await Runner.run(agent, state) return cast(str | None, result.final_output)这是 HITL 路径的核心循环Runner.run返回结果后若存在interruptions即工具调用等待人工审批则进入循环通过result.to_state()把运行状态序列化为可恢复的RunState遍历每个interruption打印工具名并调用state.approve(interruption, always_approveTrue)自动批准always_approveTrue表示对本次工具调用授予永久批准后续同工具不再中断用更新后的state重新Runner.run直至没有任何中断最后返回final_output。由于示例配置了require_approvalalways每次工具调用都会产生中断这个循环正是为了在代码中自动完成审批从而在不引入真实人工交互的情况下验证审批链路是否工作。3.2 启动带过滤与审批策略的 MCP 服务器async with MCPServerStdio( nameFilesystem Server with filter, params{ command: npx, args: [-y, modelcontextprotocol/server-filesystem, samples_dir], cwd: samples_dir, }, require_approvalalways, tool_filtercreate_static_tool_filter( allowed_tool_names[read_file, list_directory], blocked_tool_names[write_file], ), ) as server:逐项说明MCPServerStdio基于 stdio 传输的 MCP 服务器实现定义于 src/agents/mcp/server.py通过子进程标准输入/输出与 MCP 服务器通信paramsMCPServerStdioParamsTypedDict镜像mcp.client.stdio.StdioServerParameters支持command、args、env、cwd、encoding等字段见 server.py。此处commandnpx、args[-y, modelcontextprotocol/server-filesystem, samples_dir]表示临时下载并启动官方 filesystem 服务器并以其工作目录cwdsamples_dir作为可访问根目录require_approvalalways审批策略使服务器上所有工具调用都需要批准。除字符串外还支持never、按工具名的字典映射以及带 always/never 工具列表的对象见 server.pytool_filtercreate_static_tool_filter(...)静态工具过滤器白名单放行read_file、list_directory黑名单剔除write_file。MCPServerStdio还提供其他可配置项例如cache_tools_list缓存工具列表避免每次往返服务器显著降低延迟、client_session_timeout_secondsClientSession 读超时默认 5 秒、max_retry_attempts与retry_backoff_seconds_baselist_tools/call_tool 失败重试与指数退避、use_structured_content是否直接使用tool_result.structured_content、tool_input_guardrails/tool_output_guardrails服务器级工具守卫等均可按需组合使用。3.3 绑定 MCP 服务器的 Agentagent Agent( nameMCP Assistant, instructions( Use only the available filesystem tools. All file paths should be absolute paths inside the allowed directory. If a user asks for an action that requires an unavailable tool, explicitly explain that it is blocked by the tool filter. ), mcp_servers[server], )mcp_servers[server]把上面创建的 MCP 服务器挂载到 Agent 上模型即可调用服务器暴露的工具instructions引导模型只使用可用工具、路径必须是允许目录内的绝对路径当用户请求需要被过滤工具时明确说明该操作被工具过滤器屏蔽。这是让“拦截行为可观察”的关键提示词设计。3.4 两轮验证对话trace_id gen_trace_id() with trace(workflow_nameMCP Tool Filter Example, trace_idtrace_id): print(fView trace: https://platform.openai.com/logs/trace?trace_id{trace_id}\n) result await run_with_auto_approval( agent, fList the files in this allowed directory: {samples_dir} ) print(result) blocked_result await run_with_auto_approval( agent, ( fCreate a file at {target_path} with the text hello. If you cannot, explain that write operations are blocked by the tool filter. ), ) print(\nAttempting to write a file (should be blocked):) print(blocked_result)gen_trace_id()生成全局唯一追踪 IDtrace(workflow_name..., trace_id...)包裹整个工作流以进行端到端追踪第一轮要求列出允许目录下的文件——list_directory在白名单内工具可用模型应能成功返回sample_files下的books.txt、favorite_songs.txt等文件第二轮要求向target_path即sample_files/test.txt写入文本——write_file已被过滤工具不存在模型应当返回“写入操作被工具过滤器屏蔽”的说明。目标路径特意放在服务器根目录下确保失败原因确实是过滤而非路径权限。四、深入底层create_static_tool_filter 与过滤执行原理4.1 静态过滤器构造器create_static_tool_filter定义于 src/agents/mcp/util.py签名如下def create_static_tool_filter( allowed_tool_names: list[str] | None None, blocked_tool_names: list[str] | None None, ) - ToolFilterStatic | None:其行为当allowed_tool_names与blocked_tool_names都为None时返回None表示不过滤否则构造并返回ToolFilterStatic字典仅包含显式提供的键。ToolFilterStatic是一个 TypedDict见 util.pyclass ToolFilterStatic(TypedDict): allowed_tool_names: NotRequired[list[str]] # 白名单仅这些工具可用 blocked_tool_names: NotRequired[list[str]] # 黑名单这些工具被过滤掉4.2 静态过滤的判定顺序在 src/agents/mcp/server.py 中_apply_tool_filter会先判断tool_filter的类型是dict即ToolFilterStatic→ 走_apply_static_tool_filter是可调用对象ToolFilterCallable→ 走_apply_dynamic_tool_filter实现基于RunContextWrapper、Agent 与服务器名的动态过滤返回True保留、False剔除且支持同步/异步函数过滤函数抛异常时该工具会被默认剔除以保证安全。_apply_static_tool_filterserver.py的执行顺序是若存在allowed_tool_names先做白名单过滤filtered_tools [t for t in filtered_tools if t.name in allowed_names]若存在blocked_tool_names再对剩余集合做黑名单剔除filtered_tools [t for t in filtered_tools if t.name not in blocked_names]。因此当白名单与黑名单同时给出时先应用白名单、再剔除黑名单中的工具。这与 docs/mcp.md 的说明一致同时提供allowed_tool_names和blocked_tool_names时SDK 先应用白名单再从剩余工具中移除黑名单项。过滤发生在工具列表暴露给模型之前见 server.py 的get_tools调用链被过滤的工具对模型完全不可见因此模型不会尝试调用它——第二轮对话中模型“解释写入被屏蔽”的行为正是这一机制的外在表现。4.3 静态与动态过滤的取舍静态过滤本示例采用声明式、零开销、可静态分析适合“工具集固定、安全策略稳定”的场景动态过滤ToolFilterCallable签名见 util.py接收ToolFilterContext含run_context、agent、server_name和待判定工具可在每次获取工具列表时按运行上下文做细粒度决策适合“同一服务器在不同 Agent 或不同会话中暴露不同工具”的场景。五、require_approval 与 HITL 审批路径require_approvalalways使服务器上的每次工具调用都进入审批流程产生interruptions。示例的run_with_auto_approval展示了标准的 HITL 处理模式首次Runner.run返回带interruptions的结果result.to_state()导出可恢复状态遍历interruptions用state.approve(interruption, always_approveTrue)批准以新状态重新运行直到无中断。在生产场景中将state.approve(...)替换为真实的人工确认如文件审批、Webhook、聊天确认即可把示例无缝改造成带人工审批的 MCP 工具调用流水线。仓库中还提供了更完整的 HITL 会话示例如 examples/memory/file_hitl_example.py、examples/memory/memory_session_hitl_example.py可供参考。六、预期输出与结果验证运行成功时第一轮应看到模型返回sample_files目录中的文件清单第二轮打印Attempting to write a file (should be blocked): 模型说明写入操作被工具过滤器屏蔽的文本你还可以在 Trace 页面确认两轮对话的工具列表第一轮可见read_file/list_directory调用第二轮模型未产生write_file调用——这正是“过滤发生在工具暴露之前”的直接证据。若要进一步验证过滤效果可修改 main.py 中的allowed_tool_names/blocked_tool_names列表后重跑例如把list_directory也加入黑名单观察模型在第一轮是否还能列出目录。七、小结通过本示例你可以掌握 openai-agents-python 中 MCP 集成的三个关键能力接入用MCPServerStdionpx快速拉起任意 stdio 型 MCP 服务器filesystem 只是其中一种收敛用create_static_tool_filter以白名单/黑名单方式把工具面收敛到最小必要集合从源头杜绝模型调用危险工具先白名单、后黑名单的判定顺序见 server.py管控用require_approval把工具调用纳入审批策略配合RunState.approve实现自动或人工的 HITL 审批让多 Agent 工作流中的外部工具调用始终处于可控范围。这套“MCP 服务器 静态过滤 审批策略”的组合是构建安全、可审计的工具调用链路的通用范式可直接迁移到数据库访问、代码执行、文件操作等任何基于 MCP 的工具集成场景。【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考