跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++AI算法

C++ 实现 MCP 客户端架构与核心机制解析

MCP 协议 C++ 客户端实现涵盖 STDIO 与 SSE 两种通信模式,通过 fork+pipe 或 libcurl+SSE 连接服务端。核心包含传输层、工具管理层及请求响应同步机制,利用条件变量与互斥锁保障线程安全。基于 JSON-RPC 2.0 统一消息格式,支持工具调用、资源读取及提示模板交互,为 AI 模型扩展外部能力提供标准化基础设施。

星落发布于 2026/4/11更新于 2026/10/25101 浏览

C++ 实现 MCP 客户端

Model Context Protocol(MCP) 是 Anthropic 推出的开放协议,旨在让 AI 模型能够标准化地调用外部工具、读取资源、执行 Prompt。本文结合 C++ 实现代码,讲解 MCP 客户端的架构设计与核心机制。


MCP 协议简介

MCP 是一套 AI 与外部工具之间的通信协议。它定义了三种核心能力:

  • Tools(工具):AI 可以调用的函数,例如查询天气、执行代码
  • Prompts(提示模板):预定义的提示词模板,支持参数化
  • Resources(资源):AI 可以读取的外部数据,例如文件、数据库条目

这套协议使用 JSON-RPC 2.0 作为消息格式,保证了跨语言、跨平台的互操作性。


整体架构设计

这份代码包含三个核心类,分工明确:

MCPServiceIntegrator ← 顶层集成器,统一对外暴露
└── MCPClient ← 传输层,负责与 MCP Server 通信
└── MCPToolManager ← 工具管理层,缓存工具列表、处理调用
传输层:两种通信模式

MCPClient 支持两种传输方式,由 MCPTransportType 枚举区分:

模式适用场景实现方式
STDIO本地进程fork() + pipe() + execv()
SSE远程 HTTP 服务libcurl + Server-Sent Events

STDIO 模式:本地进程通信

核心流程
父进程(MCPClient) 子进程(MCP Server)
│ │
│──── stdin_pipe ──────────>│ 写入 JSON-RPC 请求
│ │
│<─── stdout_pipe ─────────│ 读取 JSON-RPC 响应/通知
启动子进程

在 startMCPServer() 中,我们通过标准系统调用建立管道并启动子进程:

// 1. 创建两对管道
int stdin_pipe_fd[2]; // 父写 → 子读
int stdout_pipe_fd[2]; // 子写 → 父读
(stdin_pipe_fd);
(stdout_pipe_fd);


 server_pid_ = fork();

 (server_pid_ == ) {
    
(stdin_pipe_fd[], STDIN_FILENO);
(stdout_pipe_fd[], STDOUT_FILENO);
(server_path_.(), argv.());
}


stdin_pipe_ = stdin_pipe_fd[]; 
stdout_pipe_ = stdout_pipe_fd[]; 
(stdout_pipe_, F_SETFL, O_NONBLOCK);
pipe
pipe
// 2. fork 出子进程
pid_t
if
0
// 3. 子进程内:重定向 stdin/stdout 到管道
dup2
0
dup2
1
execv
c_str
data
// 4. 父进程内:保存可用端,设置非阻塞读
1
// 可写端
0
// 可读端
fcntl

通过 dup2() 将标准输入输出'嫁接'到管道,子进程完全感知不到自己在被远程控制——这正是 STDIO 传输的精妙之处。

后台读取线程

连接建立后,主线程启动一个后台线程持续从 stdout_pipe_ 读取数据:

notification_thread_ = std::thread([this]{ processNotificationsStdio(); });

读到完整的 分隔行后,解析 JSON-RPC,判断是响应还是通知,分别处理:

  • 响应(有 id 字段)→ 推入 response_queue_,唤醒等待的调用方
  • 通知(method == "notifications/message")→ 调用用户注册的回调

SSE 模式:远程服务通信

SSE(Server-Sent Events)是一种基于 HTTP 的单向推送协议,非常适合服务端主动推送事件流。

整体设计
MCPClient
├── HTTP POST ────────────────→ /message (发送 JSON-RPC 请求)
└── SSE 长连接 ←──────────────── /sse (接收响应和通知)

请求与响应走两条独立通道:

  1. 通过 sendRequestSSE() 发一个普通 POST 请求
  2. 后台 SSE 监听线程(processNotificationsSSE())持续接收服务端推送的事件流
  3. sseWriteCallback() 解析 data: 行中的 JSON,分发到响应队列或通知回调
CURL 回调机制
size_t MCPClient::sseWriteCallback(char* ptr, size_t size, size_t nmemb, void* userdata) {
    MCPClient* client = static_cast<MCPClient*>(userdata);
    // 追加到缓冲区,寻找 "\n\n" 作为事件分隔符
    // 解析 "data: {...}" 行,提取 JSON 数据
    // 判断是响应还是通知,分别处理
    return size * nmemb;
}

请求 - 响应同步机制

无论哪种传输方式,请求和响应之间的同步都依赖同一套生产者 - 消费者模型:

// 生产者(后台读取线程)
{
    std::lock_guard<std::mutex> lock(queue_mutex_);
    response_queue_.push(response);
    queue_cv_.notify_one(); // 唤醒等待方
}

// 消费者(调用方线程)
std::unique_lock<std::mutex> lock(queue_mutex_);
queue_cv_.wait_for(lock, std::chrono::seconds(30), [this]{
    return !response_queue_.empty();
});
MCPResponse response = response_queue_.front();
response_queue_.pop();

这是经典的 条件变量 + 互斥锁 模式,保证线程安全的同时,避免了忙等(busy-waiting)带来的 CPU 浪费。


JSON-RPC 消息构造

所有请求统一通过 buildJSONRPCRequest() 序列化:

{"jsonrpc":"2.0","method":"tools/call","id":"call_tool_1712345678","params":{"name":"search","arguments":{"query":"MCP protocol"}}}

响应通过 parseJSONRPCResponse() 反序列化,区分成功结果(result 字段)与错误(error.message 字段)。

原子类型的使用

connected_ 和 running_ 均使用原子类型,避免多线程读写时的数据竞争:

std::atomic<bool> connected_{false};
std::atomic<bool> running_{false};

工具调用的完整链路

以调用一个工具为例,梳理完整的数据流:

用户代码
├─→ MCPToolManager::executeTool("search", "{\"query\":\"MCP\"}")
│   │
│   ├─→ MCPClient::callTool()
│   │   │
│   │   ├─→ 构造 MCPRequest {method="tools/call", ...}
│   │   ├─→ sendRequest() → sendRequestStdio() → write(stdin_pipe_)
│   │   │   │
│   │   │   └─→ receiveResponse() ← 阻塞等待(最多 30s)
│   │   │       │
│   │   │       ↑
│   │   │       [后台线程] processNotificationsStdio()
│   │   │           │
│   │   │           read(stdout_pipe_) → parseJSONRPCResponse()
│   │   │           response_queue_.push() + queue_cv_.notify_one()
│   │   │
│   │   └─→ 返回 MCPResponse {result: "搜索结果..."}
│   └─→ 使用工具执行结果

总结

这份 C++ MCP 客户端实现涵盖了以下核心工程要点:

  • 进程间通信:fork + pipe + dup2 + execv 构成 STDIO 模式的基础
  • HTTP 长连接:libcurl + SSE 事件流实现远程传输
  • 线程同步:条件变量 + 互斥锁保证响应的安全传递
  • 协议设计:JSON-RPC 2.0 统一请求/响应/通知的消息格式
  • 接口抽象:IMCPClient 纯虚接口使传输层可替换、可测试

MCP 协议的魅力在于它把 AI 能力的扩展标准化了——无论是本地脚本还是远程服务,都能通过同一套接口被 AI 模型调用。随着 MCP 生态的成熟,这类客户端实现将成为 AI 应用开发的基础设施之一。

目录

  1. C++ 实现 MCP 客户端
  2. MCP 协议简介
  3. 整体架构设计
  4. 传输层:两种通信模式
  5. STDIO 模式:本地进程通信
  6. 核心流程
  7. 启动子进程
  8. 后台读取线程
  9. SSE 模式:远程服务通信
  10. 整体设计
  11. CURL 回调机制
  12. 请求 - 响应同步机制
  13. JSON-RPC 消息构造
  14. 原子类型的使用
  15. 工具调用的完整链路
  16. 总结

更多推荐文章

查看全部
  • Instant-NGP 多分辨率哈希编码技术解析
  • 使用 SCP 命令在 Windows 与 Linux 系统间传输文件
  • 2026 年 AI 编程工具推荐:从 Copilot 到 Trae 的开发者选型指南
  • 鸿蒙金融理财全栈项目:性能优化与安全加固
  • Python 3.14 无 GIL 模式解析:NumPy 3.0 适配与并发性能提升
  • Coze AI 应用开发实战:从智能体构建到 Web 部署
  • 基于 LLaMA-Factory 的大模型 LoRA 微调实战指南
  • 2026 年 3 月行业动态与开源生态全景报告
  • 基于 1Panel 部署 OpenClaw 与 Ollama 本地 AI 助理
  • C++ 多线程进阶:深入理解互斥锁与竞态条件
  • 北京理工大学网络与信息安全专业考研备考经验分享
  • 人脸识别核心算法解析:FaceNet与ArcFace原理及实战
  • Linux scp 安全文件传输工具详解
  • JavaWeb 核心:JSON 数据交换与 Ajax 异步请求实战
  • ROS 2 自主导航机器人系统架构与 SLAM 实践
  • Copilot 指令文件解析:copilot-instructions.md vs AGENTS.md vs .instructions.md
  • Java Web 开发入门指南:基础、环境与核心技术
  • GLM-4.7-Flash 本地 Copilot 工具构建实战教程
  • 算法视角下的数组基础:定义、操作与场景
  • AI 小说生成器实战:基于大语言模型的长篇小说自动化创作

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online