Compare commits

...

2 Commits

Author SHA1 Message Date
jif-oai
f866570696 Merge branch 'main' into jif/mcp-mem-pollution 2026-05-06 16:23:51 +02:00
jif-oai
d022f897ab feat: disable pollution check for memories MCP 2026-05-06 14:26:49 +01:00
4 changed files with 57 additions and 4 deletions

View File

@@ -4304,6 +4304,35 @@ async fn to_mcp_config_omits_builtin_mcps_when_feature_is_disabled() -> std::io:
Ok(())
}
#[tokio::test]
async fn to_mcp_config_reserves_builtin_mcp_names_when_feature_is_disabled() -> std::io::Result<()>
{
let codex_home = TempDir::new()?;
let config = Config::load_from_base_config_with_overrides(
ConfigToml {
mcp_servers: HashMap::from([(
codex_mcp::MEMORIES_MCP_SERVER_NAME.to_string(),
http_mcp("https://user.example/memories"),
)]),
..ConfigToml::default()
},
ConfigOverrides::default(),
codex_home.abs(),
)
.await?;
let plugins_manager = PluginsManager::new(codex_home.path().to_path_buf());
let mcp_config = config.to_mcp_config(&plugins_manager).await;
assert!(
!mcp_config
.configured_mcp_servers
.contains_key(codex_mcp::MEMORIES_MCP_SERVER_NAME)
);
Ok(())
}
#[tokio::test]
async fn to_mcp_config_reserves_enabled_builtin_mcp_names() -> std::io::Result<()> {
let codex_home = TempDir::new()?;

View File

@@ -1097,6 +1097,8 @@ impl Config {
&& self.memories.use_memories,
});
let mut configured_mcp_servers = self.mcp_servers.get().clone();
// Built-in server names are reserved even when the built-in itself is disabled.
configured_mcp_servers.remove(codex_mcp::MEMORIES_MCP_SERVER_NAME);
for plugin in loaded_plugins
.plugins()
.iter()
@@ -1109,6 +1111,9 @@ impl Config {
self.config_layer_stack.requirements().plugins.as_ref(),
);
for (name, plugin_server) in plugin_mcp_servers {
if name == codex_mcp::MEMORIES_MCP_SERVER_NAME {
continue;
}
configured_mcp_servers.entry(name).or_insert(plugin_server);
}
}

View File

@@ -42,6 +42,7 @@ use codex_features::Feature;
use codex_hooks::PermissionRequestDecision;
use codex_mcp::CODEX_APPS_MCP_SERVER_NAME;
use codex_mcp::MCP_TOOL_CODEX_APPS_META_KEY;
use codex_mcp::MEMORIES_MCP_SERVER_NAME;
use codex_mcp::McpPermissionPromptAutoApproveContext;
use codex_mcp::SandboxState;
use codex_mcp::auth_elicitation_completed_result;
@@ -310,9 +311,9 @@ async fn handle_approved_mcp_tool_call(
request_meta: Option<JsonValue>,
mcp_app_resource_uri: Option<String>,
) -> HandledMcpToolCall {
maybe_mark_thread_memory_mode_polluted(sess, turn_context).await;
let server = invocation.server.clone();
maybe_mark_thread_memory_mode_polluted(sess, turn_context, &server).await;
let tool_name = invocation.tool.clone();
let arguments_value = invocation.arguments.clone();
let connector_id = metadata.and_then(|metadata| metadata.connector_id.as_deref());
@@ -738,8 +739,14 @@ async fn augment_mcp_tool_request_meta_with_sandbox_state(
Ok(meta)
}
async fn maybe_mark_thread_memory_mode_polluted(sess: &Session, turn_context: &TurnContext) {
if !turn_context.config.memories.disable_on_external_context {
async fn maybe_mark_thread_memory_mode_polluted(
sess: &Session,
turn_context: &TurnContext,
server_name: &str,
) {
if !turn_context.config.memories.disable_on_external_context
|| !mcp_tool_call_may_include_external_context(server_name)
{
return;
}
state_db::mark_thread_memory_mode_polluted(
@@ -750,6 +757,10 @@ async fn maybe_mark_thread_memory_mode_polluted(sess: &Session, turn_context: &T
.await;
}
fn mcp_tool_call_may_include_external_context(server_name: &str) -> bool {
server_name != MEMORIES_MCP_SERVER_NAME
}
fn sanitize_mcp_tool_result_for_model(
supports_image_input: bool,
result: Result<CallToolResult, String>,

View File

@@ -1129,6 +1129,14 @@ async fn install_host_owned_codex_apps_manager(session: &Session, turn_context:
*session.services.mcp_connection_manager.write().await = manager;
}
#[test]
fn memories_mcp_call_does_not_include_external_context() {
assert!(!mcp_tool_call_may_include_external_context(
MEMORIES_MCP_SERVER_NAME
));
assert!(mcp_tool_call_may_include_external_context("external"));
}
#[tokio::test]
async fn codex_apps_auth_elicitation_feature_disabled_returns_original_result() {
let (session, turn_context, rx_event) = make_session_and_context_with_rx().await;