模型上下文协议 (MCP)是一个开放协议,为 AI 模型和代理与各种资源、工具和服务交互提供了标准化的方式。
cpp-mcp 该框架实现了 MCP 协议的核心功能,并符合 2024-11-05 基本协议规范。
- JSON-RPC 2.0 通信:基于 JSON-RPC 2.0 标准的请求/响应通信
- 资源抽象:文件、API 等资源的标准接口。
- 工具注册:使用结构化参数注册和调用工具
- 可扩展架构:易于扩展新的资源类型和工具
- 多传输支持:支持 HTTP 和标准输入/输出 (stdio) 通信方法
1.使用 CMake 构建的示例:
cmake -B build
cmake --build build --config Release
2.通过测试构建:
git submodule update --init --recursive # Get GoogleTestcmake -B build -DMCP_BUILD_TESTS=ON
cmake --build build --config Release
3.使用 SSL 支持进行构建:
git submodule update --init --recursive # Get GoogleTestcmake -B build -DMCP_SSL=ON
cmake --build build --config Release
三、构成
MCP C++库包括以下主要组件:
定义 MCP 客户端的抽象接口,所有具体的客户端实现都从该接口继承。
使用 HTTP 和服务器发送事件 (SSE) 与 MCP 服务器通信的客户端实现。
客户端实现使用标准输入/输出与 MCP 服务器通信,能够启动子进程并与其通信。
处理 JSON-RPC 消息的序列化和反序列化。
管理和调用 MCP 工具。
管理 MCP 资源。
实现 MCP 服务器功能。
使用自定义工具的 MCP 服务器实现示例:
- 时间工具:获取当前时间
- 计算器工具:执行数学运算
- 回显工具:回显输入并可选择转换(转换为大写、反转)
- 问候工具:返回
Hello,+输入名称+!,默认为Hello, World!
MCP 客户端连接到服务器的示例:
- 获取服务器信息
- 列出可用的工具
- 调用带参数的工具
- 访问资源
演示如何使用 stdio 客户端与本地服务器通信:
- 启动本地服务器进程
- 访问文件系统资源
- 调用服务器工具
| 选项 | 描述 |
|---|---|
--base-url |
LLM 基本网址(例如https://openrouter.ai) |
--endpoint |
LLM 端点(默认为/v1/chat/completions/) |
--api-key |
LLM API 密钥 |
--model |
型号名称(例如gpt-3.5-turbo) |
--system-prompt |
系统提示 |
--max-tokens |
生成的最大令牌数(默认为 2048) |
--temperature |
温度(默认为 0.0) |
--max-steps |
无需用户输入调用工具的最大步骤(默认为 3) |
使用示例:
./build/examples/agent_example --base-url <base_url> --endpoint <endpoint> --api-key <api_key> --model <model_name>
注意-DMCP_SSL=ON:连接到 https 基本 URL 时请记住进行编译。
// Create and configure the server mcp::server server("localhost", 8080); // Host and port server.set_server_info("MCP Example Server", "0.1.0"); // Name and version// Register tools mcp::json hello_handler(const mcp::json& params, const std::string /* session_id */) {std::string name = params.contains("name") ? params["name"].get<std::string>() : "World";// Server will catch exceptions and return error contents// For example, you can use `throw mcp::mcp_exception(mcp::error_code::invalid_params, "Invalid name");` to report an error// Content should be a JSON array, see: https://modelcontextprotocol.io/specification/2024-11-05/server/tools#tool-resultreturn {{{"type", "text"},{"text", "Hello, " + name + "!"}}}; }mcp::tool hello_tool = mcp::tool_builder("hello").with_description("Say hello").with_string_param("name", "Name to say hello to", "World").build();server.register_tool(hello_tool, hello_handler);// Register resources auto file_resource = std::make_shared<mcp::file_resource>("<file_path>"); server.register_resource("file://<file_path>", file_resource);// Start the server server.start(true); // Blocking mode
// Connect to the server mcp::sse_client client("localhost", 8080);// Initialize the connection client.initialize("My Client", "1.0.0");// Call a tool mcp::json params = {{"name", "Client"} };mcp::json result = client.call_tool("hello", params);
SSE 客户端使用 HTTP 和服务器发送事件 (SSE) 与 MCP 服务器通信。这是一种基于 Web 标准的通信方式,适用于与支持 HTTP/SSE 的服务器通信。
#include "mcp_sse_client.h"// Create a client, specifying the server address and port mcp::sse_client client("localhost", 8080); // Or use a base URL // mcp::sse_client client("http://localhost:8080");// Set an authentication token (if needed) client.set_auth_token("your_auth_token");// Set custom request headers (if needed) client.set_header("X-Custom-Header", "value");// Initialize the client if (!client.initialize("My Client", "1.0.0")) {// Handle initialization failure }// Call a tool json result = client.call_tool("tool_name", {{"param1", "value1"},{"param2", 42} });
Stdio 客户端可以与任何支持 stdio 传输的 MCP 服务器进行通信,例如:
- @modelcontextprotocol/server-everything - 示例服务器
- @modelcontextprotocol/server-filesystem - 文件系统服务器
- 其他支持 stdio 传输的MCP 服务器
#include "mcp_stdio_client.h"// Create a client, specifying the server command mcp::stdio_client client("npx -y @modelcontextprotocol/server-everything"); // mcp::stdio_client client("npx -y @modelcontextprotocol/server-filesystem /path/to/directory");// Initialize the client if (!client.initialize("My Client", "1.0.0")) {// Handle initialization failure }// Access resources json resources = client.list_resources(); json content = client.read_resource("resource://uri");// Call a tool json result = client.call_tool("tool_name", {{"param1", "value1"},{"param2", "value2"} });
