mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Expose MCP app identity in app context (#29934)
## Why MCP tool-call events need to expose trusted app identity and action metadata directly so v2 clients do not have to infer it from tool names or resource URIs. ## What changed - Add optional `appName`, `templateId`, and `actionName` fields to MCP tool-call `appContext`. - Populate `appName` and `templateId` from trusted Codex Apps metadata, and derive `actionName` from the trusted app resource metadata. - Preserve all three fields through core events, legacy protocol events, persisted thread history, resume redaction, and app-server v2 responses. - Document the public `appContext` fields in `codex-rs/app-server/README.md`. - Regenerate app-server JSON and TypeScript schemas and add coverage for serialization, persistence, redaction, and metadata propagation. ## Validation - `just test -p codex-app-server-protocol mcp_tool_call` - `just test -p codex-core mcp_tool_call_item_metadata_only_trusts_codex_apps_identity mcp_tool_call_item_includes_app_identity` - `just write-app-server-schema` --------- Co-authored-by: Martin Au-Yeung <280153141+martinauyeung-oai@users.noreply.github.com>
This commit is contained in:
1 parent
fb8598df3f
commit
ec300bc7bd
32 files changed
+516
-4
No files matched your search
@@ -326,6 +326,9 @@ struct McpToolCallItemMetadata {
|
||||
connector_id: Option<String>,
|
||||
link_id: Option<String>,
|
||||
mcp_app_resource_uri: Option<String>,
|
||||
app_name: Option<String>,
|
||||
template_id: Option<String>,
|
||||
action_name: Option<String>,
|
||||
plugin_id: Option<String>,
|
||||
}
|
||||
|
||||
@@ -342,6 +345,15 @@ impl McpToolCallItemMetadata {
|
||||
link_id: trusted_mcp_app_metadata.and_then(|metadata| metadata.link_id.clone()),
|
||||
mcp_app_resource_uri: metadata
|
||||
.and_then(|metadata| metadata.mcp_app_resource_uri.clone()),
|
||||
app_name: trusted_mcp_app_metadata.and_then(|metadata| metadata.connector_name.clone()),
|
||||
template_id: trusted_mcp_app_metadata.and_then(|metadata| metadata.template_id.clone()),
|
||||
action_name: trusted_mcp_app_metadata
|
||||
.and_then(|metadata| metadata.codex_apps_meta.as_ref())
|
||||
.and_then(|meta| meta.get(MCP_TOOL_RESOURCE_URI_META_KEY))
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.and_then(|resource_uri| resource_uri.trim_matches('/').rsplit('/').next())
|
||||
.filter(|action_name| !action_name.is_empty())
|
||||
.map(str::to_string),
|
||||
plugin_id: metadata.and_then(|metadata| metadata.plugin_id.clone()),
|
||||
}
|
||||
}
|
||||
@@ -881,6 +893,9 @@ async fn notify_mcp_tool_call_started(
|
||||
connector_id: item_metadata.connector_id,
|
||||
mcp_app_resource_uri: item_metadata.mcp_app_resource_uri,
|
||||
link_id: item_metadata.link_id,
|
||||
app_name: item_metadata.app_name,
|
||||
template_id: item_metadata.template_id,
|
||||
action_name: item_metadata.action_name,
|
||||
plugin_id: item_metadata.plugin_id,
|
||||
status: McpToolCallStatus::InProgress,
|
||||
result: None,
|
||||
@@ -923,6 +938,9 @@ async fn notify_mcp_tool_call_completed(
|
||||
connector_id: item_metadata.connector_id,
|
||||
mcp_app_resource_uri: item_metadata.mcp_app_resource_uri,
|
||||
link_id: item_metadata.link_id,
|
||||
app_name: item_metadata.app_name,
|
||||
template_id: item_metadata.template_id,
|
||||
action_name: item_metadata.action_name,
|
||||
plugin_id: item_metadata.plugin_id,
|
||||
status,
|
||||
result,
|
||||
@@ -999,6 +1017,7 @@ pub(crate) struct McpToolApprovalMetadata {
|
||||
tool_title: Option<String>,
|
||||
tool_description: Option<String>,
|
||||
mcp_app_resource_uri: Option<String>,
|
||||
template_id: Option<String>,
|
||||
codex_apps_meta: Option<serde_json::Map<String, serde_json::Value>>,
|
||||
openai_file_input_params: Option<Vec<String>>,
|
||||
}
|
||||
@@ -1009,6 +1028,8 @@ const MCP_TOOL_LINK_ID_META_KEY: &str = "link_id";
|
||||
const MCP_TOOL_PLUGIN_ID_META_KEY: &str = "plugin_id";
|
||||
const MCP_TOOL_THREAD_ID_META_KEY: &str = "threadId";
|
||||
const MCP_TOOL_CONNECTED_ACCOUNT_EMAIL_META_KEY: &str = "connected_account_email";
|
||||
const MCP_TOOL_TEMPLATE_ID_META_KEY: &str = "template_id";
|
||||
const MCP_TOOL_RESOURCE_URI_META_KEY: &str = "resource_uri";
|
||||
|
||||
async fn custom_mcp_tool_approval_mode(
|
||||
sess: &Session,
|
||||
@@ -1531,6 +1552,11 @@ pub(crate) async fn lookup_mcp_tool_metadata(
|
||||
tool_title: tool_info.tool.title,
|
||||
tool_description: tool_info.tool.description.map(std::borrow::Cow::into_owned),
|
||||
mcp_app_resource_uri: get_mcp_app_resource_uri(tool_info.tool.meta.as_deref()),
|
||||
template_id: codex_apps_meta
|
||||
.as_ref()
|
||||
.and_then(|meta| meta.get(MCP_TOOL_TEMPLATE_ID_META_KEY))
|
||||
.and_then(serde_json::Value::as_str)
|
||||
.map(str::to_string),
|
||||
codex_apps_meta,
|
||||
// Disallow custom MCPs from uploading files via fileParams.
|
||||
openai_file_input_params: openai_file_input_params_for_server(
|
||||
|
||||
Reference in new issue
Block a user