
Envoy MCP HTTP 过滤器 attribute_source 配置详解BODY / VERIFY / HEADERS 三种属性提取模式【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy本文介绍 Envoy 官方 MCPModel Context ProtocolHTTP 过滤器中新增的attribute_source配置项它决定了过滤器从何处获取 MCP 请求属性是仅从请求体JSON-RPC 2.0 消息解析还是结合Mcp-Method/Mcp-Name请求头做一致性验证或是完全信任请求头以跳过请求体解析的快速路径。读完本文你将掌握三种模式的语义、适用场景、请求头与 JSON 路径的映射关系、完整 YAML 配置写法以及基于源码的关键执行流程与边界回退行为。背景MCP 过滤器与请求属性的用途Envoy 的 MCP HTTP 过滤器扩展名为envoy.filters.http.mcp类型 URL 为type.googleapis.com/envoy.extensions.filters.http.mcp.v3.Mcp详见 api/envoy/extensions/filters/http/mcp/v3/mcp.proto会检查进入网关的 MCP 流量并从 MCP 请求中提取属性。这些属性默认以envoy.filters.http.mcp为命名空间写入动态元数据dynamic metadata可供后续的 RBAC 过滤器、ext_authz过滤器或路由逻辑消费典型场景包括基于 MCP 方法名如tools/call、resources/read、initialize做细粒度鉴权基于params.name、params.uri、params.taskId等参数做资源级授权例如只允许调用名为get_weather的工具与clear_route_cache配合根据解析出的 MCP 元数据重新选择路由。在早期实现中过滤器必须缓冲并解析请求体才能获得这些属性。随着 MCP 客户端逐步支持在请求头中声明方法名与资源标识Envoy 新增了attribute_source配置允许在解析请求体与信任请求头之间做出显式选择从而在只关心方法名和标识符的场景下完全跳过请求体解析显著降低代理开销。该特性对应的变更记录见 changelogs/current/new_features/mcp__header_attribute_source.rst。AttributeSource 枚举三种模式的定义attribute_source字段Mcp消息的第 9 个字段校验规则为defined_only的类型是AttributeSource枚举在 api/envoy/extensions/filters/http/mcp/v3/mcp.proto 中定义如下枚举值名称语义0BODY从请求体解析属性并忽略Mcp-Method/Mcp-Name属性头。这是过滤器最传统、最严格的行为所有属性均来自对 JSON-RPC 2.0 请求体的解析。1VERIFY使用 MCP 属性头Mcp-Method/Mcp-Name并在解析请求体后验证头中携带的值与请求体解析出的值一致不一致则拒绝请求。2HEADERS信任Mcp-Method和Mcp-Name请求头method与由Mcp-Name携带的方法特定标识符对应params.name、params.uri或params.taskId直接取自请求头当没有其他内容需要解析请求体时完全跳过 body 解析走快速路径。三种模式之间存在清晰的递进关系BODY是只信 body、VERIFY是头体并用、以 body 为准校验头、HEADERS是只信头、尽力避免解析 body。选择哪种模式取决于你对下游 MCP 客户端是否可靠携带请求头的信任程度以及对延迟和资源开销的敏感度。HEADERS 模式无请求体的快速路径快速路径的判定逻辑HEADERS模式的核心是能不用 body 就不用 body。过滤器在decodeHeaders阶段读取mcp-method与mcp-name请求头头名称常量定义见 source/extensions/filters/common/mcp/constants.h并通过 mcp_filter.cc 中的needsBody()决定是否仍然需要缓冲请求体bool McpFilter::needsBody() const { // HEADERS 模式之外的任何模式都必须解析 body if (config_-attributeSource() ! ...Mcp::HEADERS) { return true; } // 头部属性不完整缺 method 或 name时回退到 body 解析 if (!hasCompleteHeaderAttributes()) { return true; } const auto parser_config parserConfig(); const std::string name_path parser_config.getNameAttributePath(header_method_); // 只要存在除 method 和当前方法的 name 路径之外的提取规则就必须解析 body for (const auto rule : parser_config.getFieldsForMethod(header_method_)) { if (rule.path ! method rule.path ! name_path) { return true; } } // trace context / baggage 传播与重复键检查也依赖 body if (config_-propagateTraceContext().has_value() || config_-propagateBaggage().has_value() || rejectDuplicateKeys()) { return true; } return false; }从源码可以归纳出HEADERS模式能够真正跳过 body 解析即快速路径生效需要同时满足以下条件Mcp-Method请求头存在且非空hasCompleteHeaderAttributes()的判定见 mcp_filter.cc若该方法存在名称类属性路径如params.name则Mcp-Name头必须存在若该方法本就没有名称属性则Mcp-Name头不是必需的ParserConfig中为该方法配置的提取规则只包含method和该方法的名称路径没有其他 JSON 路径规则未启用propagate_trace_context、propagate_baggage或reject_duplicate_keys这三项都依赖 body 内容。一旦判定needsBody()返回false过滤器设置skip_body_parsing_ true并直接调用populateMetadataFromHeaders()生成元数据随后立刻Continue全程不设置 buffer limit、不缓冲请求体见 mcp_filter.cc。从请求头生成元数据populateMetadataFromHeaders()mcp_filter.cc负责把头部属性写入动态元数据 / filter stateMcp-Method→ 元数据中的method字段Mcp-Name→ 写入到该方法对应的名称路径params.name、params.uri或params.taskId下的嵌套字段若配置了group_metadata_key还会同步写入方法分组名如tool、resource、lifecycle之后按request_storage_mode的设置写入动态元数据和/或 filter state并在配置了clear_route_cache时清除路由缓存以便基于新写入的元数据重新选路。嵌套字段的写入由setNestedStringValue实现mcp_filter.cc它把以.分隔的 JSON 路径逐段展开为嵌套的Protobuf::Struct。Mcp-Name 与 JSON 路径的映射Mcp-Name头的语义是方法特定的标识符具体落到哪个 JSON 路径由McpParserConfig::getNameAttributePath()决定。结合 source/extensions/filters/common/mcp/constants.h 中定义的默认路径和单元测试见 test/extensions/filters/http/mcp/mcp_filter_test.cc可确认以下默认映射MCP 方法Mcp-Name对应的 JSON 路径测试用例tools/callparams.nameHeadersAttributeSourceUsesNamePathmcp_filter_test.ccresources/readparams.uriHeadersAttributeSourceUsesResourceUriPathmcp_filter_test.cctasks/get等任务类方法params.taskIdHeadersAttributeSourceUsesFastPathmcp_filter_test.cc例如一个携带Mcp-Method: tasks/get与Mcp-Name: task-123的 POST 请求在快速路径下生成的元数据等价于从 body{method:tasks/get,params:{taskId:task-123}}解析出的结果methodtasks/get、params.taskIdtask-123。若某方法没有名称类属性getNameAttributePath返回空串则仅凭Mcp-Method即可走快速路径。快速路径的验证不设置 buffer limit单元测试HeadersAttributeSourceUsesFastPath明确断言了快速路径的行为特征EXPECT_CALL(decoder_callbacks_, setBufferLimit(_)).Times(0); EXPECT_EQ(Http::FilterHeadersStatus::Continue, filter_-decodeHeaders(headers, false));即decodeHeaders直接返回Continue、从不调用setBufferLimit与 body 解析路径StopIteration 设置 buffer limit形成鲜明对比。这意味着在高 QPS 的 MCP 网关场景下HEADERS模式可以让过滤器从缓冲并解析 JSON 请求体退化为仅读取两个请求头从而节省内存与 CPU。VERIFY 模式请求头与请求体的一致性校验VERIFY模式面向既要利用请求头、又不愿无条件信任客户端的场景过滤器仍然会缓冲并解析请求体但会把Mcp-Method/Mcp-Name头与请求体解析结果进行比对不一致即拒绝。校验逻辑与失败响应校验由verifyHeaderAttributes()mcp_filter.cc与headerAttributesMatch()mcp_filter.cc实现先比对Mcp-Method头与 body 中的method字段若该方法存在名称路径再比对Mcp-Name头与 body 中该路径的字符串值body 中该字段缺失或类型非字符串也判定为不匹配。校验失败时过滤器递增header_mismatch_统计计数器并返回400 Bad Request本地响应体为MCP header attributes do not match request body见 mcp_filter.cc。对应测试用例覆盖了各类失败与成功场景缺少Mcp-Method头被拒绝VerifyRejectsMissingMethodHeadermcp_filter_test.cc头与 body 的方法不一致被拒绝VerifyRejectsMethodMismatchmcp_filter_test.ccMcp-Name与 body 中的params.taskId不一致被拒绝VerifyRejectsNameMismatchmcp_filter_test.cc头与 body 完全一致则放行VerifyAcceptsMatchingAttributesmcp_filter_test.cc。与 HEADERS 模式的差异关键差异在于VERIFY模式下即使头信息完整needsBody()也会返回true因为只有HEADERS模式才可能跳过 body因此每个请求都必须解析 body无法享受快速路径但它获得的是头体一致的强保证适合鉴权策略基于 body 内容、又希望防御头信息被客户端误填或篡改的部署。此外VERIFY模式下 body 中真实解析出的值而非头值会被写入元数据。配置示例三种模式的 YAML 写法在 HTTP Connection Manager 的http_filters链中配置 MCP 过滤器完整可运行示例见 docs/root/configuration/http/http_filters/_include/mcp-filter.yaml过滤器部分参见 mcp_filter.rsthttp_filters: - name: envoy.filters.http.mcp typed_config: type: type.googleapis.com/envoy.extensions.filters.http.mcp.v3.Mcp traffic_mode: PASS_THROUGH attribute_source: HEADERS # 可选值BODY / VERIFY / HEADERS clear_route_cache: false # 写入元数据后是否重选路由 request_storage_mode: DYNAMIC_METADATA max_request_body_size: 8192 # 默认 8KB最大 10MB parser_config: methods: - method: tools/call group: tool extraction_rules: - path: params.name - path: params.arguments group_metadata_key: group - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router上例中若把attribute_source设为HEADERS并移除parser_config中params.arguments这条 body 专属规则tools/call请求即可走快速路径而只要extraction_rules里存在params.arguments这样的非名称路径测试用例HeadersAttributeSourceBuffersForBodyOnlyExtractionRule验证了这一行为见 mcp_filter_test.ccneedsBody()就会返回true过滤器退化为缓冲解析 body 后再用头值覆盖同名属性。mcp-method与mcp-name是下游客户端需要主动携带的请求头例如POST /mcp HTTP/1.1 Host: mcp.example.com Content-Type: application/json Accept: application/json, text/event-stream Mcp-Method: tools/call Mcp-Name: get_weather与其他配置项的协同与约束attribute_source不是孤立开关它的实际行为受Mcp消息中其他字段的制约全部字段定义见 api/envoy/extensions/filters/http/mcp/v3/mcp.protomax_request_body_size默认 8192 字节上限 10485760 字节设为 0 关闭限制只在需要缓冲 body 时生效。PASS_THROUGH模式下超限请求会被放行并写入is_exceeding_limit标记REJECT_NO_MCP模式下超限直接400。HEADERS快速路径完全不触及该限制。traffic_modeNOOP模式完全禁用过滤器处理包括属性提取与头读取此时attribute_source不生效REJECT_NO_MCP模式下非 MCP 流量会被拒绝。parser_config通过methods按方法配置group与extraction_rules规则按顺序首个匹配生效和group_metadata_key分组元数据键扩展属性提取当提取规则超出method与名称路径时HEADERS快速路径自动失效。AttributeExtractionRule.path为点分隔 JSON 路径如params.name、params.uri、params.taskId见 api/envoy/extensions/filters/http/mcp/v3/mcp.proto。reject_duplicate_keys默认 falselast-win启用后强制要求解析 body因此会取消HEADERS快速路径测试HeadersAttributeSourceBuffersWhenDuplicateKeyCheckEnabled验证见 mcp_filter_test.cc。propagate_trace_context/propagate_baggage分别从params._meta.traceparent/params._meta.tracestate/params._meta.baggage提取 W3C 上下文并注入到traceparent/tracestate/baggage请求头启用任一选项都会强制解析 body从而禁用快速路径。request_storage_mode决定属性写入动态元数据DYNAMIC_METADATA默认、filter stateFILTER_STATE还是两者DYNAMIC_METADATA_AND_FILTER_STATE快速路径同样遵循该设置测试HeadersAttributeSourceStoresFilterState验证见 mcp_filter_test.cc。clear_route_cache默认 false置 true 时在元数据写入后清除路由缓存使路由可根据 MCP 元数据重新选择快速路径下同样生效见 mcp_filter_test.cc。此外McpOverride每路由覆盖配置见 mcp.proto可对traffic_mode、max_request_body_size、clear_route_cache、parser_config、request_storage_mode、reject_duplicate_keys做 per-route 覆盖目前attribute_source不在 per-route 覆盖字段之列只能全局配置。头部缺失与不一致时的回退行为HEADERS模式的快速路径并非一票否决——头部不完整时过滤器会优雅回退到 body 解析且不产生错误缺Mcp-Method头hasCompleteHeaderAttributes()返回 falseneedsBody()返回 true回退为解析 body元数据完全取自 bodyHeadersAttributeSourceFallsBackWhenMethodHeaderMissingmcp_filter_test.cc缺Mcp-Name头但该方法需要名称同样回退到 body 解析以 body 值为准HeadersAttributeSourceFallsBackWhenNameHeaderMissingmcp_filter_test.cc头与 body 不一致HEADERS 模式且 body 因其他原因被解析不拒绝请求仅递增header_mismatch_统计并优先采用头值覆盖元数据中的同名属性HeadersMismatchIsStatOnlyWhenBodyIsParsed与completeParsing()中的头值覆盖逻辑见 mcp_filter_test.cc 和 mcp_filter.cc。这与VERIFY模式形成对照VERIFY下同样的不一致会直接以400拒绝HEADERS下只计数不拒绝。因此若你的安全模型要求头 body 必须一致应使用VERIFY若只是希望能信头就信头、信不了就退回 body使用HEADERS。小结与选型建议attribute_source为 Envoy MCP HTTP 过滤器的属性提取提供了三档灵活度BODY兼容性最强不依赖客户端携带任何 MCP 头适合客户端未升级或需要严格以 body 为准的场景VERIFY要求客户端携带Mcp-Method/Mcp-Name并以 body 为事实来源做一致性校验兼顾性能与安全适合鉴权敏感场景HEADERS信任请求头在提取规则仅涉及method与名称路径且未启用 trace/baggage/重复键检查时可完全跳过请求体解析适合高吞吐 MCP 网关对延迟敏感的部署头部缺失时自动回退到 body 解析不会产生误拒绝。实现与测试证据集中在 source/extensions/filters/http/mcp/mcp_filter.cc、api/envoy/extensions/filters/http/mcp/v3/mcp.proto 与 test/extensions/filters/http/mcp/mcp_filter_test.cc完整可运行的过滤器示例可参考 docs/root/configuration/http/http_filters/_include/mcp-filter.yaml。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考