* @brief Handle tools/call request */
| 303 | * @brief Handle tools/call request |
| 304 | */ |
| 305 | API::MCP::MCPResponse API::MCPHandler::handleToolsCall(const MCP::MCPRequest& request, |
| 306 | const QString& sessionId) |
| 307 | { |
| 308 | Q_UNUSED(sessionId); |
| 309 | |
| 310 | const auto name = request.params.value(QStringLiteral("name")).toString(); |
| 311 | const auto arguments = request.params.value(QStringLiteral("arguments")).toObject(); |
| 312 | |
| 313 | if (name.isEmpty()) { |
| 314 | return MCP::MCPResponse::makeError( |
| 315 | request.id, MCP::ErrorCode::InvalidParams, QStringLiteral("Missing tool name")); |
| 316 | } |
| 317 | |
| 318 | auto& registry = CommandRegistry::instance(); |
| 319 | if (!registry.hasCommand(name)) { |
| 320 | return MCP::MCPResponse::makeError( |
| 321 | request.id, MCP::ErrorCode::InvalidParams, QStringLiteral("Unknown tool: %1").arg(name)); |
| 322 | } |
| 323 | |
| 324 | if (!Server::instance().authorizeRemoteCommand(name)) { |
| 325 | return MCP::MCPResponse::makeError( |
| 326 | request.id, MCP::ErrorCode::InternalError, QStringLiteral("Device write denied by user")); |
| 327 | } |
| 328 | |
| 329 | const auto response = registry.execute(name, QString(), arguments); |
| 330 | |
| 331 | QJsonObject contentObj; |
| 332 | contentObj[QStringLiteral("type")] = QStringLiteral("text"); |
| 333 | contentObj[QStringLiteral("text")] = |
| 334 | QString::fromUtf8(QJsonDocument(response.result).toJson(QJsonDocument::Compact)); |
| 335 | |
| 336 | QJsonObject result; |
| 337 | result[QStringLiteral("content")] = QJsonArray{contentObj}; |
| 338 | |
| 339 | if (!response.success) { |
| 340 | QJsonObject errorData; |
| 341 | errorData[QStringLiteral("tool")] = name; |
| 342 | errorData[QStringLiteral("providedArguments")] = arguments; |
| 343 | errorData[QStringLiteral("commandResult")] = response.result; |
| 344 | |
| 345 | if (response.errorMessage.contains(QStringLiteral("must be")) && arguments.size() > 0) { |
| 346 | const auto argKey = arguments.keys().first(); |
| 347 | const auto argValue = arguments.value(argKey); |
| 348 | errorData[QStringLiteral("parameter")] = argKey; |
| 349 | errorData[QStringLiteral("receivedValue")] = argValue; |
| 350 | errorData[QStringLiteral("receivedType")] = |
| 351 | QString::fromUtf8(argValue.toVariant().typeName()); |
| 352 | |
| 353 | if (argValue.isString()) { |
| 354 | errorData[QStringLiteral("suggestion")] = |
| 355 | QStringLiteral( |
| 356 | "Parameter '%1' appears to be a string but may need to be a number. Try passing %2 as integer.") |
| 357 | .arg(argKey, argValue.toString()); |
| 358 | } |
| 359 | } |
| 360 | |
| 361 | return MCP::MCPResponse::makeError( |
| 362 | request.id, MCP::ErrorCode::InternalError, response.errorMessage, QJsonValue(errorData)); |
nothing calls this directly
no test coverage detected