// Minimal CLI runner that registers Kompanion MCP tools and dispatches requests. #include #include #include #include #include #include #include #ifdef HAVE_KCONFIG #include #include #else #include #include #include #endif #include "mcp/KomMcpServer.hpp" #include "mcp/RegisterTools.hpp" namespace { std::string read_all(std::istream& in) { std::ostringstream oss; oss << in.rdbuf(); return oss.str(); } std::string load_request(int argc, char** argv) { if (argc < 3) { return read_all(std::cin); } std::string arg = argv[2]; if (arg == "-") { return read_all(std::cin); } std::filesystem::path p{arg}; if (std::filesystem::exists(p)) { std::ifstream file(p); if (!file) throw std::runtime_error("unable to open request file: " + p.string()); return read_all(file); } return arg; } void print_usage(const char* exe, KomMcpServer& server) { std::cerr << "Usage: " << exe << " [request-json|-|path]\n"; std::cerr << "Available tools:\n"; for (const auto& name : server.listTools()) { std::cerr << " - " << name << "\n"; } } } // namespace #ifdef HAVE_KCONFIG std::optional read_dsn_from_config() { auto config = KSharedConfig::openConfig(QStringLiteral("kompanionrc")); if (!config) return std::nullopt; KConfigGroup dbGroup(config, QStringLiteral("Database")); const QString dsn = dbGroup.readEntry(QStringLiteral("PgDsn"), QString()); if (dsn.isEmpty()) { return std::nullopt; } return dsn.toStdString(); } #else QString configFilePath() { QString base = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation); if (base.isEmpty()) { base = QDir::homePath(); } return QDir(base).filePath(QStringLiteral("kompanionrc")); } std::optional read_dsn_from_config() { QSettings settings(configFilePath(), QSettings::IniFormat); const QString dsn = settings.value(QStringLiteral("Database/PgDsn")).toString(); if (dsn.isEmpty()) { return std::nullopt; } return dsn.toStdString(); } #endif int main(int argc, char** argv) { KomMcpServer server; register_default_tools(server); const char* envDsn = std::getenv("PG_DSN"); std::optional effectiveDsn; if (envDsn && *envDsn) { effectiveDsn = std::string(envDsn); } else { effectiveDsn = read_dsn_from_config(); if (effectiveDsn) { ::setenv("PG_DSN", effectiveDsn->c_str(), 1); } } if (!effectiveDsn) { std::cerr << "[kom_mcp] PG_DSN not set; fallback DAL will be used if available (configure Database/PgDsn via KConfig).\n"; } if (argc < 2) { print_usage(argv[0], server); return 1; } std::string tool = argv[1]; if (tool == "--list") { for (const auto& name : server.listTools()) { std::cout << name << "\n"; } return 0; } if (!server.hasTool(tool)) { std::cerr << "Unknown tool: " << tool << "\n"; print_usage(argv[0], server); return 1; } try { std::string request = load_request(argc, argv); std::string response = server.dispatch(tool, request); std::cout << response << std::endl; return 0; } catch (const std::exception& ex) { std::cerr << "Error: " << ex.what() << "\n"; return 1; } }