mirror of
https://github.com/openai/codex.git
synced 2026-11-15 21:50:46 +00:00
wip
This commit is contained in:
@@ -112,7 +112,7 @@ fn codex_app_tool(
|
||||
) -> ToolInfo {
|
||||
let tool_namespace = connector_name
|
||||
.map(sanitize_name)
|
||||
.map(|connector_name| format!("mcp__{CODEX_APPS_MCP_SERVER_NAME}__{connector_name}"))
|
||||
.map(|connector_name| format!("{CODEX_APPS_MCP_SERVER_NAME}__{connector_name}"))
|
||||
.unwrap_or_else(|| CODEX_APPS_MCP_SERVER_NAME.to_string());
|
||||
|
||||
ToolInfo {
|
||||
@@ -175,7 +175,7 @@ fn merge_connectors_replaces_plugin_placeholder_name_with_accessible_name() {
|
||||
fn accessible_connectors_from_mcp_tools_carries_plugin_display_names() {
|
||||
let tools = HashMap::from([
|
||||
(
|
||||
"mcp__codex_apps__calendar_list_events".to_string(),
|
||||
"codex_apps__calendar__list_events".to_string(),
|
||||
codex_app_tool(
|
||||
"calendar_list_events",
|
||||
"calendar",
|
||||
@@ -184,7 +184,7 @@ fn accessible_connectors_from_mcp_tools_carries_plugin_display_names() {
|
||||
),
|
||||
),
|
||||
(
|
||||
"mcp__codex_apps__calendar_create_event".to_string(),
|
||||
"codex_apps__calendar__create_event".to_string(),
|
||||
codex_app_tool(
|
||||
"calendar_create_event",
|
||||
"calendar",
|
||||
@@ -193,7 +193,7 @@ fn accessible_connectors_from_mcp_tools_carries_plugin_display_names() {
|
||||
),
|
||||
),
|
||||
(
|
||||
"mcp__sample__echo".to_string(),
|
||||
"sample__echo".to_string(),
|
||||
ToolInfo {
|
||||
server_name: "sample".to_string(),
|
||||
callable_name: "echo".to_string(),
|
||||
@@ -242,7 +242,7 @@ async fn refresh_accessible_connectors_cache_from_mcp_tools_writes_latest_instal
|
||||
let cache_key = accessible_connectors_cache_key(&config, /*auth*/ None);
|
||||
let tools = HashMap::from([
|
||||
(
|
||||
"mcp__codex_apps__calendar_list_events".to_string(),
|
||||
"codex_apps__calendar__list_events".to_string(),
|
||||
codex_app_tool(
|
||||
"calendar_list_events",
|
||||
"calendar",
|
||||
@@ -251,7 +251,7 @@ async fn refresh_accessible_connectors_cache_from_mcp_tools_writes_latest_instal
|
||||
),
|
||||
),
|
||||
(
|
||||
"mcp__codex_apps__openai_hidden".to_string(),
|
||||
"codex_apps__openai_hidden".to_string(),
|
||||
codex_app_tool(
|
||||
"openai_hidden",
|
||||
"connector_openai_hidden",
|
||||
@@ -318,11 +318,11 @@ fn merge_connectors_unions_and_dedupes_plugin_display_names() {
|
||||
#[test]
|
||||
fn accessible_connectors_from_mcp_tools_preserves_description() {
|
||||
let mcp_tools = HashMap::from([(
|
||||
"mcp__codex_apps__calendar_create_event".to_string(),
|
||||
"codex_apps__calendar__create_event".to_string(),
|
||||
ToolInfo {
|
||||
server_name: CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
callable_name: "calendar_create_event".to_string(),
|
||||
callable_namespace: "mcp__codex_apps__calendar".to_string(),
|
||||
callable_namespace: "codex_apps__calendar".to_string(),
|
||||
server_instructions: None,
|
||||
tool: Tool {
|
||||
name: "calendar_create_event".to_string().into(),
|
||||
|
||||
@@ -1907,7 +1907,7 @@ async fn approve_mode_skips_when_annotations_do_not_require_approval() {
|
||||
&turn_context,
|
||||
"call-1",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Approve,
|
||||
)
|
||||
@@ -1980,7 +1980,7 @@ async fn guardian_mode_skips_auto_when_annotations_do_not_require_approval() {
|
||||
&turn_context,
|
||||
"call-guardian",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Auto,
|
||||
)
|
||||
@@ -1995,7 +1995,7 @@ async fn permission_request_hook_allows_mcp_tool_call() {
|
||||
let log_path = install_mcp_permission_request_hook(
|
||||
&mut session,
|
||||
&turn_context,
|
||||
"mcp__memory__.*",
|
||||
"memory__.*",
|
||||
&serde_json::json!({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PermissionRequest",
|
||||
@@ -2036,7 +2036,7 @@ async fn permission_request_hook_allows_mcp_tool_call() {
|
||||
&turn_context,
|
||||
"call-mcp-hook",
|
||||
&invocation,
|
||||
"mcp__memory__create_entities",
|
||||
"memory__create_entities",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Auto,
|
||||
)
|
||||
@@ -2057,7 +2057,7 @@ async fn permission_request_hook_allows_mcp_tool_call() {
|
||||
"transcript_path": null,
|
||||
"model": turn_context.model_info.slug,
|
||||
"permission_mode": "default",
|
||||
"tool_name": "mcp__memory__create_entities",
|
||||
"tool_name": "memory__create_entities",
|
||||
"hook_event_name": "PermissionRequest",
|
||||
"tool_input": {
|
||||
"entities": [{
|
||||
@@ -2075,7 +2075,7 @@ async fn permission_request_hook_uses_hook_tool_name_without_metadata() {
|
||||
let log_path = install_mcp_permission_request_hook(
|
||||
&mut session,
|
||||
&turn_context,
|
||||
"mcp__memory__.*",
|
||||
"memory__.*",
|
||||
&serde_json::json!({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PermissionRequest",
|
||||
@@ -2096,7 +2096,7 @@ async fn permission_request_hook_uses_hook_tool_name_without_metadata() {
|
||||
&turn_context,
|
||||
"call-mcp-hook-no-metadata",
|
||||
&invocation,
|
||||
"mcp__memory__create_entities",
|
||||
"memory__create_entities",
|
||||
/*metadata*/ None,
|
||||
AppToolApproval::Auto,
|
||||
)
|
||||
@@ -2117,7 +2117,7 @@ async fn permission_request_hook_uses_hook_tool_name_without_metadata() {
|
||||
"transcript_path": null,
|
||||
"model": turn_context.model_info.slug,
|
||||
"permission_mode": "default",
|
||||
"tool_name": "mcp__memory__create_entities",
|
||||
"tool_name": "memory__create_entities",
|
||||
"hook_event_name": "PermissionRequest",
|
||||
"tool_input": { "entities": [] }
|
||||
})]
|
||||
@@ -2130,7 +2130,7 @@ async fn permission_request_hook_runs_after_remembered_mcp_approval() {
|
||||
let log_path = install_mcp_permission_request_hook(
|
||||
&mut session,
|
||||
&turn_context,
|
||||
"mcp__memory__.*",
|
||||
"memory__.*",
|
||||
&serde_json::json!({
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PermissionRequest",
|
||||
@@ -2173,7 +2173,7 @@ async fn permission_request_hook_runs_after_remembered_mcp_approval() {
|
||||
&turn_context,
|
||||
"call-mcp-remembered",
|
||||
&invocation,
|
||||
"mcp__memory__create_entities",
|
||||
"memory__create_entities",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Auto,
|
||||
)
|
||||
@@ -2253,7 +2253,7 @@ async fn guardian_mode_mcp_denial_returns_rationale_message() {
|
||||
&turn_context,
|
||||
"call-guardian-deny",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Auto,
|
||||
)
|
||||
@@ -2310,7 +2310,7 @@ async fn prompt_mode_waits_for_approval_when_annotations_do_not_require_approval
|
||||
&turn_context,
|
||||
"call-prompt",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Prompt,
|
||||
)
|
||||
@@ -2385,7 +2385,7 @@ async fn approve_mode_blocks_when_arc_returns_interrupt_for_model() {
|
||||
&turn_context,
|
||||
"call-2",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Approve,
|
||||
)
|
||||
@@ -2457,7 +2457,7 @@ async fn custom_approve_mode_blocks_when_arc_returns_interrupt_for_model() {
|
||||
&turn_context,
|
||||
"call-2-custom",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Approve,
|
||||
)
|
||||
@@ -2529,7 +2529,7 @@ async fn approve_mode_blocks_when_arc_returns_interrupt_without_annotations() {
|
||||
&turn_context,
|
||||
"call-3",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Approve,
|
||||
)
|
||||
@@ -2611,7 +2611,7 @@ async fn full_access_mode_skips_arc_monitor_for_all_approval_modes() {
|
||||
&turn_context,
|
||||
"call-2",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
approval_mode,
|
||||
)
|
||||
@@ -2701,7 +2701,7 @@ async fn approve_mode_skips_arc_and_guardian_when_guardian_reviewer_is_enabled()
|
||||
&turn_context,
|
||||
"call-3",
|
||||
&invocation,
|
||||
"mcp__test__tool",
|
||||
"test__tool",
|
||||
Some(&metadata),
|
||||
AppToolApproval::Approve,
|
||||
)
|
||||
|
||||
@@ -48,10 +48,10 @@ fn make_mcp_tool(
|
||||
let tool_namespace = if server_name == CODEX_APPS_MCP_SERVER_NAME {
|
||||
connector_name
|
||||
.map(sanitize_name)
|
||||
.map(|connector_name| format!("mcp__{server_name}__{connector_name}"))
|
||||
.map(|connector_name| format!("{server_name}__{connector_name}"))
|
||||
.unwrap_or_else(|| server_name.to_string())
|
||||
} else {
|
||||
format!("mcp__{server_name}__")
|
||||
server_name.to_string()
|
||||
};
|
||||
|
||||
ToolInfo {
|
||||
@@ -82,7 +82,7 @@ fn numbered_mcp_tools(count: usize) -> HashMap<String, ToolInfo> {
|
||||
.map(|index| {
|
||||
let tool_name = format!("tool_{index}");
|
||||
(
|
||||
format!("mcp__rmcp__{tool_name}"),
|
||||
format!("rmcp__{tool_name}"),
|
||||
make_mcp_tool(
|
||||
"rmcp", &tool_name, /*connector_id*/ None, /*connector_name*/ None,
|
||||
),
|
||||
@@ -165,7 +165,7 @@ async fn directly_exposes_explicit_apps_without_deferred_overlap() {
|
||||
let tools_config = tools_config_for_mcp_tool_exposure(/*search_tool*/ true).await;
|
||||
let mut mcp_tools = numbered_mcp_tools(DIRECT_MCP_TOOL_EXPOSURE_THRESHOLD - 1);
|
||||
mcp_tools.extend([(
|
||||
"mcp__codex_apps__calendar_create_event".to_string(),
|
||||
"codex_apps__calendar__create_event".to_string(),
|
||||
make_mcp_tool(
|
||||
CODEX_APPS_MCP_SERVER_NAME,
|
||||
"calendar_create_event",
|
||||
@@ -187,7 +187,7 @@ async fn directly_exposes_explicit_apps_without_deferred_overlap() {
|
||||
tool_names.sort();
|
||||
assert_eq!(
|
||||
tool_names,
|
||||
vec!["mcp__codex_apps__calendar_create_event".to_string()]
|
||||
vec!["codex_apps__calendar__create_event".to_string()]
|
||||
);
|
||||
assert_eq!(
|
||||
exposure.deferred_tools.as_ref().map(HashMap::len),
|
||||
@@ -203,8 +203,8 @@ async fn directly_exposes_explicit_apps_without_deferred_overlap() {
|
||||
.all(|direct_tool_name| !deferred_tools.contains_key(direct_tool_name)),
|
||||
"direct tools should not also be deferred: {tool_names:?}"
|
||||
);
|
||||
assert!(!deferred_tools.contains_key("mcp__codex_apps__calendar_create_event"));
|
||||
assert!(deferred_tools.contains_key("mcp__rmcp__tool_0"));
|
||||
assert!(!deferred_tools.contains_key("codex_apps__calendar__create_event"));
|
||||
assert!(deferred_tools.contains_key("rmcp__tool_0"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -217,13 +217,13 @@ async fn always_defer_feature_preserves_explicit_apps() {
|
||||
let tools_config = tools_config_for_mcp_tool_exposure(/*search_tool*/ true).await;
|
||||
let mcp_tools = HashMap::from([
|
||||
(
|
||||
"mcp__rmcp__tool".to_string(),
|
||||
"rmcp__tool".to_string(),
|
||||
make_mcp_tool(
|
||||
"rmcp", "tool", /*connector_id*/ None, /*connector_name*/ None,
|
||||
),
|
||||
),
|
||||
(
|
||||
"mcp__codex_apps__calendar_create_event".to_string(),
|
||||
"codex_apps__calendar__create_event".to_string(),
|
||||
make_mcp_tool(
|
||||
CODEX_APPS_MCP_SERVER_NAME,
|
||||
"calendar_create_event",
|
||||
@@ -246,12 +246,12 @@ async fn always_defer_feature_preserves_explicit_apps() {
|
||||
direct_tool_names.sort();
|
||||
assert_eq!(
|
||||
direct_tool_names,
|
||||
vec!["mcp__codex_apps__calendar_create_event".to_string()]
|
||||
vec!["codex_apps__calendar__create_event".to_string()]
|
||||
);
|
||||
let deferred_tools = exposure
|
||||
.deferred_tools
|
||||
.as_ref()
|
||||
.expect("MCP tools should be discoverable through tool_search");
|
||||
assert!(deferred_tools.contains_key("mcp__rmcp__tool"));
|
||||
assert!(!deferred_tools.contains_key("mcp__codex_apps__calendar_create_event"));
|
||||
assert!(deferred_tools.contains_key("rmcp__tool"));
|
||||
assert!(!deferred_tools.contains_key("codex_apps__calendar__create_event"));
|
||||
}
|
||||
|
||||
@@ -142,12 +142,12 @@ mod tests {
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
tracker: Arc::new(Mutex::new(TurnDiffTracker::new())),
|
||||
call_id: "call-mcp-pre".to_string(),
|
||||
tool_name: codex_tools::ToolName::namespaced("mcp__memory__", "create_entities"),
|
||||
tool_name: codex_tools::ToolName::namespaced("memory", "create_entities"),
|
||||
source: ToolCallSource::Direct,
|
||||
payload,
|
||||
}),
|
||||
Some(PreToolUsePayload {
|
||||
tool_name: HookToolName::new("mcp__memory__create_entities"),
|
||||
tool_name: HookToolName::new("memory__create_entities"),
|
||||
tool_input: json!({
|
||||
"entities": [{
|
||||
"name": "Ada",
|
||||
@@ -191,14 +191,14 @@ mod tests {
|
||||
cancellation_token: tokio_util::sync::CancellationToken::new(),
|
||||
tracker: Arc::new(Mutex::new(TurnDiffTracker::new())),
|
||||
call_id: "call-mcp-post".to_string(),
|
||||
tool_name: codex_tools::ToolName::namespaced("mcp__filesystem__", "read_file"),
|
||||
tool_name: codex_tools::ToolName::namespaced("filesystem", "read_file"),
|
||||
source: ToolCallSource::Direct,
|
||||
payload,
|
||||
};
|
||||
assert_eq!(
|
||||
McpHandler.post_tool_use_payload(&invocation, &output),
|
||||
Some(PostToolUsePayload {
|
||||
tool_name: HookToolName::new("mcp__filesystem__read_file"),
|
||||
tool_name: HookToolName::new("filesystem__read_file"),
|
||||
tool_use_id: "call-mcp-post".to_string(),
|
||||
tool_input: json!({
|
||||
"path": {
|
||||
|
||||
@@ -202,11 +202,11 @@ mod tests {
|
||||
let handler = handler_from_tools(
|
||||
Some(&std::collections::HashMap::from([
|
||||
(
|
||||
"mcp__calendar__create_event".to_string(),
|
||||
"calendar__create_event".to_string(),
|
||||
tool_info("calendar", "create_event", "Create events"),
|
||||
),
|
||||
(
|
||||
"mcp__calendar__list_events".to_string(),
|
||||
"calendar__list_events".to_string(),
|
||||
tool_info("calendar", "list_events", "List events"),
|
||||
),
|
||||
])),
|
||||
@@ -226,8 +226,8 @@ mod tests {
|
||||
tools,
|
||||
vec![
|
||||
LoadableToolSpec::Namespace(ResponsesApiNamespace {
|
||||
name: "mcp__calendar__".to_string(),
|
||||
description: "Tools in the mcp__calendar__ namespace.".to_string(),
|
||||
name: "calendar".to_string(),
|
||||
description: "Tools in the calendar namespace.".to_string(),
|
||||
tools: vec![
|
||||
ResponsesApiNamespaceTool::Function(ResponsesApiTool {
|
||||
name: "create_event".to_string(),
|
||||
@@ -380,7 +380,7 @@ mod tests {
|
||||
.map(|index| {
|
||||
let tool_name = format!("tool_{index:03}");
|
||||
(
|
||||
format!("mcp__{server_name}__{tool_name}"),
|
||||
format!("{server_name}__{tool_name}"),
|
||||
tool_info(server_name, &tool_name, description_prefix),
|
||||
)
|
||||
})
|
||||
@@ -391,7 +391,7 @@ mod tests {
|
||||
ToolInfo {
|
||||
server_name: server_name.to_string(),
|
||||
callable_name: tool_name.to_string(),
|
||||
callable_namespace: format!("mcp__{server_name}__"),
|
||||
callable_namespace: server_name.to_string(),
|
||||
server_instructions: None,
|
||||
tool: Tool {
|
||||
name: tool_name.to_string().into(),
|
||||
|
||||
@@ -23,7 +23,7 @@ impl ToolHandler for TestHandler {
|
||||
fn handler_looks_up_namespaced_aliases_explicitly() {
|
||||
let plain_handler = Arc::new(TestHandler) as Arc<dyn AnyToolHandler>;
|
||||
let namespaced_handler = Arc::new(TestHandler) as Arc<dyn AnyToolHandler>;
|
||||
let namespace = "mcp__codex_apps__gmail";
|
||||
let namespace = "codex_apps__gmail";
|
||||
let tool_name = "gmail_get_recent_emails";
|
||||
let plain_name = codex_tools::ToolName::plain(tool_name);
|
||||
let namespaced_name = codex_tools::ToolName::namespaced(namespace, tool_name);
|
||||
@@ -35,7 +35,7 @@ fn handler_looks_up_namespaced_aliases_explicitly() {
|
||||
let plain = registry.handler(&plain_name);
|
||||
let namespaced = registry.handler(&namespaced_name);
|
||||
let missing_namespaced = registry.handler(&codex_tools::ToolName::namespaced(
|
||||
"mcp__codex_apps__calendar",
|
||||
"codex_apps__calendar",
|
||||
tool_name,
|
||||
));
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ async fn parallel_support_does_not_match_namespaced_local_tool_names() -> anyhow
|
||||
.expect("test session should expose a parallel shell-like tool");
|
||||
|
||||
assert!(!router.tool_supports_parallel(&ToolCall {
|
||||
tool_name: ToolName::namespaced("mcp__server__", parallel_tool_name),
|
||||
tool_name: ToolName::namespaced("server", parallel_tool_name),
|
||||
call_id: "call-namespaced-tool".to_string(),
|
||||
payload: ToolPayload::Function {
|
||||
arguments: "{}".to_string(),
|
||||
@@ -76,7 +76,7 @@ async fn build_tool_call_uses_namespace_for_registry_name() -> anyhow::Result<()
|
||||
ResponseItem::FunctionCall {
|
||||
id: None,
|
||||
name: tool_name.clone(),
|
||||
namespace: Some("mcp__codex_apps__calendar".to_string()),
|
||||
namespace: Some("codex_apps__calendar".to_string()),
|
||||
arguments: "{}".to_string(),
|
||||
call_id: "call-namespace".to_string(),
|
||||
},
|
||||
@@ -86,7 +86,7 @@ async fn build_tool_call_uses_namespace_for_registry_name() -> anyhow::Result<()
|
||||
|
||||
assert_eq!(
|
||||
call.tool_name,
|
||||
ToolName::namespaced("mcp__codex_apps__calendar", tool_name)
|
||||
ToolName::namespaced("codex_apps__calendar", tool_name)
|
||||
);
|
||||
assert_eq!(call.call_id, "call-namespace");
|
||||
match call.payload {
|
||||
@@ -115,7 +115,7 @@ async fn mcp_parallel_support_uses_exact_payload_server() -> anyhow::Result<()>
|
||||
);
|
||||
|
||||
let deferred_call = ToolCall {
|
||||
tool_name: ToolName::namespaced("mcp__echo__", "query_with_delay"),
|
||||
tool_name: ToolName::namespaced("echo", "query_with_delay"),
|
||||
call_id: "call-deferred".to_string(),
|
||||
payload: ToolPayload::Mcp {
|
||||
server: "echo".to_string(),
|
||||
@@ -126,7 +126,7 @@ async fn mcp_parallel_support_uses_exact_payload_server() -> anyhow::Result<()>
|
||||
assert!(router.tool_supports_parallel(&deferred_call));
|
||||
|
||||
let different_server_call = ToolCall {
|
||||
tool_name: ToolName::namespaced("mcp__hello_echo__", "query_with_delay"),
|
||||
tool_name: ToolName::namespaced("hello_echo", "query_with_delay"),
|
||||
call_id: "call-other-server".to_string(),
|
||||
payload: ToolPayload::Mcp {
|
||||
server: "hello_echo".to_string(),
|
||||
|
||||
@@ -61,7 +61,7 @@ fn mcp_tool_info(tool: rmcp::model::Tool) -> ToolInfo {
|
||||
ToolInfo {
|
||||
server_name: "test_server".to_string(),
|
||||
callable_name: tool.name.to_string(),
|
||||
callable_namespace: "mcp__test_server__".to_string(),
|
||||
callable_namespace: "test_server".to_string(),
|
||||
server_instructions: None,
|
||||
tool,
|
||||
connector_id: None,
|
||||
@@ -133,7 +133,7 @@ fn deferred_responses_api_tool_serializes_with_defer_loading() {
|
||||
|
||||
let serialized = serde_json::to_value(ToolSpec::Function(
|
||||
mcp_tool_to_deferred_responses_api_tool(
|
||||
&ToolName::namespaced("mcp__codex_apps__", "lookup_order"),
|
||||
&ToolName::namespaced("codex_apps", "lookup_order"),
|
||||
&tool,
|
||||
)
|
||||
.expect("convert deferred tool"),
|
||||
@@ -893,11 +893,11 @@ async fn search_tool_description_falls_back_to_connector_name_without_descriptio
|
||||
&tools_config,
|
||||
/*mcp_tools*/ None,
|
||||
Some(HashMap::from([(
|
||||
"mcp__codex_apps__calendar_create_event".to_string(),
|
||||
"codex_apps__calendar__create_event".to_string(),
|
||||
ToolInfo {
|
||||
server_name: CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
callable_name: "_create_event".to_string(),
|
||||
callable_namespace: "mcp__codex_apps__calendar".to_string(),
|
||||
callable_name: "create_event".to_string(),
|
||||
callable_namespace: "codex_apps__calendar".to_string(),
|
||||
server_instructions: None,
|
||||
tool: mcp_tool(
|
||||
"calendar_create_event",
|
||||
@@ -945,11 +945,11 @@ async fn search_tool_registers_namespaced_mcp_tool_aliases() {
|
||||
/*mcp_tools*/ None,
|
||||
Some(HashMap::from([
|
||||
(
|
||||
"mcp__codex_apps__calendar_create_event".to_string(),
|
||||
"codex_apps__calendar__create_event".to_string(),
|
||||
ToolInfo {
|
||||
server_name: CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
callable_name: "_create_event".to_string(),
|
||||
callable_namespace: "mcp__codex_apps__calendar".to_string(),
|
||||
callable_name: "create_event".to_string(),
|
||||
callable_namespace: "codex_apps__calendar".to_string(),
|
||||
server_instructions: None,
|
||||
tool: mcp_tool(
|
||||
"calendar-create-event",
|
||||
@@ -963,11 +963,11 @@ async fn search_tool_registers_namespaced_mcp_tool_aliases() {
|
||||
},
|
||||
),
|
||||
(
|
||||
"mcp__codex_apps__calendar_list_events".to_string(),
|
||||
"codex_apps__calendar__list_events".to_string(),
|
||||
ToolInfo {
|
||||
server_name: CODEX_APPS_MCP_SERVER_NAME.to_string(),
|
||||
callable_name: "_list_events".to_string(),
|
||||
callable_namespace: "mcp__codex_apps__calendar".to_string(),
|
||||
callable_name: "list_events".to_string(),
|
||||
callable_namespace: "codex_apps__calendar".to_string(),
|
||||
server_instructions: None,
|
||||
tool: mcp_tool(
|
||||
"calendar-list-events",
|
||||
@@ -981,11 +981,11 @@ async fn search_tool_registers_namespaced_mcp_tool_aliases() {
|
||||
},
|
||||
),
|
||||
(
|
||||
"mcp__rmcp__echo".to_string(),
|
||||
"rmcp__echo".to_string(),
|
||||
ToolInfo {
|
||||
server_name: "rmcp".to_string(),
|
||||
callable_name: "echo".to_string(),
|
||||
callable_namespace: "mcp__rmcp__".to_string(),
|
||||
callable_namespace: "rmcp".to_string(),
|
||||
server_instructions: None,
|
||||
tool: mcp_tool("echo", "Echo", serde_json::json!({"type": "object"})),
|
||||
connector_id: None,
|
||||
@@ -999,8 +999,8 @@ async fn search_tool_registers_namespaced_mcp_tool_aliases() {
|
||||
)
|
||||
.build();
|
||||
|
||||
let app_alias = ToolName::namespaced("mcp__codex_apps__calendar", "_create_event");
|
||||
let mcp_alias = ToolName::namespaced("mcp__rmcp__", "echo");
|
||||
let app_alias = ToolName::namespaced("codex_apps__calendar", "create_event");
|
||||
let mcp_alias = ToolName::namespaced("rmcp", "echo");
|
||||
|
||||
assert!(registry.has_handler(&ToolName::plain(TOOL_SEARCH_TOOL_NAME)));
|
||||
assert!(registry.has_handler(&app_alias));
|
||||
@@ -1025,7 +1025,7 @@ async fn tool_search_entries_skip_namespace_outputs_when_namespace_tools_are_dis
|
||||
});
|
||||
tools_config.namespace_tools = false;
|
||||
let mcp_tools = HashMap::from([(
|
||||
"mcp__test_server__echo".to_string(),
|
||||
"test_server__echo".to_string(),
|
||||
mcp_tool_info(mcp_tool(
|
||||
"echo",
|
||||
"Echo",
|
||||
@@ -1084,7 +1084,7 @@ async fn direct_mcp_tools_register_namespaced_handlers() {
|
||||
let (_, registry) = build_specs(
|
||||
&tools_config,
|
||||
Some(HashMap::from([(
|
||||
"mcp__test_server__echo".to_string(),
|
||||
"test_server__echo".to_string(),
|
||||
mcp_tool_info(mcp_tool(
|
||||
"echo",
|
||||
"Echo",
|
||||
@@ -1096,8 +1096,8 @@ async fn direct_mcp_tools_register_namespaced_handlers() {
|
||||
)
|
||||
.build();
|
||||
|
||||
assert!(registry.has_handler(&ToolName::namespaced("mcp__test_server__", "echo")));
|
||||
assert!(!registry.has_handler(&ToolName::plain("mcp__test_server__echo")));
|
||||
assert!(registry.has_handler(&ToolName::namespaced("test_server", "echo")));
|
||||
assert!(!registry.has_handler(&ToolName::plain("test_server__echo")));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
@@ -1118,7 +1118,7 @@ async fn unavailable_mcp_tools_are_exposed_as_dummy_function_tools() {
|
||||
windows_sandbox_level: WindowsSandboxLevel::Disabled,
|
||||
});
|
||||
|
||||
let unavailable_tool = ToolName::namespaced("mcp__codex_apps__calendar", "_create_event");
|
||||
let unavailable_tool = ToolName::namespaced("codex_apps__calendar", "create_event");
|
||||
let (tools, registry) = build_specs_with_unavailable_tools(
|
||||
&tools_config,
|
||||
/*mcp_tools*/ None,
|
||||
@@ -1128,7 +1128,7 @@ async fn unavailable_mcp_tools_are_exposed_as_dummy_function_tools() {
|
||||
)
|
||||
.build();
|
||||
|
||||
let tool = find_tool(&tools, "mcp__codex_apps__calendar_create_event");
|
||||
let tool = find_tool(&tools, "codex_apps__calendar__create_event");
|
||||
let ToolSpec::Function(ResponsesApiTool {
|
||||
description,
|
||||
parameters,
|
||||
@@ -1143,10 +1143,10 @@ async fn unavailable_mcp_tools_are_exposed_as_dummy_function_tools() {
|
||||
Some(AdditionalProperties::Boolean(false))
|
||||
);
|
||||
assert!(registry.has_handler(&ToolName::namespaced(
|
||||
"mcp__codex_apps__calendar",
|
||||
"_create_event"
|
||||
"codex_apps__calendar",
|
||||
"create_event"
|
||||
)));
|
||||
assert!(!registry.has_handler(&ToolName::plain("mcp__codex_apps__calendar_create_event")));
|
||||
assert!(!registry.has_handler(&ToolName::plain("codex_apps__calendar__create_event")));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -39,7 +39,10 @@ pub(crate) fn collect_unavailable_called_tools(
|
||||
}
|
||||
|
||||
fn should_collect_unavailable_tool(name: &str, namespace: Option<&str>) -> bool {
|
||||
namespace.is_some_and(|namespace| namespace.starts_with("mcp__")) || name.starts_with("mcp__")
|
||||
// New histories preserve the namespace split, so any missing namespaced call
|
||||
// is eligible for a placeholder. Keep the flattened MCP branch for rollouts
|
||||
// written before namespaced MCP calls were preserved in history.
|
||||
namespace.is_some() || name.starts_with("mcp__")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -58,11 +61,12 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn collect_unavailable_called_tools_detects_mcp_function_calls() {
|
||||
fn collect_unavailable_called_tools_detects_namespaced_and_legacy_mcp_calls() {
|
||||
let input = vec![
|
||||
function_call("shell", /*namespace*/ None),
|
||||
function_call("mcp__server__lookup", /*namespace*/ None),
|
||||
function_call("_create_event", Some("mcp__codex_apps__calendar")),
|
||||
function_call("lookup", Some("calendar")),
|
||||
];
|
||||
|
||||
let tools = collect_unavailable_called_tools(&input, &HashSet::new());
|
||||
@@ -70,6 +74,7 @@ mod tests {
|
||||
assert_eq!(
|
||||
tools,
|
||||
vec![
|
||||
ToolName::namespaced("calendar", "lookup"),
|
||||
ToolName::namespaced("mcp__codex_apps__calendar", "_create_event"),
|
||||
ToolName::plain("mcp__server__lookup"),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user