Expose MCP server info as part of server status (#24698)

# Summary

Expose MCP server info via App Server (when available) so apps can
render a richer MCP experience
This commit is contained in:
Gabriel Peal
2026-05-28 09:38:34 -07:00
committed by GitHub
Unverified
parent 2a1158b8e2
commit 8a827d6426
20 changed files with 599 additions and 40 deletions
@@ -2,6 +2,7 @@ use super::shared::v2_enum_from_core;
use codex_protocol::approvals::ElicitationRequest as CoreElicitationRequest;
use codex_protocol::items::McpToolCallError as CoreMcpToolCallError;
use codex_protocol::mcp::CallToolResult as CoreMcpCallToolResult;
use codex_protocol::mcp::McpServerInfo;
use codex_protocol::mcp::Resource as McpResource;
pub use codex_protocol::mcp::ResourceContent as McpResourceContent;
use codex_protocol::mcp::ResourceTemplate as McpResourceTemplate;
@@ -53,6 +54,7 @@ pub enum McpServerStatusDetail {
#[ts(export_to = "v2/")]
pub struct McpServerStatus {
pub name: String,
pub server_info: Option<McpServerInfo>,
pub tools: std::collections::HashMap<String, McpTool>,
pub resources: Vec<McpResource>,
pub resource_templates: Vec<McpResourceTemplate>,
@@ -11,6 +11,7 @@ use codex_protocol::items::TurnItem;
use codex_protocol::items::UserMessageItem;
use codex_protocol::items::WebSearchItem;
use codex_protocol::mcp::CallToolResult;
use codex_protocol::mcp::McpServerInfo;
use codex_protocol::memory_citation::MemoryCitation as CoreMemoryCitation;
use codex_protocol::memory_citation::MemoryCitationEntry as CoreMemoryCitationEntry;
use codex_protocol::models::AdditionalPermissionProfile as CoreAdditionalPermissionProfile;
@@ -2003,6 +2004,80 @@ fn mcp_server_elicitation_response_serializes_nullable_content() {
);
}
#[test]
fn mcp_server_status_serializes_absent_server_info_as_null() {
let response = ListMcpServerStatusResponse {
data: vec![McpServerStatus {
name: "not-ready".to_string(),
server_info: None,
tools: HashMap::new(),
resources: Vec::new(),
resource_templates: Vec::new(),
auth_status: McpAuthStatus::Unsupported,
}],
next_cursor: None,
};
assert_eq!(
serde_json::to_value(response).expect("response should serialize"),
json!({
"data": [{
"name": "not-ready",
"serverInfo": null,
"tools": {},
"resources": [],
"resourceTemplates": [],
"authStatus": "unsupported",
}],
"nextCursor": null,
})
);
}
#[test]
fn mcp_server_status_serializes_absent_server_info_metadata_as_null() {
let response = ListMcpServerStatusResponse {
data: vec![McpServerStatus {
name: "initialized".to_string(),
server_info: Some(McpServerInfo {
name: "lookup-server".to_string(),
title: None,
version: "1.0.0".to_string(),
description: None,
icons: None,
website_url: None,
}),
tools: HashMap::new(),
resources: Vec::new(),
resource_templates: Vec::new(),
auth_status: McpAuthStatus::Unsupported,
}],
next_cursor: None,
};
assert_eq!(
serde_json::to_value(response).expect("response should serialize"),
json!({
"data": [{
"name": "initialized",
"serverInfo": {
"name": "lookup-server",
"title": null,
"version": "1.0.0",
"description": null,
"icons": null,
"websiteUrl": null,
},
"tools": {},
"resources": [],
"resourceTemplates": [],
"authStatus": "unsupported",
}],
"nextCursor": null,
})
);
}
#[test]
fn sandbox_policy_round_trips_workspace_write_access() {
let v2_policy = SandboxPolicy::WorkspaceWrite {