refactor(mcp): extract AddServerRequestBuilder and McpImportSummary

Extract request building and import summary formatting helpers.
Wire into McpServersViewModel with unit test coverage.
This commit is contained in:
Hy4ri committed 2026-09-11 18:00:47 +03:00
1 parent 9eaf9663f3
commit 4a93772b93
5 files changed
+195 -39

No files matched your search

@@ -0,0 +1,56 @@
package com.m57.hermescontrol.ui.mcp
import com.m57.hermescontrol.data.model.AddMcpServerRequest
object AddServerRequestBuilder {
/**
* Constructs a validated AddMcpServerRequest from the add-server form parameters.
*/
fun build(
name: String,
mode: AddServerMode,
url: String,
command: String,
args: String,
auth: String,
bearerToken: String,
): AddMcpServerRequest {
val isHttp = mode == AddServerMode.HTTP
val isStdio = mode == AddServerMode.Stdio
val resolvedUrl = if (isHttp) url.trim().ifBlank { null } else null
val resolvedCommand = if (isStdio) command.trim().ifBlank { null } else null
val resolvedArgs =
if (isStdio && args.isNotBlank()) {
args.trim().split("\\s+".toRegex()).filter { it.isNotEmpty() }
} else {
null
}
val resolvedAuth = if (isHttp && auth != "none") auth else null
val resolvedBearerToken =
if (isHttp && auth == "header") bearerToken.trim().ifBlank { null } else null
return AddMcpServerRequest(
name = name.trim(),
url = resolvedUrl,
command = resolvedCommand,
args = resolvedArgs,
auth = resolvedAuth,
bearerToken = resolvedBearerToken,
)
}
/**
* Overload reading form parameters directly from McpServersUiState.
*/
fun build(state: McpServersUiState): AddMcpServerRequest =
build(
name = state.addServerName,
mode = state.addMode,
url = state.addServerUrl,
command = state.addServerCommand,
args = state.addServerArgs,
auth = state.addServerAuth,
bearerToken = state.addServerBearerToken,
)
}
@@ -0,0 +1,18 @@
package com.m57.hermescontrol.ui.mcp
object McpImportSummary {
/**
* Formats the human-readable summary message reporting the result of a batch MCP JSON import.
*/
fun formatSummary(
successCount: Int,
errors: List<String>,
): String {
val errSummary = errors.joinToString("; ")
return when {
errors.isEmpty() -> "Successfully imported $successCount server(s)"
successCount > 0 -> "Imported $successCount server(s), ${errors.size} failed: $errSummary"
else -> "Failed to import: $errSummary"
}
}
}
@@ -297,13 +297,7 @@ class McpServersViewModel :
}
_uiState.update { state ->
val errSummary = errors.joinToString("; ")
val msg =
when {
errors.isEmpty() -> "Successfully imported $successCount server(s)"
successCount > 0 -> "Imported $successCount server(s), ${errors.size} failed: $errSummary"
else -> "Failed to import: $errSummary"
}
val msg = McpImportSummary.formatSummary(successCount, errors)
state.copy(
isImportingJson = false,
showImportDialog = false,
@@ -357,38 +351,7 @@ class McpServersViewModel :
}
_uiState.update { it.copy(addingServer = true) }
viewModelScope.launch {
val request =
AddMcpServerRequest(
name = state.addServerName.trim(),
url = if (state.addMode == AddServerMode.HTTP) state.addServerUrl.trim().ifBlank { null } else null,
command =
if (state.addMode == AddServerMode.Stdio) {
state.addServerCommand.trim().ifBlank { null }
} else {
null
},
args =
if (state.addMode == AddServerMode.Stdio && state.addServerArgs.isNotBlank()) {
state.addServerArgs
.trim()
.split("\\s+".toRegex())
.filter { it.isNotEmpty() }
} else {
null
},
auth =
if (state.addMode == AddServerMode.HTTP && state.addServerAuth != "none") {
state.addServerAuth
} else {
null
},
bearerToken =
if (state.addMode == AddServerMode.HTTP && state.addServerAuth == "header") {
state.addServerBearerToken.trim().ifBlank { null }
} else {
null
},
)
val request = AddServerRequestBuilder.build(state)
val result =
withContext(Dispatchers.IO) {
safeApiCall { ApiClient.hermesApi.addMcpServer(request) }