Commit Graph
11 Commits
Author SHA1 Message Date
Adrià Arrufat f1bdd0019f Merge branch 'main' into tool-session 2026-08-28 15:14:56 +02:00
Adrià Arrufat e6165d23bb mcp: release a large HTTP response buffer after the reply
The transport already drops its staging buffer past 256 KB, but the
connection buffer that receives the copy lives for the whole keep-alive
connection and was only ever cleared, so one screenshot pinned its
capacity per open connection. Apply the same threshold there.

Claude-Session: https://claude.ai/code/session_01S9t1TX3vTKunaXdnatbcjB
2026-08-27 21:28:32 +02:00
Adrià Arrufat d8893f95d7 mcp: bracket every isolate use, drop park_isolates
stdio kept the isolate permanently entered while HTTP parked it between
requests, so a handler touching page JS without enterIsolate passed the
stdio-mode tests and only failed under --port. Bracket unconditionally:
stdio is the one-isolate case of the same discipline.

The flag survives only as `multi_session`, which is what it always gated:
the session tools need a transport that routes by id.

Claude-Session: https://claude.ai/code/session_01M6WGk8wZSE28efFQkYT9SK
2026-08-27 16:30:49 +02:00
Pierre Tachoire 78fda6779f allow localhost host to connect to CDP and MCP 2026-08-26 09:24:01 +08:00
Pierre TachoireandAdrià Arrufat a0e3da6a6b Update src/mcp/HttpServer.zig
Co-authored-by: Adrià Arrufat <1671644+arrufat@users.noreply.github.com>
2026-08-26 09:24:01 +08:00
Pierre Tachoire 9db3c1bb94 mcp: enforce HTTP conditions
Apply same conditions than CDP for MCP HTTP conns:
* refuse requests including Origin header
* accept only ip as host
* ensure content-type is json for POST
2026-08-26 09:24:00 +08:00
Adrià Arrufat ec396f5dc1 mcp: close the connection after a keep_alive=false response
std.http.Server's respond() only drains the request body when the server
keeps the connection alive; with keep_alive=false it leaves the body
unread, sets reader.state = .closing, and expects the caller to sever the
connection ("the connection will be severed after the response is sent").

handleConn looped on the client's keep_alive flag instead, which is true
for any HTTP/1.1 request, so after a 405/413/415/417/403 it called
receiveHead() again and fed the unread POST body to the head parser. The
server advertised `connection: close` but held the socket open until the
peer gave up.

Honour the reader's closing state so the socket is closed right after the
rejection response.
2026-08-25 10:33:39 +02:00
Karl Seguin 2d32e78838 chore: Remove Server component from Network
Network is less cohesive than https://github.com/lightpanda-io/browser/pull/3242
would indicate. It has two distinct and _completely_ separate responsibilities.

1 - It acts as the base for each HttpClient, providing a shared connection pool
    (for http and ws) and access to the process wide Cache, RobotStore,
    WebBothAuth, certificates, ...

2 - It accepts, polls and reads from CDP connection

There is zero relationship between these, and it's a particularly bad place for
this duality to exist because both parts are, in their own way, the main
multi-threaded junction in the system.

This commit is purely mechanical it:

1 - Keeps network as the base for each HttpClient.
2 - Extract the CDP interaction into the existing Server.zig
3 - Gives mcp's HttpServer its own accept loop
2026-08-22 10:11:30 +08:00
Karl Seguin 8e42d63c1c zig: Zig 0.16
Built against https://github.com/lightpanda-io/zig-v8-fork/tree/zig-0.16 but
it doesn't require a new v8 build.

Built against https://github.com/lightpanda-io/boringssl-zig/tree/zig-0.16
since the current fork we point to isn't updated.

A global std.Io instance, lp.io. Way easier this way and requires 0 changes to
our libcurl integration / event loop.

Network code uses a new layer that does what Zig 0.15's posix package used to
do. Again, quicker migration that way. But, as long as we have the global IO,
and given the half-baked nature of networking in std.Io 0.16, this just makes
sense. Things can be migrated as needed.

The std.time.* -> std.Io.Timestamp/Clock/Duration resulted in _a lot_ of
changes. ArrayList = .{} -> ArrayList -> .empty also resulted in a lot of
changes, but that's obviously superficial. As is the trimLeft/trimRight ->
trimStart/trimEnd rename.

Locking adopt the `Uncancelable` variants, e.g. mutex.lockUncancelable() to
preserve the error-free signature (and, because cancellation would be something
we'd have to put more thought into).

std.json.ObjectMap is now unmanaged, so the allocator had to be passed along.
However, there's still a deprecated managed variant of MemoryPool, so I switched
to it (we can do a small follow up PR to move to the unmanaged after).

I tried use_llvm = false, but it locks my computer, consuming RAM until MacOS
gives me a popup I've never seen before, begging me to start killing processes.

Agent and the networking stuff saw the most significant changes.
2026-07-22 13:26:03 +08:00
Adrià Arrufat 2c4803b1cf mcp: ensure clean http server shutdown
Track active connections and shut down sockets during deinit to unblock
pending reads. Drain the job queue properly before stopping the worker.
Also fix `--http-port` references to `--port` in docs and errors.
2026-07-13 10:07:37 +02:00
Adrià Arrufat f66f0c191d mcp: add HTTP transport and multi-session support
Introduces an HTTP transport option to serve multipleagents from a
single process. Each connection is routed to its own isolated
browsing session using the `Mcp-Session-Id` header.

Also adds new session management tools (`session_new`, `session_list`,
`session_close`) and refactors the MCP server to support multiple V8
isolates with parking.
2026-07-12 15:27:20 +02:00