mirror of
https://github.com/openai/codex.git
synced 2026-10-22 17:58:46 +00:00
## Why `codex-mcp` already owns the shared MCP API surface, including `auth`, `McpConfig`, `CODEX_APPS_MCP_SERVER_NAME`, and tool-name helpers in [`codex-rs/codex-mcp/src/mcp/mod.rs`](https://github.com/openai/codex/blob/f61e85dbfb5373cde6827d232ac8ea447c237e81/codex-rs/codex-mcp/src/mcp/mod.rs#L1-L35). Re-exporting that surface from `codex_core::mcp` gives downstream crates two import paths for the same API and hides the real crate dependency. This PR keeps `codex_core::mcp` focused on the local `McpManager` wrapper in [`codex-rs/core/src/mcp.rs`](https://github.com/openai/codex/blob/f61e85dbfb5373cde6827d232ac8ea447c237e81/codex-rs/core/src/mcp.rs#L13-L40) and makes consumers import shared MCP APIs from `codex_mcp` directly. ## What - Remove the `codex_mcp::mcp` re-export surface from `core/src/mcp.rs`. - Update `codex-core` internals plus `codex-app-server`, `codex-cli`, and `codex-tui` test code to import MCP APIs from `codex_mcp::mcp` directly. - Add explicit `codex-mcp` dependencies where those crates now use that API surface, and refresh `Cargo.lock`. ## Verification - `just bazel-lock-check` - `cargo test -p codex-core -p codex-cli -p codex-tui` - `codex-cli` passed. - `codex-core` still fails five unrelated config tests in `core/src/config/config_tests.rs` (`approvals_reviewer_*` and `smart_approvals_alias_*`). - A broader `cargo test -p codex-core -p codex-app-server -p codex-cli -p codex-tui` run previously hung in `codex-app-server` test `in_process_start_uses_requested_session_source_for_thread_start`.
73 lines
2.7 KiB
Rust
73 lines
2.7 KiB
Rust
use codex_app_server_protocol::AppInfo;
|
|
use codex_mcp::mcp::CODEX_APPS_MCP_SERVER_NAME;
|
|
use codex_protocol::protocol::APPS_INSTRUCTIONS_CLOSE_TAG;
|
|
use codex_protocol::protocol::APPS_INSTRUCTIONS_OPEN_TAG;
|
|
|
|
pub(crate) fn render_apps_section(connectors: &[AppInfo]) -> Option<String> {
|
|
if !connectors
|
|
.iter()
|
|
.any(|connector| connector.is_accessible && connector.is_enabled)
|
|
{
|
|
return None;
|
|
}
|
|
|
|
let body = format!(
|
|
"## Apps (Connectors)\nApps (Connectors) can be explicitly triggered in user messages in the format `[$app-name](app://{{connector_id}})`. Apps can also be implicitly triggered as long as the context suggests usage of available apps.\nAn app is equivalent to a set of MCP tools within the `{CODEX_APPS_MCP_SERVER_NAME}` MCP.\nAn installed app's MCP tools are either provided to you already, or can be lazy-loaded through the `tool_search` tool. If `tool_search` is available, the apps that are searchable by `tools_search` will be listed by it.\nDo not additionally call list_mcp_resources or list_mcp_resource_templates for apps."
|
|
);
|
|
Some(format!(
|
|
"{APPS_INSTRUCTIONS_OPEN_TAG}\n{body}\n{APPS_INSTRUCTIONS_CLOSE_TAG}"
|
|
))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
fn connector(id: &str, is_accessible: bool, is_enabled: bool) -> AppInfo {
|
|
AppInfo {
|
|
id: id.to_string(),
|
|
name: id.to_string(),
|
|
description: None,
|
|
logo_url: None,
|
|
logo_url_dark: None,
|
|
distribution_channel: None,
|
|
branding: None,
|
|
app_metadata: None,
|
|
labels: None,
|
|
install_url: None,
|
|
is_accessible,
|
|
is_enabled,
|
|
plugin_display_names: Vec::new(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn omits_apps_section_without_accessible_and_enabled_apps() {
|
|
assert_eq!(render_apps_section(&[]), None);
|
|
assert_eq!(
|
|
render_apps_section(&[connector(
|
|
"calendar", /*is_accessible*/ true, /*is_enabled*/ false
|
|
)]),
|
|
None
|
|
);
|
|
assert_eq!(
|
|
render_apps_section(&[connector(
|
|
"calendar", /*is_accessible*/ false, /*is_enabled*/ true
|
|
)]),
|
|
None
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn renders_apps_section_with_an_accessible_and_enabled_app() {
|
|
let rendered = render_apps_section(&[connector(
|
|
"calendar", /*is_accessible*/ true, /*is_enabled*/ true,
|
|
)])
|
|
.expect("expected apps section");
|
|
|
|
assert!(rendered.starts_with(APPS_INSTRUCTIONS_OPEN_TAG));
|
|
assert!(rendered.contains("## Apps (Connectors)"));
|
|
assert!(rendered.ends_with(APPS_INSTRUCTIONS_CLOSE_TAG));
|
|
}
|
|
}
|