Skip to content

Repository files navigation

MCP C++ Server SDK

C++17 服务端 SDK,支持 Tools、Resources、Prompts、列表分页、参数补全和资源内容更新,提供 stdio 与 Streamable HTTP。现代协议使用 MCP 2026-07-28,同时兼容 2025-11-25、2025-06-18;三种协议共用业务注册与请求控制。

构建与安装

支持 POSIX 环境,当前在 macOS 验证。需要 C++17 编译器、CMake 3.16+、OpenSSL 3.x;测试还需要 Python 3。首次配置会下载固定提交的 jsoncons,nlohmann/json 和 cpp-httplib 已在源码中。

cmake -S . -B build-sdk -DCMAKE_BUILD_TYPE=Debug
cmake --build build-sdk -j 8
ctest --test-dir build-sdk --output-on-failure
cmake --install build-sdk --prefix "$PWD/build-sdk/install"

仅构建 SDK 与示例程序时加 -DBUILD_TESTING=OFF。离线构建可用 -DFETCHCONTENT_SOURCE_DIR_JSONCONS=/path/to/jsoncons 指向版本一致的本地源码。

外部工程使用安装后的公共接口:

find_package(mcp CONFIG REQUIRED)
add_executable(my_server main.cc)
target_link_libraries(my_server PRIVATE mcp::sdk)

配置外部工程时设置 -DCMAKE_PREFIX_PATH=/path/to/install。tests/consumer 是一个实际独立构建的最小消费者。

开发期间也可直接使用构建目录,设置 -Dmcp_DIR=/absolute/path/to/build-sdk;同样通过 find_package(mcp CONFIG REQUIRED) 引用 mcp::sdk。

注册工具

#include <csignal>
#include <mcp/server.h>

int main() {
  std::signal(SIGPIPE, SIG_IGN);
  mcp::Server server;
  server.AddTool({"echo", "Echo a message", {{"type", "object"},
      {"properties", {{"message", {{"type", "string"}}}}},
      {"required", {"message"}}}},
      [](const mcp::Json& args, mcp::RequestContext&) {
        return mcp::ToolResult::Text(args.at("message"));
      });
  server.RunStdio();
}

使用 HTTP 时将最后一行换成 server.RunHttp({"127.0.0.1", 8080, {}})。两种传输都由 SDK 处理协议差异。工具须在服务启动前注册,启动后列表保持只读;并发调用要求 handler 自身线程安全。

ToolResult::Text 返回文本,Structured 返回任意 JSON 值及其文本表示,Failure 返回 isError。ToolDefinition::output_schema 可声明输出契约;不符合输出 schema 的成功结果会被拒绝。输入 schema 使用 JSON Schema 2020-12,根部须声明 type: "object",支持本地引用,默认不解析外部网络引用。无效 schema 和不支持的方言在注册时拒绝。

现代客户端可接收对象、数组、标量和 null 的结构化输出。旧版协议仅接受对象:数组、标量和 null 仍在服务端校验,但以 JSON 文本返回;旧版工具列表只公布根部为 type: "object" 的输出 schema。

Server::Handle 是自定义传输和进程内集成的公共入口。它返回 JSON-RPC 响应,通知返回 null;可选通知回调用于接收进度和订阅事件。

进度、取消和续传

handler 通过 RequestContext::ReportProgress 报告进度,通过 IsCancelled 或 WaitFor 合作响应取消。stdio 接收取消通知,现代 HTTP 流断开会取消对应请求。Server::Stop 应从普通线程调用;调用方须等待运行线程和 handler 退出后再销毁 Server。阻塞业务必须提供自己的超时或取消机制,SDK 不强制终止 C++ 线程。停止后的实例不重新启动,需要创建新实例。

现代 subscriptions/listen 会先确认实际支持的资源 URI,再发送带 subscriptionId 的内容更新。没有资源时仍可确认空过滤集合。工具、资源和提示定义在启动后只读,不声明 listChanged;取消、断连和超限会清理对应订阅。

ToolResult::InputRequired 提供 MRTR 框架,支持规范中的输入请求映射;InputResponses() 提供已做结构校验的客户端响应,RequestState() 提供通过完整性检查的续传状态。SDK 不实现 Roots、Sampling、Elicitation 的业务处理。

续传状态由 HMAC-SHA256 保护,绑定工具名、参数和过期时间。默认密钥仅在当前 Server 实例内有效;跨实例恢复需配置至少 32 字节的同一应用专用 request_state_key。状态有签名但未加密,不能存放需要对客户端保密的信息。有效期内允许重放,一次性业务操作需要自行实现防重放与授权检查。

资源、提示与补全

AddResource 注册资源 URI 和读取回调,AddResourceTemplate 注册参数化地址,AddPrompt 注册带字符串参数的消息模板。两类模板都可附带 CompletionHandler。示例和完整约束见 上下文示例。

server.AddResource({"report://current", "current", "Current report", "text/plain"},
    [](const mcp::ResourceRequest& request, mcp::RequestContext&) {
      return std::vector<mcp::ResourceContent>{
          mcp::ResourceContent::Text(request.uri, "ready")};
    });

资源内容变化后,应用调用 NotifyResourceUpdated(uri),SDK 将更新排入匹配订阅的有界队列,不等待客户端读取,也不承诺客户端已收到。客户端收到 URI 后重新读取内容。业务回调负责其数据源的权限、读取上限和线程安全;SDK 不自动读取本机文件或网络地址。

page_size 默认 100,四类列表共用分页行为;不透明 cursor 绑定服务实例、列表和协议,使用 request_state_ttl_seconds 作为有效期。max_completions_per_second 默认 100,为整个实例每秒的补全请求上限;max_resource_subscriptions 默认 128,为单流可关注的 URI 数上限。通知队列使用 max_queue_messages;现代订阅占用活跃请求名额,旧版 HTTP GET 流另以 max_concurrent_requests 限制总数,每 session 最多一个 GET 流。

资源、提示和补全回调共用并发准入、合作取消与超时。stdio 保持读取取消消息;HTTP 对这些回调使用请求级 SSE 感知断连。回调异常、输出违约或响应超出 max_body_bytes 返回协议错误,资源不存在返回 -32002;已注册的资源回调可抛出 ResourceNotFound 表达这一情况。应用应在创建大型返回值之前限制读取量。

旧版使用 resources/subscribe、resources/unsubscribe:stdio 在共享输出流投递,HTTP 通过受 Origin、版本和 session 校验的 GET SSE 通道投递。GET 断开或队列超限会清空该流的订阅,重连后需重新订阅;session 终止或空闲过期也会清理流。现代 HTTP GET 仍返回 405。

HTTP 与资源限制

HTTP 端点固定为 /mcp,默认绑定 loopback。Origin 缺省允许本机服务对应的精确来源,也可通过 HttpOptions::allowed_origins 设置允许列表。现代请求验证版本、方法和名称头与请求体的一致性,并支持名称的 Base64 哨兵编码。

旧版成功初始化后分配服务端会话,支持会话超时和 DELETE 终止。请求进度使用 POST 响应流,旧版资源更新使用受会话约束的 GET SSE;现代 GET 返回 405,两种模式均不提供 SSE 历史重放。

ServerOptions 默认限制:请求体 1 MiB、8 个长请求、128 个旧版会话、每条流 64 条待发送消息;旧版会话闲置 600 秒失效,累计请求 ID 上限 65536,工具默认截止时间 30 秒,续传状态有效期 300 秒。上限可配置。线上的 JSON 消息嵌套深度限制为 64。达到旧版 ID 上限时需重新连接。

交付范围为本机服务。Tasks、OAuth、公网多用户部署和 TLS 运维不在此版本中。

客户端与验证

内置 mcp_server 提供一个 echo 工具:

./build-sdk/src/mcp_server
./build-sdk/src/mcp_server --mode http --host 127.0.0.1 --port 8080

Codex 的 stdio 配置使用 command = "/absolute/path/to/mcp_server";HTTP 配置使用 url = "http://127.0.0.1:8080/mcp"。Cursor 的 mcpServers 项也可使用对应的 command 或 url。默认连接走客户端支持的兼容协议;Codex 0.149.0 的现代 HTTP 路径需要 mcp_2026_07_28 功能开关。

CTest 覆盖公共 API、协议流、进度与取消、MRTR、安装后独立消费者。官方客户端检查独立运行:

node tests/verify_official_client.mjs build-sdk/src/mcp_server /path/to/node_modules

该目录需要固定的 @modelcontextprotocol/client@2.0.0。tests/verify_real_client.py --help 提供实际 Codex/Cursor 验收命令;它使用已有登录态并消耗相应客户端额度,因此不自动进入 CTest。验收以实际 tools/call 和对应 wire 响应为准。

可选的 ONNX 手写数字识别示例 提供 recognize_mnist,启动时加载模型并复用 Session,可由 Codex/Cursor 经两种传输调用。默认构建保持无 ML 依赖。

协议及依赖版本见 依赖说明。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages