77#include " fastmcpp/client/types.hpp"
88#include " fastmcpp/exceptions.hpp"
99#include " fastmcpp/server/server.hpp"
10+ #include " fastmcpp/telemetry.hpp"
1011#include " fastmcpp/types.hpp"
1112#include " fastmcpp/util/json_schema.hpp"
1213#include " fastmcpp/util/json_schema_type.hpp"
@@ -68,6 +69,15 @@ class IServerRequestTransport
6869 virtual void set_server_request_handler (ServerRequestHandler handler) = 0;
6970};
7071
72+ // / Optional transport interface: some transports expose MCP session IDs.
73+ class ISessionTransport
74+ {
75+ public:
76+ virtual ~ISessionTransport () = default ;
77+ virtual std::string session_id () const = 0;
78+ virtual bool has_session () const = 0;
79+ };
80+
7181// / Loopback transport for in-process server testing
7282class LoopbackTransport : public ITransport
7383{
@@ -240,12 +250,15 @@ class Client
240250 CallToolResult call_tool_mcp (const std::string& name, const fastmcpp::Json& arguments,
241251 const CallToolOptions& options = CallToolOptions{})
242252 {
253+ auto span =
254+ telemetry::client_span (" tool " + name, " tools/call" , name, transport_session_id ());
243255
244256 fastmcpp::Json payload = {{" name" , name}, {" arguments" , arguments}};
245257
246258 // Add _meta if provided
247- if (options.meta )
248- payload[" _meta" ] = *options.meta ;
259+ auto propagated_meta = telemetry::inject_trace_context (options.meta );
260+ if (propagated_meta)
261+ payload[" _meta" ] = *propagated_meta;
249262
250263 if (options.progress_handler )
251264 options.progress_handler (0 .0f , std::nullopt , " request started" );
@@ -439,7 +452,13 @@ class Client
439452 // / Read a resource by URI
440453 ReadResourceResult read_resource_mcp (const std::string& uri)
441454 {
442- auto response = call (" resources/read" , {{" uri" , uri}});
455+ auto span = telemetry::client_span (" resource " + uri, " resources/read" , uri,
456+ transport_session_id ());
457+ fastmcpp::Json payload = {{" uri" , uri}};
458+ auto propagated_meta = telemetry::inject_trace_context (std::nullopt );
459+ if (propagated_meta)
460+ payload[" _meta" ] = *propagated_meta;
461+ auto response = call (" resources/read" , payload);
443462 return parse_read_resource_result (response);
444463 }
445464
@@ -477,7 +496,8 @@ class Client
477496 GetPromptResult get_prompt_mcp (const std::string& name,
478497 const fastmcpp::Json& arguments = fastmcpp::Json::object())
479498 {
480-
499+ auto span =
500+ telemetry::client_span (" prompt " + name, " prompts/get" , name, transport_session_id ());
481501 fastmcpp::Json payload = {{" name" , name}};
482502 if (!arguments.empty ())
483503 {
@@ -491,6 +511,10 @@ class Client
491511 payload[" arguments" ] = stringArgs;
492512 }
493513
514+ auto propagated_meta = telemetry::inject_trace_context (std::nullopt );
515+ if (propagated_meta)
516+ payload[" _meta" ] = *propagated_meta;
517+
494518 auto response = call (" prompts/get" , payload);
495519 return parse_get_prompt_result (response);
496520 }
@@ -810,6 +834,18 @@ class Client
810834 }
811835 }
812836
837+ std::optional<std::string> transport_session_id () const
838+ {
839+ if (!transport_)
840+ return std::nullopt ;
841+ if (auto * session_transport = dynamic_cast <ISessionTransport*>(transport_.get ()))
842+ {
843+ if (session_transport->has_session ())
844+ return session_transport->session_id ();
845+ }
846+ return std::nullopt ;
847+ }
848+
813849 // Internal constructor for cloning
814850 Client (std::shared_ptr<ITransport> t, std::shared_ptr<CallbackState> callbacks,
815851 bool /* internal*/ )
@@ -1541,6 +1577,9 @@ inline std::shared_ptr<ResourceTask> Client::read_resource_task(const std::strin
15411577
15421578 fastmcpp::Json task_meta = {{" ttl" , ttl_ms}};
15431579 payload[" _meta" ] = fastmcpp::Json{{" modelcontextprotocol.io/task" , std::move (task_meta)}};
1580+ auto propagated_meta = telemetry::inject_trace_context (payload[" _meta" ]);
1581+ if (propagated_meta)
1582+ payload[" _meta" ] = *propagated_meta;
15441583
15451584 auto response = call (" resources/read" , payload);
15461585
@@ -1575,6 +1614,9 @@ Client::get_prompt_task(const std::string& name, const fastmcpp::Json& arguments
15751614
15761615 fastmcpp::Json task_meta = {{" ttl" , ttl_ms}};
15771616 payload[" _meta" ] = fastmcpp::Json{{" modelcontextprotocol.io/task" , std::move (task_meta)}};
1617+ auto propagated_meta = telemetry::inject_trace_context (payload[" _meta" ]);
1618+ if (propagated_meta)
1619+ payload[" _meta" ] = *propagated_meta;
15781620
15791621 auto response = call (" prompts/get" , payload);
15801622
0 commit comments