fix(application,domain,backend): les serveurs MCP des plugins assignés atteignent la session de l'agent — #302 (cause: MutateAgentPluginTool persistait bien PluginToolRef dans ProjectPluginSettings mais le launcher ne consommait jamais assignments.tools, les configs de session ne contenaient que le serveur MCP natif idea, donc tool_search restait aveugle aux tools plugin comme unity_detect_project; fix: ProjectPluginResolver::assigned_mcp_servers projette les affectations de l'agent en specs stdio uniquement si plugin activé pour le projet/runtime-actif/installé et serveur autoStart, avec substitution ${pluginRoot}/${appDataDir}, dédup par (pluginId,serverId), et nom client stable idea_plugin__<enc>__<enc> via PluginMcpServerSpec::client_name qui encode chaque octet non alphanumérique pour éviter collisions TOML/namespace; matérialisation au lancement/restart dans .mcp.json + enabledMcpjsonServers (Claude), mcp_servers de .codex/config.toml (Codex), bloc mcp de opencode.json (OpenCode local/cloud), avec réconciliation préservant le wiring idea réel lors d'un restart interne sans McpRuntime et retirant les entrées plugin obsolètes; racines cwd/commande des serveurs assignés ajoutées en lecture au plan Landlock quand un plan existe; aucun changement de .ideai/mcp-tool-permissions.json ni pollution du catalogue natif idea_*; gap documenté: OpenAiCompatibleSession/tools_for_context ne rend pas les tools plugin appelables en direct (nécessite client JSON-RPC dédié), à traiter séparément; QA verte reconfirmée par Git: rustup run stable cargo fmt --all -- --check, git diff --check, cargo test -p application --lib 180/180 dont assigned_mcp_servers 2/2, cargo test -p application --test agent_lifecycle 111/111, cargo test -p domain plugin --lib 7/7 dont plugin_mcp_client_name_is_stable_and_collision_free_for_punctuation, cargo check -p backend OK, cargo check -p app-tauri OK; fichiers tickets/296/*, tickets/299-302/*, counter/index, attachments/ et scripts/ hors périmètre; aucun push)
This commit is contained in:
@ -796,6 +796,36 @@ pub struct PluginMcpServerSpec {
|
||||
pub transport: String,
|
||||
}
|
||||
|
||||
impl PluginMcpServerSpec {
|
||||
/// Stable, collision-free MCP client name for this plugin server.
|
||||
///
|
||||
/// Plugin/server ids may contain punctuation that is awkward in TOML table
|
||||
/// paths and becomes part of the tool namespace in MCP clients. Encode every
|
||||
/// non-alphanumeric byte instead of merely replacing it, so distinct ids can
|
||||
/// never collapse onto the same session server name.
|
||||
#[must_use]
|
||||
pub fn client_name(&self) -> String {
|
||||
fn component(raw: &str) -> String {
|
||||
let mut out = String::new();
|
||||
for byte in raw.bytes() {
|
||||
if byte.is_ascii_alphanumeric() {
|
||||
out.push(char::from(byte).to_ascii_lowercase());
|
||||
} else {
|
||||
out.push('_');
|
||||
out.push_str(&format!("{byte:02x}"));
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
format!(
|
||||
"idea_plugin__{}__{}",
|
||||
component(self.plugin_id.as_str()),
|
||||
component(self.server_id.as_str())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// MCP server status.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
@ -862,6 +892,32 @@ mod tests {
|
||||
assert!(PluginLifecycleState::Enabled.is_runtime_active());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_mcp_client_name_is_stable_and_collision_free_for_punctuation() {
|
||||
fn spec(plugin: &str) -> PluginMcpServerSpec {
|
||||
PluginMcpServerSpec {
|
||||
plugin_id: PluginId::new(plugin).unwrap(),
|
||||
server_id: PluginMcpServerId::new("unity-editor").unwrap(),
|
||||
identity: String::new(),
|
||||
display_name: String::new(),
|
||||
command: String::new(),
|
||||
args: Vec::new(),
|
||||
env: Vec::new(),
|
||||
cwd: String::new(),
|
||||
transport: "stdio".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
spec("com.idea.unity").client_name(),
|
||||
"idea_plugin__com_2eidea_2eunity__unity_2deditor"
|
||||
);
|
||||
assert_ne!(
|
||||
spec("com.idea-unity").client_name(),
|
||||
spec("com.idea.unity").client_name()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plugin_capabilities_serialize_public_manifest_names() {
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user