cxxmcp 1.1.6
C++ MCP SDK
Loading...
Searching...
No Matches
stdio_transport.hpp
Go to the documentation of this file.
1// Copyright (c) 2025 [caomengxuan666]
2
3#pragma once
4
7
8#include <istream>
9#include <mutex>
10#include <optional>
11#include <ostream>
12#include <string>
13#include <string_view>
14#include <utility>
15
18
19namespace mcp::transport {
20
34template <class Role>
35class StdioTransport final : public Transport<Role> {
36 public:
37 using TxMessage = typename Transport<Role>::TxMessage;
38 using RxMessage = typename Transport<Role>::RxMessage;
39
40 StdioTransport(std::istream& input, std::ostream& output)
41 : input_(&input), output_(&output) {}
42
43 std::string_view name() const noexcept override { return "stdio"; }
44
45 protocol::Json diagnostics() const override {
46 std::lock_guard<std::mutex> lock(mutex_);
47 return protocol::Json{
48 {"name", "stdio"},
49 {"closed", closed_},
50 };
51 }
52
53 core::Result<core::Unit> send(TxMessage message) override {
54 const auto serialized = protocol::serialize_message(message);
55 if (!serialized) {
56 return mcp::core::unexpected(serialized.error());
57 }
58
59 std::lock_guard<std::mutex> lock(mutex_);
60 if (closed_) {
61 return mcp::core::unexpected(transport_error(
62 protocol::ErrorCode::InvalidRequest, "transport is closed"));
63 }
64 (*output_) << *serialized << '\n';
65 output_->flush();
66 if (!*output_) {
67 return mcp::core::unexpected(
68 transport_error(protocol::ErrorCode::InternalError,
69 "failed to write transport message"));
70 }
71 return core::Unit{};
72 }
73
75 {
76 std::lock_guard<std::mutex> lock(mutex_);
77 if (closed_) {
78 return std::nullopt;
79 }
80 }
81
82 std::string line;
83 if (!std::getline(*input_, line)) {
84 return std::nullopt;
85 }
86 if (line.empty()) {
87 return mcp::core::unexpected(transport_error(
88 protocol::ErrorCode::ParseError, "empty transport message"));
89 }
90
91 const auto parsed = protocol::parse_message(line);
92 if (!parsed) {
93 return mcp::core::unexpected(parsed.error());
94 }
95 return RxMessage{*parsed};
96 }
97
99 std::lock_guard<std::mutex> lock(mutex_);
100 closed_ = true;
101 return core::Unit{};
102 }
103
104 private:
105 static core::Error transport_error(protocol::ErrorCode code,
106 std::string message) {
107 return core::Error{
108 static_cast<int>(code),
109 std::move(message),
110 {},
111 "transport",
112 };
113 }
114
115 std::istream* input_;
116 std::ostream* output_;
117 mutable std::mutex mutex_;
118 bool closed_ = false;
119};
120
121using ClientStdioTransport = StdioTransport<RoleClient>;
122using ServerStdioTransport = StdioTransport<RoleServer>;
123
124} // namespace mcp::transport
Message-level stdio transport for either MCP role.
Definition stdio_transport.hpp:35
core::Result< core::Unit > send(TxMessage message) override
Sends one JSON-RPC message to the peer.
Definition stdio_transport.hpp:53
core::Result< std::optional< RxMessage > > receive() override
Receives the next JSON-RPC message from the peer.
Definition stdio_transport.hpp:74
std::string_view name() const noexcept override
Human-readable transport name for diagnostics.
Definition stdio_transport.hpp:43
core::Result< core::Unit > close() override
Closes the transport and unblocks receive() where possible.
Definition stdio_transport.hpp:98
protocol::Json diagnostics() const override
Structured implementation diagnostics.
Definition stdio_transport.hpp:45
Minimal message-level transport contract shared by MCP roles.
Definition transport.hpp:38
ErrorCode
JSON-RPC and MCP-specific error codes used in ErrorObject.
Definition types.hpp:65
nlohmann::json Json
JSON value type used by all protocol DTOs.
Definition types.hpp:28
std::monostate Unit
Success value for operations that only need to report failure.
Definition result.hpp:55
tl::expected< T, Error > Result
Alias for the SDK result type.
Definition result.hpp:64
JSON-RPC method names and message construction/parsing helpers.
Structured error returned by fallible SDK operations.
Definition result.hpp:35
Role-generic MCP transport contract for SDK peer/service layers.