From b3d52c966d9c59836fd168bb43c339ff996a3e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Arrufat?= Date: Sun, 1 Mar 2026 20:23:23 +0900 Subject: [PATCH] mcp: handle errors during resource and tool streaming --- src/mcp/resources.zig | 13 +++++++++---- src/mcp/tools.zig | 26 ++++++++++++++------------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/mcp/resources.zig b/src/mcp/resources.zig index d5f16770..9742800b 100644 --- a/src/mcp/resources.zig +++ b/src/mcp/resources.zig @@ -1,6 +1,7 @@ const std = @import("std"); const lp = @import("lightpanda"); +const log = lp.log; const protocol = @import("protocol.zig"); const Server = @import("Server.zig"); @@ -58,8 +59,12 @@ const ResourceStreamingResult = struct { try jw.writer.writeByte('"'); var escaped = protocol.JsonEscapingWriter.init(jw.writer); switch (self.format) { - .html => try lp.dump.root(self.server.page.document, .{}, &escaped.writer, self.server.page), - .markdown => try lp.markdown.dump(self.server.page.document.asNode(), .{}, &escaped.writer, self.server.page), + .html => lp.dump.root(self.server.page.document, .{}, &escaped.writer, self.server.page) catch |err| { + log.err(.mcp, "html dump failed", .{ .err = err }); + }, + .markdown => lp.markdown.dump(self.server.page.document.asNode(), .{}, &escaped.writer, self.server.page) catch |err| { + log.err(.mcp, "markdown dump failed", .{ .err = err }); + }, } try jw.writer.writeByte('"'); jw.endWriteRaw(); @@ -79,7 +84,7 @@ pub fn handleRead(server: *Server, arena: std.mem.Allocator, req: protocol.Reque }; if (std.mem.eql(u8, params.uri, "mcp://page/html")) { - const result = ResourceStreamingResult{ + const result: ResourceStreamingResult = .{ .contents = &.{.{ .uri = params.uri, .mimeType = "text/html", @@ -88,7 +93,7 @@ pub fn handleRead(server: *Server, arena: std.mem.Allocator, req: protocol.Reque }; try sendResult(server, req.id.?, result); } else if (std.mem.eql(u8, params.uri, "mcp://page/markdown")) { - const result = ResourceStreamingResult{ + const result: ResourceStreamingResult = .{ .contents = &.{.{ .uri = params.uri, .mimeType = "text/markdown", diff --git a/src/mcp/tools.zig b/src/mcp/tools.zig index 80253a6a..0b1de596 100644 --- a/src/mcp/tools.zig +++ b/src/mcp/tools.zig @@ -126,21 +126,23 @@ const ToolStreamingText = struct { var escaped = protocol.JsonEscapingWriter.init(jw.writer); const w = &escaped.writer; switch (self.action) { - .markdown => try lp.markdown.dump(self.server.page.document.asNode(), .{}, w, self.server.page), + .markdown => lp.markdown.dump(self.server.page.document.asNode(), .{}, w, self.server.page) catch |err| { + log.err(.mcp, "markdown dump failed", .{ .err = err }); + }, .links => { - const list = Selector.querySelectorAll(self.server.page.document.asNode(), "a[href]", self.server.page) catch |err| { - log.err(.mcp, "Error querying links: {s}", .{@errorName(err)}); - return; - }; - var first = true; - for (list._nodes) |node| { - if (node.is(Element)) |el| { - if (el.getAttributeSafe(String.wrap("href"))) |href| { - if (!first) try w.writeByte('\n'); - try w.writeAll(href); - first = false; + if (Selector.querySelectorAll(self.server.page.document.asNode(), "a[href]", self.server.page)) |list| { + var first = true; + for (list._nodes) |node| { + if (node.is(Element)) |el| { + if (el.getAttributeSafe(String.wrap("href"))) |href| { + if (!first) try w.writeByte('\n'); + try w.writeAll(href); + first = false; + } } } + } else |err| { + log.err(.mcp, "query links failed", .{ .err = err }); } }, }