mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Use MCP server instructions in deferred namespace descriptions (#21053)
## Why MCP servers can provide `instructions` that explain what their tools are for. Directly exposed MCP namespaces already use those instructions when a connector description is not available, but deferred `tool_search` results did not preserve that fallback. The direct path falls back from connector metadata to server instructions, while the deferred path only carried `connector_description` and otherwise fell back to generic namespace text. That meant a plain MCP server could provide useful model-facing guidance and still appear as `Tools in the X namespace.` whenever it was discovered lazily through `tool_search`. ## What changed - Store one model-facing `namespace_description` on `ToolInfo`, using connector descriptions for connector-backed tools and server instructions for plain MCP servers. - Thread that namespace description through the `tool_search` source list, search indexing, and returned namespace metadata. - Add an end-to-end regression test for deferred non-app MCP search results exposing server instructions as the namespace description. ## Verification - `cargo test -p codex-tools search_tool_description_lists_each_mcp_source_once --lib` - `cargo test -p codex-core --test all tool_search_uses_non_app_mcp_server_instructions_as_namespace_description`
This commit is contained in:
@@ -27,7 +27,7 @@ pub struct ToolSearchSourceInfo {
|
||||
pub struct ToolSearchSource<'a> {
|
||||
pub server_name: &'a str,
|
||||
pub connector_name: Option<&'a str>,
|
||||
pub connector_description: Option<&'a str>,
|
||||
pub description: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
@@ -37,7 +37,7 @@ pub struct ToolSearchResultSource<'a> {
|
||||
pub tool_name: &'a str,
|
||||
pub tool: &'a rmcp::model::Tool,
|
||||
pub connector_name: Option<&'a str>,
|
||||
pub connector_description: Option<&'a str>,
|
||||
pub description: Option<&'a str>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)]
|
||||
@@ -215,7 +215,7 @@ pub fn tool_search_result_source_to_loadable_tool_spec(
|
||||
|
||||
fn tool_search_result_source_namespace_description(source: ToolSearchResultSource<'_>) -> String {
|
||||
source
|
||||
.connector_description
|
||||
.description
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(str::to_string)
|
||||
@@ -251,7 +251,7 @@ pub fn collect_tool_search_source_infos<'a>(
|
||||
return Some(ToolSearchSourceInfo {
|
||||
name: name.to_string(),
|
||||
description: tool
|
||||
.connector_description
|
||||
.description
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(str::to_string),
|
||||
@@ -265,7 +265,11 @@ pub fn collect_tool_search_source_infos<'a>(
|
||||
|
||||
Some(ToolSearchSourceInfo {
|
||||
name: name.to_string(),
|
||||
description: None,
|
||||
description: tool
|
||||
.description
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(str::to_string),
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
|
||||
@@ -282,7 +282,7 @@ pub fn build_tool_registry_plan(
|
||||
ToolSearchSource {
|
||||
server_name: tool.server_name,
|
||||
connector_name: tool.connector_name,
|
||||
connector_description: tool.connector_description,
|
||||
description: tool.description,
|
||||
}
|
||||
}))
|
||||
})
|
||||
|
||||
@@ -1414,7 +1414,7 @@ fn search_tool_description_lists_each_mcp_source_once() {
|
||||
"mcp__rmcp__",
|
||||
"rmcp",
|
||||
/*connector_name*/ None,
|
||||
/*connector_description*/ None,
|
||||
Some("Remote memory tools."),
|
||||
),
|
||||
]),
|
||||
&[],
|
||||
@@ -1433,7 +1433,7 @@ fn search_tool_description_lists_each_mcp_source_once() {
|
||||
.count(),
|
||||
1
|
||||
);
|
||||
assert!(description.contains("- rmcp"));
|
||||
assert!(description.contains("- rmcp: Remote memory tools."));
|
||||
assert!(!description.contains("mcp__rmcp__echo"));
|
||||
|
||||
assert!(handlers.contains(&ToolHandlerSpec {
|
||||
@@ -1454,7 +1454,7 @@ fn search_tool_requires_model_capability_and_enabled_feature() {
|
||||
"mcp__codex_apps__calendar",
|
||||
CODEX_APPS_MCP_SERVER_NAME,
|
||||
Some("Calendar"),
|
||||
/*connector_description*/ None,
|
||||
/*description*/ None,
|
||||
)]);
|
||||
|
||||
let features = Features::with_defaults();
|
||||
@@ -2355,13 +2355,13 @@ fn deferred_mcp_tool<'a>(
|
||||
tool_namespace: &'a str,
|
||||
server_name: &'a str,
|
||||
connector_name: Option<&'a str>,
|
||||
connector_description: Option<&'a str>,
|
||||
description: Option<&'a str>,
|
||||
) -> ToolRegistryPlanDeferredTool<'a> {
|
||||
ToolRegistryPlanDeferredTool {
|
||||
name: ToolName::namespaced(tool_namespace, tool_name),
|
||||
server_name,
|
||||
connector_name,
|
||||
connector_description,
|
||||
description,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ pub struct ToolRegistryPlanDeferredTool<'a> {
|
||||
pub name: ToolName,
|
||||
pub server_name: &'a str,
|
||||
pub connector_name: Option<&'a str>,
|
||||
pub connector_description: Option<&'a str>,
|
||||
pub description: Option<&'a str>,
|
||||
}
|
||||
|
||||
impl ToolRegistryPlan {
|
||||
|
||||
Reference in New Issue
Block a user