205 lines
5.2 KiB
C
205 lines
5.2 KiB
C
|
/**
|
|||
|
* @file mcp_stdio_client.h
|
|||
|
* @brief MCP Stdio Client implementation
|
|||
|
*
|
|||
|
* This file implements the client-side functionality for the Model Context Protocol
|
|||
|
* using standard input/output (stdio) as the transport mechanism.
|
|||
|
* Follows the 2024-11-05 protocol specification.
|
|||
|
*/
|
|||
|
|
|||
|
#ifndef MCP_STDIO_CLIENT_H
|
|||
|
#define MCP_STDIO_CLIENT_H
|
|||
|
|
|||
|
#include "mcp_message.h"
|
|||
|
#include "mcp_tool.h"
|
|||
|
#include "mcp_logger.h"
|
|||
|
|
|||
|
#include <string>
|
|||
|
#include <map>
|
|||
|
#include <vector>
|
|||
|
#include <memory>
|
|||
|
#include <mutex>
|
|||
|
#include <functional>
|
|||
|
#include <atomic>
|
|||
|
#include <condition_variable>
|
|||
|
#include <future>
|
|||
|
#include <thread>
|
|||
|
|
|||
|
namespace mcp {
|
|||
|
|
|||
|
/**
|
|||
|
* @class stdio_client
|
|||
|
* @brief Client for connecting to MCP servers using stdio transport
|
|||
|
*
|
|||
|
* The stdio_client class provides functionality to connect to MCP servers
|
|||
|
* by spawning a separate process and communicating via standard input/output.
|
|||
|
*/
|
|||
|
class stdio_client {
|
|||
|
public:
|
|||
|
/**
|
|||
|
* @brief Constructor
|
|||
|
* @param command The command to execute to start the server
|
|||
|
* @param capabilities The capabilities of the client
|
|||
|
*/
|
|||
|
stdio_client(const std::string& command, const json& capabilities = json::object());
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Destructor
|
|||
|
*/
|
|||
|
~stdio_client();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Initialize the connection with the server
|
|||
|
* @param client_name The name of the client
|
|||
|
* @param client_version The version of the client
|
|||
|
* @return True if initialization was successful
|
|||
|
*/
|
|||
|
bool initialize(const std::string& client_name, const std::string& client_version);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Ping request
|
|||
|
* @return True if the server is alive
|
|||
|
*/
|
|||
|
bool ping();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Set client capabilities
|
|||
|
* @param capabilities The capabilities of the client
|
|||
|
*/
|
|||
|
void set_capabilities(const json& capabilities);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Send a request and wait for a response
|
|||
|
* @param method The method to call
|
|||
|
* @param params The parameters to pass
|
|||
|
* @return The response
|
|||
|
* @throws mcp_exception on error
|
|||
|
*/
|
|||
|
response send_request(const std::string& method, const json& params = json::object());
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Send a notification (no response expected)
|
|||
|
* @param method The method to call
|
|||
|
* @param params The parameters to pass
|
|||
|
* @throws mcp_exception on error
|
|||
|
*/
|
|||
|
void send_notification(const std::string& method, const json& params = json::object());
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Get server capabilities
|
|||
|
* @return The server capabilities
|
|||
|
* @throws mcp_exception on error
|
|||
|
*/
|
|||
|
json get_server_capabilities();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Call a tool
|
|||
|
* @param tool_name The name of the tool to call
|
|||
|
* @param arguments The arguments to pass to the tool
|
|||
|
* @return The result of the tool call
|
|||
|
* @throws mcp_exception on error
|
|||
|
*/
|
|||
|
json call_tool(const std::string& tool_name, const json& arguments = json::object());
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Get available tools
|
|||
|
* @return List of available tools
|
|||
|
* @throws mcp_exception on error
|
|||
|
*/
|
|||
|
std::vector<tool> get_tools();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Get client capabilities
|
|||
|
* @return The client capabilities
|
|||
|
*/
|
|||
|
json get_capabilities();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief List available resources
|
|||
|
* @param cursor Optional cursor for pagination
|
|||
|
* @return List of resources
|
|||
|
*/
|
|||
|
json list_resources(const std::string& cursor = "");
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Read a resource
|
|||
|
* @param resource_uri The URI of the resource
|
|||
|
* @return The resource content
|
|||
|
*/
|
|||
|
json read_resource(const std::string& resource_uri);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Subscribe to resource changes
|
|||
|
* @param resource_uri The URI of the resource
|
|||
|
* @return Subscription result
|
|||
|
*/
|
|||
|
json subscribe_to_resource(const std::string& resource_uri);
|
|||
|
|
|||
|
/**
|
|||
|
* @brief List resource templates
|
|||
|
* @return List of resource templates
|
|||
|
*/
|
|||
|
json list_resource_templates();
|
|||
|
|
|||
|
/**
|
|||
|
* @brief Check if the server process is running
|
|||
|
* @return True if the server process is running
|
|||
|
*/
|
|||
|
bool is_running() const;
|
|||
|
|
|||
|
private:
|
|||
|
// 启动服务器进程
|
|||
|
bool start_server_process();
|
|||
|
|
|||
|
// 停止服务器进程
|
|||
|
void stop_server_process();
|
|||
|
|
|||
|
// 读取线程函数
|
|||
|
void read_thread_func();
|
|||
|
|
|||
|
// 发送JSON-RPC请求
|
|||
|
json send_jsonrpc(const request& req);
|
|||
|
|
|||
|
// 服务器命令
|
|||
|
std::string command_;
|
|||
|
|
|||
|
// 进程ID
|
|||
|
int process_id_ = -1;
|
|||
|
|
|||
|
// 标准输入管道
|
|||
|
int stdin_pipe_[2] = {-1, -1};
|
|||
|
|
|||
|
// 标准输出管道
|
|||
|
int stdout_pipe_[2] = {-1, -1};
|
|||
|
|
|||
|
// 读取线程
|
|||
|
std::unique_ptr<std::thread> read_thread_;
|
|||
|
|
|||
|
// 运行状态
|
|||
|
std::atomic<bool> running_{false};
|
|||
|
|
|||
|
// 客户端能力
|
|||
|
json capabilities_;
|
|||
|
|
|||
|
// 服务器能力
|
|||
|
json server_capabilities_;
|
|||
|
|
|||
|
// 互斥锁
|
|||
|
mutable std::mutex mutex_;
|
|||
|
|
|||
|
// 请求ID到Promise的映射,用于异步等待响应
|
|||
|
std::map<json, std::promise<json>> pending_requests_;
|
|||
|
|
|||
|
// 响应处理互斥锁
|
|||
|
std::mutex response_mutex_;
|
|||
|
|
|||
|
// 初始化状态
|
|||
|
std::atomic<bool> initialized_{false};
|
|||
|
|
|||
|
// 初始化条件变量
|
|||
|
std::condition_variable init_cv_;
|
|||
|
};
|
|||
|
|
|||
|
} // namespace mcp
|
|||
|
|
|||
|
#endif // MCP_STDIO_CLIENT_H
|