// SPDX-License-Identifier: AGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® module Crafter.Review:Mcp_impl; import :Mcp; import :Json; import :Text; import :Tools; import std; namespace fs = std::filesystem; namespace Crafter::Review::Mcp { std::vector DefaultArgs() { return {"-y", std::format("@playwright/mcp@{}", PlaywrightMcpVersion), "--headless", "--isolated", "--browser", "chromium"}; } Json PlaywrightConfig(const Json& functional, const std::string& outputDir) { const Json& mcp = Dyn::Or(Dyn::Get(Dyn::Or(functional, Dyn::EmptyDict()), "mcp"), Dyn::EmptyDict()); Json args = Json::array(); const Json& configured = Dyn::Get(mcp, "args"); if (!configured.is_null()) { for (const Json& arg : configured) args.push_back(arg); } else { for (const std::string& arg : DefaultArgs()) args.push_back(arg); } if (!Dyn::In(Json("--output-dir"), args)) { args.push_back("--output-dir"); args.push_back(outputDir); } const Json& command = Dyn::Get(mcp, "command"); return {{"mcpServers", {{std::string(Tools::McpServer), {{"command", Dyn::Truthy(command) ? command : Json("npx")}, {"args", std::move(args)}}}}}}; } std::string ConfigJson(const Json& config) { return config.dump(-1, ' ', true, Json::error_handler_t::replace); } fs::path OutputDir(const fs::path& scratch, std::string_view label) { const fs::path dir = scratch / "playwright" / Dyn::Replace(Dyn::Replace(label, "/", "_"), " ", "_"); fs::create_directories(dir); return dir; } }