feat: implement Hermes MCP sync module (Phase 4)

Add mcp/hermes.rs with bidirectional MCP format conversion:
- convert_to_hermes_format: strip type field, infer from command/url
- convert_from_hermes_format: infer type, strip Hermes-specific fields
- Merge-on-write: existing Hermes fields (tools, sampling, timeout,
  roots, enabled) preserved when user has customized them
- update_mcp_servers_yaml: closure-based read-modify-write under write
  lock to prevent TOCTOU races in concurrent sync operations
- 9 unit tests for format conversion and merge logic

Wire up all MCP service dispatch:
- Replace Hermes TODO stubs with real sync/remove calls
- Remove Hermes from sync_all_enabled skip list
- Enable deep link hermes MCP flag (apps.hermes = true)
- Add Hermes import to import_mcp_from_apps command
This commit is contained in:
Jason
2026-04-15 17:33:13 +08:00
parent 6d0e9f4c74
commit 576ff53a75
6 changed files with 602 additions and 16 deletions
+1 -4
View File
@@ -180,10 +180,7 @@ pub(crate) fn parse_mcp_apps(apps_str: &str) -> Result<McpApps, AppError> {
// OpenClaw doesn't support MCP, ignore silently
log::debug!("OpenClaw doesn't support MCP, ignoring in apps parameter");
}
"hermes" => {
// TODO: Hermes MCP sync not yet implemented, ignore silently for now
log::debug!("Hermes MCP sync not yet implemented, ignoring in apps parameter");
}
"hermes" => apps.hermes = true,
other => {
return Err(AppError::InvalidInput(format!(
"Invalid app in 'apps': {other}"