mcp: improve navigation reliability and add CDP support

- Configurable navigation timeouts and wait strategies in MCP tools.
- Default navigation timeout increased from 2s to 10s.
- Added navigate, eval, and screenshot MCP tools.
- Supported running a CDP server alongside MCP using --cdp-port.
- Fixed various startup crashes when running CDP in MCP mode.
- Hardened MCP server error handling.
This commit is contained in:
Adrià Arrufat
2026-04-01 12:41:56 +02:00
parent f4802b49e8
commit 58fc60d669
4 changed files with 173 additions and 36 deletions

View File

@@ -160,6 +160,7 @@ pub fn userAgentSuffix(self: *const Config) ?[]const u8 {
pub fn cdpTimeout(self: *const Config) usize {
return switch (self.mode) {
.serve => |opts| if (opts.timeout > 604_800) 604_800_000 else @as(usize, opts.timeout) * 1000,
.mcp => 10000, // Default timeout for MCP-CDP
else => unreachable,
};
}
@@ -167,6 +168,7 @@ pub fn cdpTimeout(self: *const Config) usize {
pub fn port(self: *const Config) u16 {
return switch (self.mode) {
.serve => |opts| opts.port,
.mcp => |opts| opts.cdp_port orelse 0,
else => unreachable,
};
}
@@ -174,6 +176,7 @@ pub fn port(self: *const Config) u16 {
pub fn advertiseHost(self: *const Config) []const u8 {
return switch (self.mode) {
.serve => |opts| opts.advertise_host orelse opts.host,
.mcp => "127.0.0.1",
else => unreachable,
};
}
@@ -192,6 +195,7 @@ pub fn webBotAuth(self: *const Config) ?WebBotAuthConfig {
pub fn maxConnections(self: *const Config) u16 {
return switch (self.mode) {
.serve => |opts| opts.cdp_max_connections,
.mcp => 16,
else => unreachable,
};
}
@@ -199,6 +203,7 @@ pub fn maxConnections(self: *const Config) u16 {
pub fn maxPendingConnections(self: *const Config) u31 {
return switch (self.mode) {
.serve => |opts| opts.cdp_max_pending_connections,
.mcp => 128,
else => unreachable,
};
}
@@ -224,6 +229,7 @@ pub const Serve = struct {
pub const Mcp = struct {
common: Common = .{},
version: mcp.Version = .default,
cdp_port: ?u16 = null,
};
pub const DumpFormat = enum {
@@ -677,6 +683,19 @@ fn parseMcpArgs(
continue;
}
if (std.mem.eql(u8, "--cdp-port", opt) or std.mem.eql(u8, "--cdp_port", opt)) {
const str = args.next() orelse {
log.fatal(.mcp, "missing argument value", .{ .arg = opt });
return error.InvalidArgument;
};
result.cdp_port = std.fmt.parseInt(u16, str, 10) catch |err| {
log.fatal(.mcp, "invalid argument value", .{ .arg = opt, .err = err });
return error.InvalidArgument;
};
continue;
}
if (try parseCommonArg(allocator, opt, args, &result.common)) {
continue;
}