Add config toggles for orchestrator skills and MCP (#28942)

## Why

Orchestrator-provided skills and Codex Apps MCP tools add model-visible
instructions, resources, and tools beyond the local workspace. Hosts
need config-level switches to disable those orchestrator-owned surfaces
independently, without disabling regular skills or regular MCP servers.

## What changed

- Adds `[orchestrator.skills].enabled` and `[orchestrator.mcp].enabled`
config entries, both defaulting to `true`.
- Includes the new settings in `config.schema.json` and in the config
lock so resolved thread configuration preserves the same orchestrator
exposure decisions.
- Threads `orchestrator.skills.enabled` through the app-server skills
extension so disabled orchestrator skills do not expose the `skills`
namespace or inject orchestrator skill context.
- Gates Codex Apps MCP exposure, app instructions, and app auth
eligibility on `orchestrator.mcp.enabled` while leaving non-Codex-Apps
MCP tools available.
- Updates the thread-manager sample config to disable both
orchestrator-owned surfaces.

## Verification

- Added config parsing, loading, defaulting, and schema coverage for the
new settings.
- Added MCP exposure coverage that `orchestrator.mcp.enabled = false`
removes Codex Apps tools while preserving regular MCP tools.
- Added app-server coverage that `orchestrator.skills.enabled = false`
prevents orchestrator skill tools, prompts, and resource reads from
reaching the model turn.
This commit is contained in:
jif authored and GitHub committed 2026-06-19 14:42:26 +02:00
1 parent 3a2712ea14
commit 81b000421d
20 files changed
+405 -20

No files matched your search

+33
View File
@@ -9111,6 +9111,39 @@ apps_mcp_product_sku = "tpp"
Ok(())
}
#[tokio::test]
async fn config_loads_orchestrator_settings_from_toml() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
let cfg: ConfigToml = toml::from_str(
r#"
model = "gpt-5.4"
[orchestrator.skills]
enabled = false
[orchestrator.mcp]
enabled = false
"#,
)
.expect("TOML deserialization should succeed for orchestrator settings");
let config = Config::load_from_base_config_with_overrides(
cfg,
ConfigOverrides::default(),
codex_home.abs(),
)
.await?;
assert_eq!(
(
config.orchestrator_skills_enabled,
config.orchestrator_mcp_enabled
),
(false, false)
);
Ok(())
}
#[tokio::test]
async fn config_loads_mcp_oauth_callback_url_from_toml() -> std::io::Result<()> {
let codex_home = TempDir::new()?;
+19
View File
@@ -690,6 +690,12 @@ pub struct Config {
/// Whether to inject the `<skills_instructions>` developer block.
pub include_skill_instructions: bool,
/// Whether orchestrator-owned skills are exposed to the model.
pub orchestrator_skills_enabled: bool,
/// Whether orchestrator-owned MCP tools are exposed to the model.
pub orchestrator_mcp_enabled: bool,
/// Whether to inject the `<environment_context>` user block.
pub include_environment_context: bool,
@@ -2425,6 +2431,12 @@ fn resolve_experimental_request_user_input_enabled(config_toml: &ConfigToml) ->
.is_none_or(|config| config.enabled)
}
fn resolve_orchestrator_feature_enabled(
feature: Option<&codex_config::config_toml::OrchestratorFeatureToml>,
) -> bool {
feature.and_then(|feature| feature.enabled).unwrap_or(true)
}
fn resolve_code_mode_config(config_toml: &ConfigToml) -> CodeModeConfig {
let base = code_mode_toml_config(config_toml.features.as_ref());
@@ -2812,6 +2824,11 @@ impl Config {
validate_model_providers(&cfg.model_providers)
.map_err(|message| std::io::Error::new(std::io::ErrorKind::InvalidInput, message))?;
let orchestrator = cfg.orchestrator.as_ref();
let orchestrator_skills_enabled =
resolve_orchestrator_feature_enabled(orchestrator.and_then(|value| value.skills.as_ref()));
let orchestrator_mcp_enabled =
resolve_orchestrator_feature_enabled(orchestrator.and_then(|value| value.mcp.as_ref()));
// Ensure that every field of ConfigRequirements is applied to the final
// Config.
let ConfigRequirements {
@@ -3688,6 +3705,8 @@ impl Config {
include_apps_instructions,
include_collaboration_mode_instructions,
include_skill_instructions,
orchestrator_skills_enabled,
orchestrator_mcp_enabled,
include_environment_context,
// The config.toml omits "_mode" because it's a config file. However, "_mode"
// is important in code to differentiate the mode from the store implementation.