Compare commits

...

2 Commits

Author SHA1 Message Date
Matthew Zeng
23e54eadcc update 2026-02-14 22:52:20 -08:00
Matthew Zeng
c434bd14b2 update 2026-02-14 21:34:02 -08:00
2 changed files with 83 additions and 29 deletions

View File

@@ -4902,12 +4902,18 @@ async fn built_tools(
&skill_name_counts_lower,
);
let mut selected_mcp_tools =
if let Some(selected_tools) = sess.get_mcp_tool_selection().await {
filter_mcp_tools_by_name(&mcp_tools, &selected_tools)
} else {
HashMap::new()
};
let selected_tools = sess.get_mcp_tool_selection().await;
let mut selected_mcp_tools = if let Some(selected_tools) = selected_tools.as_ref() {
filter_mcp_tools_by_name(&mcp_tools, selected_tools)
} else {
HashMap::new()
};
selected_mcp_tools.extend(
mcp_tools
.iter()
.filter(|(_, tool)| tool.server_name != CODEX_APPS_MCP_SERVER_NAME)
.map(|(name, tool)| (name.clone(), tool.clone())),
);
let apps_mcp_tools =
filter_codex_apps_mcp_tools_only(&mcp_tools, explicitly_enabled.as_ref());
@@ -6056,6 +6062,54 @@ mod tests {
);
}
#[test]
fn search_tool_selection_always_keeps_non_codex_apps_tools() {
let selected_tool_names = vec!["mcp__codex_apps__calendar_create_event".to_string()];
let mcp_tools = HashMap::from([
(
"mcp__codex_apps__calendar_create_event".to_string(),
make_mcp_tool(
CODEX_APPS_MCP_SERVER_NAME,
"calendar_create_event",
Some("calendar"),
Some("Calendar"),
),
),
(
"mcp__rmcp__echo".to_string(),
make_mcp_tool("rmcp", "echo", None, None),
),
]);
let mut selected_mcp_tools = filter_mcp_tools_by_name(&mcp_tools, &selected_tool_names);
selected_mcp_tools.extend(
mcp_tools
.iter()
.filter(|(_, tool)| tool.server_name != CODEX_APPS_MCP_SERVER_NAME)
.map(|(name, tool)| (name.clone(), tool.clone())),
);
let connectors = connectors::accessible_connectors_from_mcp_tools(&mcp_tools);
let explicitly_enabled_connectors = HashSet::new();
let connectors = filter_connectors_for_input(
&connectors,
&[user_message("run calendar tool")],
&explicitly_enabled_connectors,
&HashMap::new(),
);
let apps_mcp_tools = filter_codex_apps_mcp_tools_only(&mcp_tools, &connectors);
selected_mcp_tools.extend(apps_mcp_tools);
let mut tool_names: Vec<String> = selected_mcp_tools.into_keys().collect();
tool_names.sort();
assert_eq!(
tool_names,
vec![
"mcp__codex_apps__calendar_create_event".to_string(),
"mcp__rmcp__echo".to_string(),
]
);
}
#[tokio::test]
async fn reconstruct_history_matches_live_compactions() {
let (session, turn_context) = make_session_and_context().await;

View File

@@ -173,7 +173,7 @@ async fn search_tool_adds_discovery_instructions_to_tool_description() -> Result
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn search_tool_hides_mcp_tools_without_search() -> Result<()> {
async fn search_tool_keeps_non_codex_apps_mcp_tools_without_search() -> Result<()> {
skip_if_no_network!(Ok(()));
let server = start_mock_server().await;
@@ -232,12 +232,12 @@ async fn search_tool_hides_mcp_tools_without_search() -> Result<()> {
"tools list should include search_tool_bm25 when enabled: {tools:?}"
);
assert!(
!tools.iter().any(|name| name == "mcp__rmcp__echo"),
"tools list should not include MCP tools before search: {tools:?}"
tools.iter().any(|name| name == "mcp__rmcp__echo"),
"tools list should include non-codex_apps MCP tools before search: {tools:?}"
);
assert!(
!tools.iter().any(|name| name == "mcp__rmcp__image"),
"tools list should not include MCP tools before search: {tools:?}"
tools.iter().any(|name| name == "mcp__rmcp__image"),
"tools list should include non-codex_apps MCP tools before search: {tools:?}"
);
Ok(())
@@ -324,18 +324,18 @@ async fn search_tool_selection_persists_within_turn_and_resets_next_turn() -> Re
let first_tools = tool_names(&requests[0].body_json());
assert!(
!first_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"first request should not include MCP tools before search: {first_tools:?}"
first_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"first request should include non-codex_apps MCP tools before search: {first_tools:?}"
);
let second_tools = tool_names(&requests[1].body_json());
assert!(
!second_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"second request should not include rmcp MCP tools after search: {second_tools:?}"
second_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"second request should include non-codex_apps MCP tools after search: {second_tools:?}"
);
assert!(
!second_tools.iter().any(|name| name == "mcp__rmcp__image"),
"second request should not include rmcp MCP tools after search: {second_tools:?}"
second_tools.iter().any(|name| name == "mcp__rmcp__image"),
"second request should include non-codex_apps MCP tools after search: {second_tools:?}"
);
let search_output_payload = search_tool_output_payload(&requests[1], call_id);
@@ -359,8 +359,8 @@ async fn search_tool_selection_persists_within_turn_and_resets_next_turn() -> Re
let third_tools = tool_names(&requests[2].body_json());
assert!(
!third_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"third request should not include MCP tools after turn reset: {third_tools:?}"
third_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"third request should include non-codex_apps MCP tools after turn reset: {third_tools:?}"
);
Ok(())
@@ -455,28 +455,28 @@ async fn search_tool_selection_unions_results_within_turn() -> Result<()> {
let first_tools = tool_names(&requests[0].body_json());
assert!(
!first_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"first request should not include MCP tools before search: {first_tools:?}"
first_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"first request should include non-codex_apps MCP tools before search: {first_tools:?}"
);
let second_tools = tool_names(&requests[1].body_json());
assert!(
!second_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"second request should not include rmcp tools after first search: {second_tools:?}"
second_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"second request should include non-codex_apps MCP tools after first search: {second_tools:?}"
);
assert!(
!second_tools.iter().any(|name| name == "mcp__rmcp__image"),
"second request should not include rmcp tools after first search: {second_tools:?}"
second_tools.iter().any(|name| name == "mcp__rmcp__image"),
"second request should include non-codex_apps MCP tools after first search: {second_tools:?}"
);
let third_tools = tool_names(&requests[2].body_json());
assert!(
!third_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"third request should not include rmcp tools: {third_tools:?}"
third_tools.iter().any(|name| name == "mcp__rmcp__echo"),
"third request should include non-codex_apps MCP tools: {third_tools:?}"
);
assert!(
!third_tools.iter().any(|name| name == "mcp__rmcp__image"),
"third request should not include rmcp tools: {third_tools:?}"
third_tools.iter().any(|name| name == "mcp__rmcp__image"),
"third request should include non-codex_apps MCP tools: {third_tools:?}"
);
let second_search_payload = search_tool_output_payload(&requests[2], second_call_id);