mirror of
https://github.com/openai/codex.git
synced 2026-04-24 14:45:27 +00:00
Chore: read mcp servers config via app server
This commit is contained in:
@@ -242,6 +242,10 @@ client_request_definitions! {
|
||||
params: #[ts(type = "undefined")] #[serde(skip_serializing_if = "Option::is_none")] Option<()>,
|
||||
response: v1::GetUserSavedConfigResponse,
|
||||
},
|
||||
GetMcpServersConfig {
|
||||
params: #[ts(type = "undefined")] #[serde(skip_serializing_if = "Option::is_none")] Option<()>,
|
||||
response: v2::GetMcpServersConfigResponse,
|
||||
},
|
||||
SetDefaultModel {
|
||||
params: v1::SetDefaultModelParams,
|
||||
response: v1::SetDefaultModelResponse,
|
||||
|
||||
@@ -210,6 +210,55 @@ impl From<codex_protocol::protocol::SandboxPolicy> for SandboxPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct GetMcpServersConfigResponse {
|
||||
pub servers: HashMap<String, McpServerConfig>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase", tag = "type")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub enum McpServerTransportConfig {
|
||||
Stdio {
|
||||
command: String,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
args: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
env: Option<HashMap<String, String>>,
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
env_vars: Vec<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
cwd: Option<PathBuf>,
|
||||
},
|
||||
StreamableHttp {
|
||||
url: String,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
bearer_token_env_var: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
http_headers: Option<HashMap<String, String>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
env_http_headers: Option<HashMap<String, String>>,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
pub struct McpServerConfig {
|
||||
pub transport: McpServerTransportConfig,
|
||||
pub enabled: bool,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub startup_timeout_sec: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub tool_timeout_sec: Option<i64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub enabled_tools: Option<Vec<String>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub disabled_tools: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[ts(export_to = "v2/")]
|
||||
|
||||
@@ -36,6 +36,7 @@ use codex_app_server_protocol::GetAuthStatusParams;
|
||||
use codex_app_server_protocol::GetAuthStatusResponse;
|
||||
use codex_app_server_protocol::GetConversationSummaryParams;
|
||||
use codex_app_server_protocol::GetConversationSummaryResponse;
|
||||
use codex_app_server_protocol::GetMcpServersConfigResponse;
|
||||
use codex_app_server_protocol::GetUserAgentResponse;
|
||||
use codex_app_server_protocol::GetUserSavedConfigResponse;
|
||||
use codex_app_server_protocol::GitDiffToRemoteResponse;
|
||||
@@ -52,6 +53,8 @@ use codex_app_server_protocol::LoginChatGptCompleteNotification;
|
||||
use codex_app_server_protocol::LoginChatGptResponse;
|
||||
use codex_app_server_protocol::LogoutAccountResponse;
|
||||
use codex_app_server_protocol::LogoutChatGptResponse;
|
||||
use codex_app_server_protocol::McpServerConfig as WireMcpServerConfig;
|
||||
use codex_app_server_protocol::McpServerTransportConfig as WireMcpServerTransportConfig;
|
||||
use codex_app_server_protocol::ModelListParams;
|
||||
use codex_app_server_protocol::ModelListResponse;
|
||||
use codex_app_server_protocol::NewConversationParams;
|
||||
@@ -110,6 +113,8 @@ use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::config::ConfigToml;
|
||||
use codex_core::config::edit::ConfigEditsBuilder;
|
||||
use codex_core::config::types::McpServerConfig as CoreMcpServerConfig;
|
||||
use codex_core::config::types::McpServerTransportConfig as CoreMcpServerTransportConfig;
|
||||
use codex_core::config_loader::load_config_as_toml;
|
||||
use codex_core::default_client::get_codex_user_agent;
|
||||
use codex_core::exec::ExecParams;
|
||||
@@ -451,6 +456,12 @@ impl CodexMessageProcessor {
|
||||
} => {
|
||||
self.get_user_saved_config(request_id).await;
|
||||
}
|
||||
ClientRequest::GetMcpServersConfig {
|
||||
request_id,
|
||||
params: _,
|
||||
} => {
|
||||
self.get_mcp_servers_config(request_id).await;
|
||||
}
|
||||
ClientRequest::SetDefaultModel { request_id, params } => {
|
||||
self.set_default_model(request_id, params).await;
|
||||
}
|
||||
@@ -1116,6 +1127,17 @@ impl CodexMessageProcessor {
|
||||
self.outgoing.send_response(request_id, response).await;
|
||||
}
|
||||
|
||||
async fn get_mcp_servers_config(&self, request_id: RequestId) {
|
||||
let servers = self
|
||||
.config
|
||||
.mcp_servers
|
||||
.iter()
|
||||
.map(|(name, server)| (name.clone(), to_wire_mcp_server_config(server)))
|
||||
.collect();
|
||||
let response = GetMcpServersConfigResponse { servers };
|
||||
self.outgoing.send_response(request_id, response).await;
|
||||
}
|
||||
|
||||
async fn get_user_info(&self, request_id: RequestId) {
|
||||
// Read alleged user email from cached auth (best-effort; not verified).
|
||||
let alleged_user_email = self.auth_manager.auth().and_then(|a| a.get_account_email());
|
||||
@@ -2847,6 +2869,48 @@ impl CodexMessageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
fn to_wire_mcp_server_config(config: &CoreMcpServerConfig) -> WireMcpServerConfig {
|
||||
let transport = match &config.transport {
|
||||
CoreMcpServerTransportConfig::Stdio {
|
||||
command,
|
||||
args,
|
||||
env,
|
||||
env_vars,
|
||||
cwd,
|
||||
} => WireMcpServerTransportConfig::Stdio {
|
||||
command: command.clone(),
|
||||
args: args.clone(),
|
||||
env: env.clone(),
|
||||
env_vars: env_vars.clone(),
|
||||
cwd: cwd.clone(),
|
||||
},
|
||||
CoreMcpServerTransportConfig::StreamableHttp {
|
||||
url,
|
||||
bearer_token_env_var,
|
||||
http_headers,
|
||||
env_http_headers,
|
||||
} => WireMcpServerTransportConfig::StreamableHttp {
|
||||
url: url.clone(),
|
||||
bearer_token_env_var: bearer_token_env_var.clone(),
|
||||
http_headers: http_headers.clone(),
|
||||
env_http_headers: env_http_headers.clone(),
|
||||
},
|
||||
};
|
||||
|
||||
WireMcpServerConfig {
|
||||
transport,
|
||||
enabled: config.enabled,
|
||||
startup_timeout_sec: config.startup_timeout_sec.and_then(duration_to_seconds),
|
||||
tool_timeout_sec: config.tool_timeout_sec.and_then(duration_to_seconds),
|
||||
enabled_tools: config.enabled_tools.clone(),
|
||||
disabled_tools: config.disabled_tools.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn duration_to_seconds(duration: Duration) -> Option<i64> {
|
||||
i64::try_from(duration.as_secs()).ok()
|
||||
}
|
||||
|
||||
async fn derive_config_from_params(
|
||||
overrides: ConfigOverrides,
|
||||
cli_overrides: Option<std::collections::HashMap<String, serde_json::Value>>,
|
||||
|
||||
Reference in New Issue
Block a user