mirror of
https://github.com/openai/codex.git
synced 2026-10-18 17:18:52 +00:00
Track cumulative MCP attribution across requests and thread history (#47081)
## What changed - Record each MCP source and its first turn, including connector and plugin identifiers when available. Cover direct and Code Mode calls, including returned errors and results that are not printed. - Persist cumulative attribution checkpoints and restore them across compaction, resume, and forks, including forks limited to recent turns. - Attach fresh attribution to Responses API `client_metadata` under `mcp_attribution`, outside model-visible content. Restrict transmission to allowed OpenAI HTTPS destinations for both HTTP and WebSocket requests. - Report `attribution_error` for legacy history without checkpoints, malformed or conflicting attribution, and serialized attribution exceeding 16 KiB. ## Testing Add coverage for source deduplication, checkpoint persistence and restoration, recent-turn forks, direct and Code Mode calls, destination filtering, and the serialized size limit. GitOrigin-RevId: fd285e152ca9e24bfa000debb20013709d67a86e
This commit is contained in:
@@ -52,6 +52,42 @@ pub fn is_node_repl_backed_tool(name: &str, namespace: Option<&str>) -> bool {
|
||||
.is_some_and(|(server, _)| is_node_repl_backed_server(server))
|
||||
}
|
||||
|
||||
/// Producer-reported completeness of the thread's MCP tools/call attribution.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum McpAttributionStatus {
|
||||
#[default]
|
||||
None,
|
||||
Complete,
|
||||
AttributionError,
|
||||
}
|
||||
|
||||
/// One source and the first runtime turn in which Codex recorded it.
|
||||
///
|
||||
/// Server and tool names are retained when no stable identifier is available;
|
||||
/// they are not guaranteed to be globally unique or independently authenticated.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct McpAttributionSource {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub connector_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub plugin_id: Option<String>,
|
||||
pub server_name: String,
|
||||
pub tool_name: String,
|
||||
pub first_turn_id: String,
|
||||
}
|
||||
|
||||
/// Cumulative, model-invisible attribution reported on Responses API requests.
|
||||
/// This is provenance data, not a training-eligibility decision or attestation.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct McpAttribution {
|
||||
pub status: McpAttributionStatus,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub sources: Vec<McpAttributionSource>,
|
||||
}
|
||||
|
||||
/// Bounded app-resource provenance retained across a compaction checkpoint.
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct McpResourceOriginCheckpoint {
|
||||
|
||||
Reference in New Issue
Block a user