38 routes_.push_back(
Route{std::move(definition), std::move(handler),
true});
44 return add(std::move(definition), std::move(handler));
47 template <
class Args,
class Result,
class Handler>
48 ToolRouter& tool(TypedToolRegistration<Args, Result, Handler> registration) {
50 std::move(registration.definition),
51 [handler = std::move(registration.handler)](
52 const ToolContext& context) -> core::Result<protocol::ToolResult> {
54 auto args = detail::argument_from_json<Args>(context.arguments);
56 detail::invoke_tool_handler(handler, std::move(args), context);
57 if constexpr (detail::is_result<decltype(handled)>::value) {
59 return mcp::core::unexpected(handled.error());
61 return detail::value_to_tool_result(*handled);
63 return detail::value_to_tool_result(std::move(handled));
65 } catch (
const std::exception& exception) {
66 return mcp::core::unexpected(core::Error{
67 static_cast<int>(protocol::ErrorCode::InvalidParams),
68 "failed to decode tool arguments",
75 ToolRouter& merge(
const ToolRouter& other) {
76 for (
const auto& route : other.routes_) {
77 routes_.push_back(route);
83 ToolRouter& remove(std::string_view name) {
84 const auto original_size = routes_.size();
85 routes_.erase(std::remove_if(routes_.begin(), routes_.end(),
86 [name](
const Route& route) {
87 return route.definition.name == name;
90 if (routes_.size() != original_size) {
97 if (!routes_.empty()) {
104 ToolRouter& enable(std::string_view name,
bool enabled =
true) {
105 for (
auto& route : routes_) {
106 if (route.definition.name == name) {
107 route.enabled = enabled;
114 ToolRouter& disable(std::string_view name) {
return enable(name,
false); }
116 ToolRouter& on_changed(RouterChangedHandler handler) {
117 on_changed_ = std::move(handler);
121 template <
class Notifier>
122 ToolRouter& bind(Notifier& notifier) {
123 auto previous = std::move(on_changed_);
124 on_changed_ = [previous = std::move(previous), ¬ifier] {
128 (void)notifier.notify_tool_list_changed();
133 const std::vector<Route>& routes() const noexcept {
return routes_; }
135 ServerBuilder& apply_to(ServerBuilder& builder)
const {
136 for (
const auto& route : routes_) {
138 builder.add_tool(route.definition, route.handler);
145 void notify_changed()
const {
151 std::vector<Route> routes_;
165 routes_.push_back(
Route{std::move(prompt), std::move(handler),
true});
171 return add(std::move(prompt), std::move(handler));
174 PromptRouter& merge(
const PromptRouter& other) {
175 for (
const auto& route : other.routes_) {
176 routes_.push_back(route);
182 PromptRouter& remove(std::string_view name) {
183 const auto original_size = routes_.size();
184 routes_.erase(std::remove_if(routes_.begin(), routes_.end(),
185 [name](
const Route& route) {
186 return route.prompt.name == name;
189 if (routes_.size() != original_size) {
195 PromptRouter& clear() {
196 if (!routes_.empty()) {
203 PromptRouter& enable(std::string_view name,
bool enabled =
true) {
204 for (
auto& route : routes_) {
205 if (route.prompt.name == name) {
206 route.enabled = enabled;
213 PromptRouter& disable(std::string_view name) {
return enable(name,
false); }
215 PromptRouter& on_changed(RouterChangedHandler handler) {
216 on_changed_ = std::move(handler);
220 template <
class Notifier>
221 PromptRouter& bind(Notifier& notifier) {
222 auto previous = std::move(on_changed_);
223 on_changed_ = [previous = std::move(previous), ¬ifier] {
227 (void)notifier.notify_prompt_list_changed();
232 const std::vector<Route>& routes() const noexcept {
return routes_; }
234 ServerBuilder& apply_to(ServerBuilder& builder)
const {
235 for (
const auto& route : routes_) {
237 builder.add_prompt(route.prompt, route.handler);
244 void notify_changed()
const {
250 std::vector<Route> routes_;
270 resources_.push_back(
271 ResourceRoute{std::move(resource), std::move(handler),
true});
277 ResourceReadHandler handler) {
278 return add(std::move(resource), std::move(handler));
281 ResourceRouter& add_template(protocol::ResourceTemplate resource_template) {
282 templates_.push_back(TemplateRoute{std::move(resource_template),
true});
287 ResourceRouter& resource_template(
288 protocol::ResourceTemplate resource_template) {
289 return add_template(std::move(resource_template));
292 ResourceRouter& merge(
const ResourceRouter& other) {
293 for (
const auto& route : other.resources_) {
294 resources_.push_back(route);
296 for (
const auto& route : other.templates_) {
297 templates_.push_back(route);
303 ResourceRouter& remove_resource(std::string_view uri) {
304 const auto original_size = resources_.size();
305 resources_.erase(std::remove_if(resources_.begin(), resources_.end(),
306 [uri](
const ResourceRoute& route) {
307 return route.resource.uri == uri;
310 if (resources_.size() != original_size) {
316 ResourceRouter& remove_template(std::string_view uri_template) {
317 const auto original_size = templates_.size();
319 std::remove_if(templates_.begin(), templates_.end(),
320 [uri_template](
const TemplateRoute& route) {
321 return route.resource_template.uri_template ==
325 if (templates_.size() != original_size) {
331 ResourceRouter& clear_resources() {
332 if (!resources_.empty()) {
339 ResourceRouter& clear_templates() {
340 if (!templates_.empty()) {
347 ResourceRouter& clear() {
348 if (!resources_.empty() || !templates_.empty()) {
356 ResourceRouter& enable_resource(std::string_view uri,
bool enabled =
true) {
357 for (
auto& route : resources_) {
358 if (route.resource.uri == uri) {
359 route.enabled = enabled;
366 ResourceRouter& disable_resource(std::string_view uri) {
367 return enable_resource(uri,
false);
370 ResourceRouter& enable_template(std::string_view uri_template,
371 bool enabled =
true) {
372 for (
auto& route : templates_) {
373 if (route.resource_template.uri_template == uri_template) {
374 route.enabled = enabled;
381 ResourceRouter& disable_template(std::string_view uri_template) {
382 return enable_template(uri_template,
false);
385 ResourceRouter& on_changed(RouterChangedHandler handler) {
386 on_changed_ = std::move(handler);
390 template <
class Notifier>
391 ResourceRouter& bind(Notifier& notifier) {
392 auto previous = std::move(on_changed_);
393 on_changed_ = [previous = std::move(previous), ¬ifier] {
397 (void)notifier.notify_resource_list_changed();
402 const std::vector<ResourceRoute>& resources() const noexcept {
406 const std::vector<TemplateRoute>& templates() const noexcept {
410 ServerBuilder& apply_to(ServerBuilder& builder)
const {
411 for (
const auto& route : resources_) {
413 builder.add_resource(route.resource, route.handler);
416 for (
const auto& route : templates_) {
418 builder.add_resource_template(route.resource_template);
425 void notify_changed()
const {
431 std::vector<ResourceRoute> resources_;
432 std::vector<TemplateRoute> templates_;