Files
codex/codex-rs/rmcp-client/src/trace_context_tests.rs
T
Ben Romano 94174e44cb Preserve MCP request trace context across transport workers (#47212)
## Why

MCP requests pass through background transport queues, so HTTP requests need the caller's trace context carried explicitly to preserve trace ancestry.

## What changed

- Capture W3C trace context in request metadata for tool and resource operations, custom requests, and event streams.
- Restore that context in an `mcp.http.request` span around HTTP POSTs, linking outgoing HTTP traces to the originating request.
- Preserve application metadata while replacing trace fields with the current caller's context and removing stale `tracestate`. Read the SDK's merged metadata so extension fields retain precedence over parameter metadata.

## Testing

Add a unit test for metadata merge precedence and an integration test covering concurrent paginated requests, tool calls, custom requests, and tool-call continuations across legacy and `2026-07-28` protocol modes. Verify HTTP trace ancestry, metadata preservation, and removal of stale `tracestate`.

GitOrigin-RevId: 0b22cd75f31f9fcb855b27fa8d34ecdffd6e3549
2026-09-22 06:47:07 +00:00

46 lines
1.6 KiB
Rust

//! Checks that trace metadata uses the SDK's envelope/params merge precedence.
use super::merged_request_meta;
use pretty_assertions::assert_eq;
use rmcp::model::ClientRequest;
use rmcp::model::CustomRequest;
use rmcp::model::GetMeta;
use rmcp::model::ListToolsRequest;
use rmcp::model::PaginatedRequestParams;
use rmcp::model::RequestMetaObject;
use serde_json::json;
#[test]
fn merged_metadata_preserves_params_and_prefers_extensions() -> serde_json::Result<()> {
let params_meta = json!({"application": "preserved", "traceparent": "params-parent"});
let mut params = PaginatedRequestParams::default();
params.meta = Some(serde_json::from_value::<RequestMetaObject>(
params_meta.clone(),
)?);
let requests = [
ClientRequest::ListToolsRequest(ListToolsRequest::with_param(params)),
ClientRequest::CustomRequest(CustomRequest::new(
"test/custom",
Some(json!({"_meta": params_meta})),
)),
];
for mut request in requests {
let params_only = serde_json::to_value(&request)?;
assert_eq!(merged_request_meta(&params_only), params_meta.as_object());
request.get_meta_mut().set_traceparent("extension-parent");
request.get_meta_mut().set_tracestate("vendor=value");
let merged = serde_json::to_value(&request)?;
assert_eq!(
merged_request_meta(&merged),
json!({
"application": "preserved",
"traceparent": "extension-parent",
"tracestate": "vendor=value",
})
.as_object(),
);
}
Ok(())
}