codex_rollout_trace/
mcp.rs1use crate::McpCallId;
8use serde_json::Value as JsonValue;
9
10const MCP_CALL_ID_META_KEY: &str = "codex_bridge_mcp_call_id";
11
12#[derive(Clone, Debug)]
14pub struct McpCallTraceContext {
15 mcp_call_id: Option<McpCallId>,
16}
17
18impl McpCallTraceContext {
19 pub fn disabled() -> Self {
21 Self { mcp_call_id: None }
22 }
23
24 pub(crate) fn enabled(mcp_call_id: McpCallId) -> Self {
26 Self {
27 mcp_call_id: Some(mcp_call_id),
28 }
29 }
30
31 pub(crate) fn mcp_call_id(&self) -> Option<&str> {
33 self.mcp_call_id.as_deref()
34 }
35
36 pub fn add_request_meta(&self, meta: Option<JsonValue>) -> Option<JsonValue> {
38 let Some(mcp_call_id) = self.mcp_call_id() else {
39 return meta;
40 };
41
42 match meta {
43 Some(JsonValue::Object(mut map)) => {
44 map.insert(
45 MCP_CALL_ID_META_KEY.to_string(),
46 JsonValue::String(mcp_call_id.to_string()),
47 );
48 Some(JsonValue::Object(map))
49 }
50 None => {
51 let mut map = serde_json::Map::new();
52 map.insert(
53 MCP_CALL_ID_META_KEY.to_string(),
54 JsonValue::String(mcp_call_id.to_string()),
55 );
56 Some(JsonValue::Object(map))
57 }
58 Some(_) => meta,
62 }
63 }
64}
65
66#[cfg(test)]
67mod tests {
68 use serde_json::json;
69
70 use super::MCP_CALL_ID_META_KEY;
71 use super::McpCallTraceContext;
72
73 #[test]
74 fn disabled_mcp_trace_leaves_request_meta_unchanged() {
75 let meta = Some(json!({"source": "test"}));
76
77 assert_eq!(
78 McpCallTraceContext::disabled().add_request_meta(meta.clone()),
79 meta
80 );
81 }
82
83 #[test]
84 fn enabled_mcp_trace_adds_bridge_correlation_meta() {
85 let trace = McpCallTraceContext::enabled("mcp-call-id".to_string());
86 let meta = trace
87 .add_request_meta(Some(json!({"source": "test"})))
88 .expect("enabled trace keeps request metadata");
89 let object = meta
90 .as_object()
91 .expect("MCP request metadata remains an object");
92
93 assert_eq!(object["source"], json!("test"));
94 assert_eq!(
95 object[MCP_CALL_ID_META_KEY],
96 json!(trace.mcp_call_id().expect("enabled trace has an ID"))
97 );
98 }
99}