Enforce Agent Plugin runtime boundaries (#37027)

## What changed

- Track Agent Plugin manifests through plugin, skill, and MCP loading so their capabilities use format-specific behavior without changing legacy plugins.
- Discover only direct-child skills, exclude app and hook capabilities, isolate MCP data, and reject MCP configuration files that are non-regular or resolve outside the plugin root.
- Bound model-visible skill instructions, plugin instructions, MCP descriptions, schemas, individual tools, and the aggregate Agent Plugin MCP tool set.
- Stop MCP and OAuth redirects when Agent Plugins send configured or authorization headers, while retaining existing redirect behavior for legacy MCP servers.

## Testing

- Add coverage for capability filtering, skill discovery, isolated MCP data and reserved-path expansion, unsafe MCP configuration files, context limits, and redirect handling.

GitOrigin-RevId: c9af66b051269f3226628ca280a58d32c808c38f
This commit is contained in:
jacobzhou-oai
2026-08-05 04:48:41 +00:00
committed by copyberry
parent f21dc46388
commit 56b82e676c
63 changed files with 1830 additions and 106 deletions

View File

@@ -52,6 +52,7 @@ pub fn app_connector_ids_from_declarations<'a>(
pub struct PluginCapabilitySummary {
pub config_name: String,
pub display_name: String,
pub plugin_namespace: Option<String>,
pub description: Option<String>,
pub has_skills: bool,
pub mcp_server_names: Vec<String>,

View File

@@ -25,6 +25,7 @@ pub struct LoadedPlugin<M> {
pub root: AbsolutePathBuf,
pub enabled: bool,
pub skill_roots: Vec<AbsolutePathBuf>,
pub skill_discovery_mode: SkillDiscoveryMode,
pub disabled_skill_paths: HashSet<AbsolutePathBuf>,
pub has_enabled_skills: bool,
pub mcp_servers: HashMap<String, M>,
@@ -42,6 +43,10 @@ impl<M> LoadedPlugin<M> {
pub fn display_name(&self) -> &str {
self.manifest_name.as_deref().unwrap_or(&self.config_name)
}
pub fn is_agent_plugin(&self) -> bool {
self.skill_discovery_mode == SkillDiscoveryMode::DirectChildren
}
}
fn plugin_capability_summary_from_loaded<M>(
@@ -57,6 +62,7 @@ fn plugin_capability_summary_from_loaded<M>(
let summary = PluginCapabilitySummary {
config_name: plugin.config_name.clone(),
display_name: plugin.display_name().to_string(),
plugin_namespace: plugin.plugin_namespace.clone(),
description: prompt_safe_plugin_description(plugin.manifest_description.as_deref()),
has_skills: plugin.has_enabled_skills,
mcp_server_names,
@@ -143,7 +149,7 @@ impl<M: Clone> PluginLoadOutcome<M> {
},
plugin_namespace: plugin_namespace.clone(),
plugin_root: plugin.root.clone(),
discovery_mode: SkillDiscoveryMode::Recursive,
discovery_mode: plugin.skill_discovery_mode,
});
}
}
@@ -241,6 +247,7 @@ mod tests {
root: test_path(config_name),
enabled: true,
skill_roots,
skill_discovery_mode: SkillDiscoveryMode::Recursive,
disabled_skill_paths: HashSet::new(),
has_enabled_skills: true,
mcp_servers: HashMap::new(),