mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Emit Trusted MCP App Identity on Tool-Call Items (#27132)
## Summary
- Add optional `appContext` to app-server MCP tool-call items with
trusted `connectorId`, `linkId`, and `mcpAppResourceUri` metadata.
- Preserve that context across tool-call events, persisted history,
reconnects, and thread resume.
- Keep the deprecated top-level `mcpAppResourceUri` temporarily for
client migration.
The consumer contract is `{ appContext: { connectorId, linkId,
mcpAppResourceUri }, tool }`.
## Validation
- Full GitHub Actions suite passes, including CLA, Bazel tests, clippy,
release builds, and argument-comment lint.
---------
Co-authored-by: martinauyeung-oai <280153141+martinauyeung-oai@users.noreply.github.com>
This commit is contained in:
co-authored by
martinauyeung-oai
parent
9bcc09f9f7
commit
765309d5a6
@@ -188,9 +188,15 @@ pub struct McpToolCallItem {
|
||||
pub arguments: serde_json::Value,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub connector_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub mcp_app_resource_uri: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub link_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub plugin_id: Option<String>,
|
||||
pub status: McpToolCallStatus,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
@@ -546,7 +552,9 @@ impl McpToolCallItem {
|
||||
tool: self.tool.clone(),
|
||||
arguments: (!self.arguments.is_null()).then(|| self.arguments.clone()),
|
||||
},
|
||||
connector_id: self.connector_id.clone(),
|
||||
mcp_app_resource_uri: self.mcp_app_resource_uri.clone(),
|
||||
link_id: self.link_id.clone(),
|
||||
plugin_id: self.plugin_id.clone(),
|
||||
})
|
||||
}
|
||||
@@ -566,6 +574,8 @@ impl McpToolCallItem {
|
||||
arguments: (!self.arguments.is_null()).then(|| self.arguments.clone()),
|
||||
},
|
||||
mcp_app_resource_uri: self.mcp_app_resource_uri.clone(),
|
||||
connector_id: self.connector_id.clone(),
|
||||
link_id: self.link_id.clone(),
|
||||
plugin_id: self.plugin_id.clone(),
|
||||
duration: self.duration?,
|
||||
result,
|
||||
|
||||
@@ -2324,9 +2324,15 @@ pub struct McpToolCallBeginEvent {
|
||||
pub invocation: McpInvocation,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub connector_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub mcp_app_resource_uri: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub link_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub plugin_id: Option<String>,
|
||||
}
|
||||
|
||||
@@ -2337,9 +2343,15 @@ pub struct McpToolCallEndEvent {
|
||||
pub invocation: McpInvocation,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub connector_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub mcp_app_resource_uri: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub link_id: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[ts(optional)]
|
||||
pub plugin_id: Option<String>,
|
||||
#[ts(type = "string")]
|
||||
pub duration: Duration,
|
||||
@@ -4940,7 +4952,9 @@ mod tests {
|
||||
server: "server".into(),
|
||||
tool: "tool".into(),
|
||||
arguments: json!({"arg": "value"}),
|
||||
connector_id: Some("connector".into()),
|
||||
mcp_app_resource_uri: Some("app://connector".into()),
|
||||
link_id: Some("link_123".into()),
|
||||
plugin_id: Some("sample@test".into()),
|
||||
status: McpToolCallStatus::InProgress,
|
||||
result: None,
|
||||
@@ -4956,10 +4970,12 @@ mod tests {
|
||||
assert_eq!(event.call_id, "mcp-1");
|
||||
assert_eq!(event.invocation.server, "server");
|
||||
assert_eq!(event.invocation.tool, "tool");
|
||||
assert_eq!(event.connector_id.as_deref(), Some("connector"));
|
||||
assert_eq!(
|
||||
event.mcp_app_resource_uri.as_deref(),
|
||||
Some("app://connector")
|
||||
);
|
||||
assert_eq!(event.link_id.as_deref(), Some("link_123"));
|
||||
assert_eq!(event.plugin_id.as_deref(), Some("sample@test"));
|
||||
}
|
||||
_ => panic!("expected McpToolCallBegin event"),
|
||||
@@ -5047,7 +5063,9 @@ mod tests {
|
||||
server: "server".into(),
|
||||
tool: "tool".into(),
|
||||
arguments: json!({"arg": "value"}),
|
||||
connector_id: Some("connector".into()),
|
||||
mcp_app_resource_uri: Some("app://connector".into()),
|
||||
link_id: Some("link_123".into()),
|
||||
plugin_id: Some("sample@test".into()),
|
||||
status: McpToolCallStatus::Completed,
|
||||
result: Some(CallToolResult {
|
||||
@@ -5068,10 +5086,12 @@ mod tests {
|
||||
assert_eq!(event.call_id, "mcp-1");
|
||||
assert_eq!(event.invocation.server, "server");
|
||||
assert_eq!(event.invocation.tool, "tool");
|
||||
assert_eq!(event.connector_id.as_deref(), Some("connector"));
|
||||
assert_eq!(
|
||||
event.mcp_app_resource_uri.as_deref(),
|
||||
Some("app://connector")
|
||||
);
|
||||
assert_eq!(event.link_id.as_deref(), Some("link_123"));
|
||||
assert_eq!(event.plugin_id.as_deref(), Some("sample@test"));
|
||||
assert_eq!(event.duration, Duration::from_millis(42));
|
||||
assert!(event.is_success());
|
||||
|
||||
Reference in New Issue
Block a user