[mcp] Fix legacy_tools (#15885)

- [x] Fix legacy_tools
This commit is contained in:
Matthew Zeng
2026-03-26 11:08:49 -07:00
committed by GitHub
parent 2c54d4b160
commit 25134b592c
4 changed files with 41 additions and 25 deletions

View File

@@ -1258,9 +1258,7 @@
"type": "object"
},
"RawMcpServerConfig": {
"additionalProperties": {
"$ref": "#/definitions/McpServerToolConfig"
},
"additionalProperties": false,
"properties": {
"args": {
"default": null,

View File

@@ -1991,28 +1991,19 @@ approval_mode = "approve"
}
#[test]
fn mcp_servers_toml_parses_legacy_flattened_per_tool_approval_overrides() {
fn mcp_servers_toml_ignores_unknown_server_fields() {
let config = toml::from_str::<ConfigToml>(
r#"
[mcp_servers.docs]
command = "docs-server"
[mcp_servers.docs.search]
approval_mode = "approve"
trust_level = "trusted"
"#,
)
.expect("legacy TOML deserialization should succeed");
let tool = config
.mcp_servers
.get("docs")
.and_then(|server| server.tools.get("search"))
.expect("docs/search tool config exists");
.expect("unknown MCP server fields should be ignored");
assert_eq!(
tool,
&McpServerToolConfig {
approval_mode: Some(AppToolApproval::Approve),
}
config.mcp_servers.get("docs"),
Some(&stdio_mcp("docs-server"))
);
}

View File

@@ -163,10 +163,6 @@ pub(crate) struct RawMcpServerConfig {
pub _name: Option<String>,
#[serde(default)]
pub tools: Option<HashMap<String, McpServerToolConfig>>,
/// Legacy flattened per-tool approval settings accepted for backward compatibility.
#[serde(default)]
#[serde(flatten)]
pub legacy_tools: HashMap<String, McpServerToolConfig>,
}
impl<'de> Deserialize<'de> for McpServerConfig {
@@ -191,10 +187,7 @@ impl<'de> Deserialize<'de> for McpServerConfig {
let disabled_tools = raw.disabled_tools.clone();
let scopes = raw.scopes.clone();
let oauth_resource = raw.oauth_resource.clone();
let mut tools = raw.legacy_tools.clone();
if let Some(nested_tools) = raw.tools.clone() {
tools.extend(nested_tools);
}
let tools = raw.tools.clone().unwrap_or_default();
fn throw_if_set<E, T>(transport: &str, field: &str, value: Option<&T>) -> Result<(), E>
where

View File

@@ -243,6 +243,40 @@ fn deserialize_server_config_with_tool_filters() {
assert_eq!(cfg.disabled_tools, Some(vec!["blocked".to_string()]));
}
#[test]
fn deserialize_ignores_unknown_server_fields() {
let cfg: McpServerConfig = toml::from_str(
r#"
command = "echo"
trust_level = "trusted"
"#,
)
.expect("should ignore unknown server fields");
assert_eq!(
cfg,
McpServerConfig {
transport: McpServerTransportConfig::Stdio {
command: "echo".to_string(),
args: vec![],
env: None,
env_vars: Vec::new(),
cwd: None,
},
enabled: true,
required: false,
disabled_reason: None,
startup_timeout_sec: None,
tool_timeout_sec: None,
enabled_tools: None,
disabled_tools: None,
scopes: None,
oauth_resource: None,
tools: HashMap::new(),
}
);
}
#[test]
fn deserialize_skill_config_with_name_selector() {
let cfg: SkillConfig = toml::from_str(