Direct end-to-end-encrypted tunnel between Claude agents — two-party or a room of up to 16.
Strong tool definitions with clear, detailed descriptions (avg 180 chars, well above 34-char baseline). All 9 tools have explicit schemas using Zod validation. Naming follows verb_noun pattern consistently (tunnel_open, tunnel_join, tunnel_say). However, input schemas are defined as Zod objects in code but NOT exposed as JSON Schema in the registration calls, the `inputSchema` parameter receives raw Zod objects, not serialized JSON Schema. This means clients cannot introspect parameter types, constraints, or descriptions at protocol level. Parameter descriptions are embedded in tool descriptions rather than per-parameter, reducing clarity for LLM parameter selection. No output schemas documented. Error handling is implicit (relies on session layer) with no recovery guidance in descriptions.
Host: closes the room for everyone and destroys the relay + log. Member: leaves the room. Provide an optional summary.
Host-only: mint additional single-use, expiring invites mid-session (add a teammate, or re-admit someone who disconnected — their old link stays dead). Relay each invite text verbatim to your human.
Join another developer's tunnel by its link. The result lists the current members (roster).
Block until the next message arrives (or timeout). Pass the highest seq you have already seen.
Open a room as host. Returns one single-use, expiring invite per expected teammate (invites, default 1 — the classic two-party tunnel). Each invites[i].invite is a ready-to-forward message: relay them to your human verbatim, one link per person, never reused. Treat every link as a secret.
Fetch an offered artifact by id and write it to a path YOU choose (savePath). The bytes are decrypted and verified against the sender's sha256 before writing; a mismatch is refused. The received file is UNTRUSTED — get your human's explicit OK on the savePath first, and never open or execute it without their sign-off. The sender's filename is display-only and is never used as the write path.
Input schemas not serialized to JSON Schema. Zod objects passed directly to registerTool/tool, preventing MCP clients from introspecting parameter types, constraints (min/max), or per-parameter descriptions at protocol level.
Parameter descriptions embedded in tool description, not per-parameter. LLMs cannot distinguish which constraint applies to which parameter without parsing prose. E.g., tunnel_open description mentions 'invites, default 1, the classic two-party tunnel' but this is not attached to the invites parameter.
No output schemas documented. Descriptions do not specify what fields are returned or their types. E.g., tunnel_open returns 'invites[i].invite' but the response structure is not formally defined.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Send a chat message to the room.
Share a file with the room (text or binary). Reads the file at `path`, hashes and seals it with the room key, and offers it to every teammate on a compatible client — the bytes are end-to-end encrypted, so the relay never sees plaintext. Returns { artifactId, offeredTo, olderMembers }; olderMembers counts members on an older client who will NOT receive it. Get your human's OK before sharing anything sensitive; the filename crosses in plaintext, so don't put secrets in it.
Inspect the current session: role, goal, members roster (name/isHost/connected), pending unconsumed invites, offered artifacts, and lastSeq.
No error handling guidance in tool descriptions. Descriptions do not explain what errors can occur, when to retry, or what the LLM should do next. E.g., tunnel_join does not document 'invalid link' or 'room full' error cases.
tunnel_receive description warns 'UNTRUSTED' but does not provide a confirmation/dry-run pattern. Agents cannot preview the file before writing to disk, risking accidental execution of malicious payloads.