clean API

main
hkr04 2025-03-13 23:57:46 +08:00
parent 9abbf6e738
commit 77a97cca30
7 changed files with 63 additions and 19 deletions

View File

@ -21,14 +21,21 @@ int main(int argc, char** argv) {
// 检查命令行参数 // 检查命令行参数
if (argc < 2) { if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <server_command>" << std::endl; std::cerr << "Usage: " << argv[0] << " <server_command>" << std::endl;
std::cerr << "Example: " << argv[0] << " \"npx -y @modelcontextprotocol/server-filesystem /Users/username/Desktop\"" << std::endl; std::cerr << "Example: " << argv[0] << " \"npx -y @modelcontextprotocol/server-everything\"" << std::endl;
return 1; return 1;
} }
std::string command = argv[1]; std::string command = argv[1];
// 创建客户端 // 设置环境变量
mcp::stdio_client client(command); mcp::json env_vars = {
{"MCP_DEBUG", "1"},
{"MCP_LOG_LEVEL", "debug"},
{"CUSTOM_VAR", "custom_value"}
};
// 创建客户端,直接在构造函数中传入环境变量
mcp::stdio_client client(command, env_vars);
// 初始化客户端 // 初始化客户端
if (!client.initialize("MCP Stdio Client Example", "1.0.0")) { if (!client.initialize("MCP Stdio Client Example", "1.0.0")) {

View File

@ -41,15 +41,15 @@ public:
* @brief Constructor * @brief Constructor
* @param host The server host (e.g., "localhost", "example.com") * @param host The server host (e.g., "localhost", "example.com")
* @param port The server port * @param port The server port
* @param sse_endpoint The endpoint for server-sent events
*/ */
client(const std::string& host, int port = 8080, const json& capabilities = json::object(), const std::string& sse_endpoint = "/sse"); client(const std::string& host, int port = 8080, const std::string& sse_endpoint = "/sse");
/** /**
* @brief Constructor * @brief Constructor
* @param base_url The base URL of the server (e.g., "localhost:8080") * @param base_url The base URL of the server (e.g., "localhost:8080")
* @param capabilities The capabilities of the client
*/ */
client(const std::string& base_url, const json& capabilities = json::object(), const std::string& sse_endpoint = "/sse"); client(const std::string& base_url, const std::string& sse_endpoint = "/sse");
/** /**
* @brief Destructor * @brief Destructor

View File

@ -171,10 +171,17 @@ public:
* @brief Constructor * @brief Constructor
* @param host The host to bind to (e.g., "localhost", "0.0.0.0") * @param host The host to bind to (e.g., "localhost", "0.0.0.0")
* @param port The port to listen on * @param port The port to listen on
* @param name The name of the server
* @param version The version of the server
* @param sse_endpoint The endpoint for server-sent events
* @param msg_endpoint The endpoint for messages
*/ */
server(const std::string& host = "localhost", int port = 8080, server(const std::string& host = "localhost",
int port = 8080,
const std::string& name = "MCP Server",
const std::string& version = "0.0.1",
const std::string& sse_endpoint = "/sse", const std::string& sse_endpoint = "/sse",
const std::string& msg_endpoint_prefix = "/message"); const std::string& msg_endpoint = "/message");
/** /**
* @brief Destructor * @brief Destructor

View File

@ -39,15 +39,25 @@ public:
/** /**
* @brief Constructor * @brief Constructor
* @param command The command to execute to start the server * @param command The command to execute to start the server
* @param env_vars Optional environment variables to set for the server process
* @param capabilities The capabilities of the client * @param capabilities The capabilities of the client
*/ */
stdio_client(const std::string& command, const json& capabilities = json::object()); stdio_client(const std::string& command,
const json& env_vars = json::object(),
const json& capabilities = json::object());
/** /**
* @brief Destructor * @brief Destructor
*/ */
~stdio_client(); ~stdio_client();
/**
* @brief Set environment variables for the server process
* @param env_vars JSON object containing environment variables (key: variable name, value: variable value)
* @note This must be called before initialize()
*/
void set_environment_variables(const json& env_vars);
/** /**
* @brief Initialize the connection with the server * @brief Initialize the connection with the server
* @param client_name The name of the client * @param client_name The name of the client
@ -198,6 +208,9 @@ private:
// 初始化条件变量 // 初始化条件变量
std::condition_variable init_cv_; std::condition_variable init_cv_;
// 环境变量
json env_vars_;
}; };
} // namespace mcp } // namespace mcp

View File

@ -11,14 +11,14 @@
namespace mcp { namespace mcp {
client::client(const std::string& host, int port, const json& capabilities, const std::string& sse_endpoint) client::client(const std::string& host, int port, const std::string& sse_endpoint)
: host_(host), port_(port), capabilities_(capabilities), sse_endpoint_(sse_endpoint) { : host_(host), port_(port), sse_endpoint_(sse_endpoint) {
init_client(host, port); init_client(host, port);
} }
client::client(const std::string& base_url, const json& capabilities, const std::string& sse_endpoint) client::client(const std::string& base_url, const std::string& sse_endpoint)
: base_url_(base_url), capabilities_(capabilities), sse_endpoint_(sse_endpoint) { : base_url_(base_url), sse_endpoint_(sse_endpoint) {
init_client(base_url); init_client(base_url);
} }
@ -286,7 +286,7 @@ void client::open_sse_connection() {
bool should_continue = sse_running_.load(); bool should_continue = sse_running_.load();
if (!should_continue) { if (!should_continue) {
LOG_INFO("SSE thread: sse_running_ is false, closing connection"); LOG_INFO("SSE thread: Received close signal, closing connection");
} }
return should_continue; return should_continue;
}); });

View File

@ -10,9 +10,8 @@
namespace mcp { namespace mcp {
server::server(const std::string& host, int port, const std::string& sse_endpoint, const std::string& msg_endpoint_prefix) server::server(const std::string& host, int port, const std::string& name, const std::string& version, const std::string& sse_endpoint, const std::string& msg_endpoint)
: host_(host), port_(port), sse_endpoint_(sse_endpoint), msg_endpoint_(msg_endpoint_prefix), name_("MCP Server"), version_(MCP_VERSION) { : host_(host), port_(port), name_(name), version_(version), sse_endpoint_(sse_endpoint), msg_endpoint_(msg_endpoint) {
http_server_ = std::make_unique<httplib::Server>(); http_server_ = std::make_unique<httplib::Server>();
} }

View File

@ -21,8 +21,8 @@
namespace mcp { namespace mcp {
stdio_client::stdio_client(const std::string& command, const json& capabilities) stdio_client::stdio_client(const std::string& command, const json& env_vars, const json& capabilities)
: command_(command), capabilities_(capabilities) { : command_(command), capabilities_(capabilities), env_vars_(env_vars) {
LOG_INFO("Creating MCP stdio client for command: ", command); LOG_INFO("Creating MCP stdio client for command: ", command);
} }
@ -183,6 +183,14 @@ bool stdio_client::is_running() const {
return running_; return running_;
} }
void stdio_client::set_environment_variables(const json& env_vars) {
if (running_) {
LOG_WARNING("Cannot set environment variables while server is running");
return;
}
env_vars_ = env_vars;
}
bool stdio_client::start_server_process() { bool stdio_client::start_server_process() {
if (running_) { if (running_) {
LOG_INFO("Server process already running"); LOG_INFO("Server process already running");
@ -219,6 +227,16 @@ bool stdio_client::start_server_process() {
if (process_id_ == 0) { if (process_id_ == 0) {
// 子进程 // 子进程
// 设置环境变量
if (!env_vars_.empty()) {
for (auto it = env_vars_.begin(); it != env_vars_.end(); ++it) {
std::string env_var = it.key() + "=" + it.value().get<std::string>();
if (putenv(const_cast<char*>(env_var.c_str())) != 0) {
LOG_ERROR("Failed to set environment variable: ", it.key());
}
}
}
// 关闭不需要的管道端 // 关闭不需要的管道端
close(stdin_pipe_[1]); // 关闭写入端 close(stdin_pipe_[1]); // 关闭写入端
close(stdout_pipe_[0]); // 关闭读取端 close(stdout_pipe_[0]); // 关闭读取端