Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codex-rs/app-server/src/request_processors/plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2026,7 +2026,7 @@ fn remote_plugin_detail_to_info(
.collect(),
hooks: Vec::new(),
apps,
mcp_servers: Vec::new(),
mcp_servers: detail.mcp_servers,
}
}

Expand Down
36 changes: 26 additions & 10 deletions codex-rs/app-server/tests/suite/v2/plugin_read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ async fn plugin_read_rejects_multiple_read_sources() -> Result<()> {
}

#[tokio::test]
async fn plugin_read_reads_remote_plugin_details_when_remote_plugin_is_disabled() -> Result<()> {
async fn plugin_read_returns_remote_mcp_servers_when_uninstalled() -> Result<()> {
let codex_home = TempDir::new()?;
let server = MockServer::start().await;
std::fs::write(
Expand All @@ -148,22 +148,31 @@ plugins = true

let detail_body = r#"{
"id": "plugins~Plugin_00000000000000000000000000000000",
"name": "linear",
"name": "example-plugin",
"scope": "GLOBAL",
"installation_policy": "AVAILABLE",
"authentication_policy": "ON_USE",
"release": {
"display_name": "Linear",
"description": "Track work in Linear",
"version": "1.2.1",
"display_name": "Example Plugin",
"description": "Example plugin",
"app_ids": [],
"keywords": [],
"interface": {
"short_description": "Plan and track work",
"short_description": "Example plugin",
"capabilities": [],
"default_prompt": "Use the legacy Linear prompt",
"default_prompt": "Use the legacy example prompt",
"default_prompts": []
},
"skills": []
"skills": [],
"mcp_servers": [
{
"key": "example-server",
"metadata": {
"command": "example-mcp"
}
}
]
}
}"#;
let installed_body = r#"{
Expand Down Expand Up @@ -211,12 +220,15 @@ plugins = true
let response: PluginReadResponse = to_response(response)?;

assert_eq!(response.plugin.marketplace_name, "openai-curated-remote");
assert_eq!(response.plugin.summary.id, "linear@openai-curated-remote");
assert_eq!(
response.plugin.summary.id,
"example-plugin@openai-curated-remote"
);
assert_eq!(
response.plugin.summary.remote_plugin_id.as_deref(),
Some("plugins~Plugin_00000000000000000000000000000000")
);
assert_eq!(response.plugin.summary.name, "linear");
assert_eq!(response.plugin.summary.name, "example-plugin");
assert_eq!(response.plugin.summary.source, PluginSource::Remote);
assert_eq!(response.plugin.summary.share_context, None);
assert_eq!(
Expand All @@ -226,7 +238,11 @@ plugins = true
.interface
.as_ref()
.and_then(|interface| interface.default_prompt.clone()),
Some(vec!["Use the legacy Linear prompt".to_string()])
Some(vec!["Use the legacy example prompt".to_string()])
);
assert_eq!(
response.plugin.mcp_servers,
vec!["example-server".to_string()]
);
Ok(())
}
Expand Down
17 changes: 17 additions & 0 deletions codex-rs/core-plugins/src/remote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ pub struct RemotePluginDetail {
pub app_manifest: Option<JsonValue>,
pub skills: Vec<RemotePluginSkill>,
pub app_ids: Vec<String>,
pub mcp_servers: Vec<String>,
}

#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -417,6 +418,13 @@ struct RemotePluginReleaseResponse {
interface: RemotePluginReleaseInterfaceResponse,
#[serde(default)]
skills: Vec<RemotePluginSkillResponse>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
mcp_servers: Vec<RemotePluginMcpServerResponse>,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
struct RemotePluginMcpServerResponse {
key: String,
}

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
Expand Down Expand Up @@ -948,6 +956,14 @@ async fn build_remote_plugin_detail(
enabled: !disabled_skill_names.contains(&skill.name),
})
.collect();
let mut mcp_servers = plugin
.release
.mcp_servers
.iter()
.map(|server| server.key.clone())
.collect::<Vec<_>>();
mcp_servers.sort_unstable();
mcp_servers.dedup();

Ok(RemotePluginDetail {
marketplace_name,
Expand All @@ -959,6 +975,7 @@ async fn build_remote_plugin_detail(
app_manifest: plugin.release.app_manifest,
skills,
app_ids: plugin.release.app_ids,
mcp_servers,
})
}

Expand Down
Loading