addrbookFor publishers
← The evidence ledger

Evidence row 309471

Observed , by probe.mcp/1.

Kind
mcp.tools
About
endpoint 746e2175-08e8-4cd4-9a6a-e4648f817b80
Recorded
Previous row
None: the first of its kind about this subject
Body SHA-256
d5a93f69b1fae07220c41005da2e88f35f20364f42073124e5ca73fc84399d8d
Leaf
0xa656aed1b4b665eb110b3eaf81f9d2d60566ef4b81b40fcb93553d51d7a7397f

What was observed

{
  "count": 9,
  "tools": [
    {
      "description": "Use the local client at https://handover.tools/client/channel.py rather than calling this by hand. After a fetch with peek=true, the client calls this with the highest sequence number it processed. That is what the peer sees as read, so a response lost in transit never turns into a false read receipt. The cursor never moves back or past the last stored message; calling again with the same seq changes nothing. Slides the channel's expiry.",
      "inputSchema": {
        "properties": {
          "key": {
            "description": "This side's channel key.",
            "type": "string"
          },
          "seq": {
            "description": "Highest sequence number this side processed.",
            "type": "integer"
          }
        },
        "required": [
          "key",
          "seq"
        ],
        "type": "object"
      },
      "name": "channel_ack"
    },
    {
      "description": "Either side can close. Deletes the channel, both keys, and every stored message immediately. The other side's next fetch reports not_found_or_closed.",
      "inputSchema": {
        "properties": {
          "key": {
            "description": "This side's channel key.",
            "type": "string"
          }
        },
        "required": [
          "key"
        ],
        "type": "object"
      },
      "name": "channel_close"
    },
    {
      "description": "Use the local client at https://handover.tools/client/channel.py rather than calling this by hand: it returns ciphertext only the client can decrypt. Returns the peer's messages this side has not fetched yet. Call only when the person asks. Clients fetch with peek=true, which marks nothing, and then call channel_ack once they have processed the messages; without peek, the messages are marked read when the server sends them (kept for older clients); after=N returns messages after sequence N (the client passes the last one it processed, so a response lost in transit is fetched again; a smaller N re-reads). Side A also receives the peer's SPAKE2 message here to finish pairing. Large backlogs are paged: more=true means fetch again.",
      "inputSchema": {
        "properties": {
          "after": {
            "description": "Return messages with seq greater than this. Defaults to what this side has already fetched.",
            "type": "integer"
          },
          "key": {
            "description": "This side's channel key.",
            "type": "string"
          },
          "peek": {
            "description": "If true, do not mark messages as read.",
            "type": "boolean"
          }
        },
        "required": [
          "key"
        ],
        "type": "object"
      },
      "name": "channel_fetch"
    },
    {
      "description": "Second half of pairing, run by the local client at https://handover.tools/client/channel.py. Send only the first 3 characters of the spoken code (the nameplate) plus this side's SPAKE2 message; the other 5 characters are the password and must never be sent to the server. The nameplate is consumed on success. Returns this side's key and the peer's SPAKE2 message. Unknown, used, or expired nameplates are deliberately indistinguishable.",
      "inputSchema": {
        "properties": {
          "nameplate": {
            "description": "First 3 characters of the spoken code, e.g. 'K7M'.",
            "type": "string"
          },
          "pake_msg": {
            "description": "Base64 SPAKE2 message (side B).",
            "type": "string"
          }
        },
        "required": [
          "nameplate",
          "pake_msg"
        ],
        "type": "object"
      },
      "name": "channel_join"
    },
    {
      "description": "Start pairing two agents on different machines for a multi-round exchange (e.g. one explores, the other studies and asks follow-up questions). Use the local client at https://handover.tools/client/channel.py — do not call this by hand. The client generates a secret password locally, and this call returns only a 3-character nameplate; the person gives nameplate + password (8 letters) to the other machine. The server never sees the password, so it cannot impersonate either side (SPAKE2). The person stays in the loop: send only after they approve, fetch only when they ask. Counts as one write against the daily write quota.",
      "inputSchema": {
        "properties": {
          "pake_msg": {
            "description": "Base64 SPAKE2 message from the local client (side A).",
            "type": "string"
          }
        },
        "required": [
          "pake_msg"
        ],
        "type": "object"
      },
      "name": "channel_open"
    },
    {
      "description": "Relay one ciphertext to the other side of a paired channel. The ciphertext must come from the local client at https://handover.tools/client/channel.py; do not call this by hand, and never base64-encode plaintext into it (that is rejected). Only send after the person has seen and approved the draft — the server cannot enforce this, the calling agent must. Returns the message's sequence number and how far the peer has read.",
      "inputSchema": {
        "properties": {
          "ciphertext": {
            "description": "Base64 ciphertext from the client.",
            "type": "string"
          },
          "key": {
            "description": "This side's channel key.",
            "type": "string"
          }
        },
        "required": [
          "key",
          "ciphertext"
        ],
        "type": "object"
      },
      "name": "channel_send"
    },
    {
      "description": "Fetch content stored by handoff_put using its 8-character code. The code is case-insensitive and hyphens are ignored, so 'kvmtrhxp' and 'KVMT-RHXP' are the same; the person may give it as a link like handover.tools/kvmtrhxp, and passing that is fine too. Return the content to the person verbatim and complete: it can be fetched only once. If the code is unknown, already fetched, or expired, content is null with a reason — these cases are deliberately indistinguishable. A channel link (handover.tools/join/<code>, or anything the person said with \"Join\") is not fetched: join it with the channel client (see /llms.txt). Passed here, it returns reason channel_code with the steps.",
      "inputSchema": {
        "properties": {
          "code": {
            "description": "The 8-character code from handoff_put, e.g. 'kvmtrhxp'.",
            "type": "string"
          }
        },
        "required": [
          "code"
        ],
        "type": "object"
      },
      "name": "handoff_get"
    },
    {
      "description": "Store a piece of context and get back a short code. The person gives the link handover.tools/<code> to an agent on another device and it can fetch the content — no copy-paste of long text. The code is 8 letters, easy to type on a phone. NOT ENCRYPTED: the server can read what you store, so never put credentials, tokens, or private data in it, and ask the person before storing an employer's or client's confidential material (security findings, internal system details, unreleased code). Content becomes unreadable after the TTL expires, and by default it can only be fetched once. The response also returns a revoke_key — keep it for the rest of this session so you can destroy the content immediately with handoff_revoke if the person changes their mind. Writes are limited to a small number per day; reads are not.",
      "inputSchema": {
        "properties": {
          "burn_after_read": {
            "description": "If true (the default) the content can be fetched exactly once and is deleted on that fetch.",
            "type": "boolean"
          },
          "content": {
            "description": "The text to hand off. Maximum 256 KB of UTF-8.",
            "type": "string"
          },
          "label": {
            "description": "Optional short hint shown to whoever fetches it, so they can confirm they got the right thing. Max 120 characters.",
            "type": "string"
          },
          "ttl_minutes": {
            "description": "Minutes until the content can no longer be fetched. Default 60, maximum 1440 (24h).",
            "type": "integer"
          }
        },
        "required": [
          "content"
        ],
        "type": "object"
      },
      "name": "handoff_put"
    },
    {
      "description": "Destroy content stored by handoff_put right now, before its TTL runs out and whether or not it has been fetched. Requires the revoke_key returned by handoff_put — the person fetching with the short code cannot revoke, only the writer can. Use this the moment someone says they sent the wrong thing, or changed their mind. Revoking an already gone item is not an error: the outcome is reported as 'already_gone'.",
      "inputSchema": {
        "properties": {
          "revoke_key": {
            "description": "The revoke_key returned by handoff_put. Not the short code — the short code cannot destroy anything.",
            "type": "string"
          }
        },
        "required": [
          "revoke_key"
        ],
        "type": "object"
      },
      "name": "handoff_revoke"
    }
  ]
}

What the leaf hashes

{"body":"d5a93f69b1fae07220c41005da2e88f35f20364f42073124e5ca73fc84399d8d","id":309471,"kind":"mcp.tools","method":"probe.mcp/1","observed_us":1793058917255004,"prev":null,"subject":"746e2175-08e8-4cd4-9a6a-e4648f817b80","subject_kind":"endpoint"}

Proof

Fold these into the leaf in order, hashing each sorted pair with keccak256, to reach the root of (296695 rows).

  1. 0xa65692c9b00737179044d83c82a276ed7bbd1acc6cddd57ce7281ebe6f90ee8c
  2. 0x930c30370f8dbdb9c8f5c8f1182101e3e0cc6cc3b85c25f4eec55b085026255e
  3. 0xd188a8741ae5a825b3a55dfa14fe0ac2ebd494c5d0a63daef5ec363414b67d71
  4. 0x688eafaa313f6d74259bf07b39cd69ca8f8b250c177d3e50dfb53a65fa611bcc
  5. 0x07888cccc753475f31eff47b21e02b0ca52d70d6d25790413da8a8ed84fb99c0
  6. 0x14227c9cf0aa7fb142f520c01faf988ee3344014f1550518c194d663a5e5a4c7
  7. 0xc724aa4c163082529b69445eec2ab95354f354c967e84fdc217e8e6cf212fd08
  8. 0x5b7e9c7537a60d387a7f36993aff903437d6e867580c636b2e8ca07e3d3c8beb
  9. 0x0f68c851b1cb79a5105a4fde13fb9158fc8cb576548b1b5c433d2f541ef01b9f
  10. 0x93c7b1ac8754236471980488e2ae86b7135fed175d7852bf9b8ef708900f060d
  11. 0xf9b4ada16aca6f9b63c09b94519008e1b94357a9d352c245023758b56b82d0b1
  12. 0x1e464fcb484a1e782f9fe44be5118a9de934eb533c96ba10fc7d20e3a3e4711c
  13. 0x292ebdce6b8d3d7ef08ad646a0fd97dee9313ab55c1a350807d9f3013794c37a
  14. 0x428106f4ae4ec142f17aebf6fa50935242f8d3f1c211cf95d6351d03d11da2b7
  15. 0x62a900133713919f4eed33d8336876b7a6d538233b8a4f3ed03b29aa44f5bad0
  16. 0x1ac20d30773e1f4f2f811540e9a99b5cca9177c9e2e029acc0d80cf3f1d11f0f
  17. 0xd21942ae3214eff88e08ab04884fd4b11958b51af9a0741b7668e2d07a2c56c9
  18. 0x9a9024edb5069d88a324facb310a5ce8e495214bbaa968f077bede437390194f
  19. 0x9b9ce5b74b9bab5121612ef6b64920a8d453cbf311096a423eef9702747e868a
Day root
0xf43e8dcc3d451a4788b26be904c55e8c4c0fa75c9666796c51db38d37e2c0df8
Chained
0x702d5ac508f08b0d1accf36af25822d8e5660367494edd17a642fb61e158a57a
Published
On Arc Testnet, block 69251483: 0x495162f8936e19f0039918feebe6c307f327cd6bf8c37219620b1970041fa9ae

How to check it · This row as JSON