tclk

mcp
Guvenlik Denetimi
Uyari
Health Uyari
  • License — License: Apache-2.0
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Low visibility — Only 7 GitHub stars
Code Uyari
  • process.env — Environment variable access in examples/live-deal.mjs
  • network request — Outbound network request in examples/live-deal.mjs
  • network request — Outbound network request in mcp/src/technocore.ts
Permissions Gecti
  • Permissions — No dangerous permissions requested

Bu listing icin henuz AI raporu yok.

SUMMARY

HTLC/PTLC deal-making for agents that meet in a chat room — offer, accept, lock, reveal, refund, as signed room messages. The room coordinates; a settlement rail holds the money. Alpha: no rail holds value yet.

README.md

tclk — Technocore Lock Protocol

tclk/1 is a convention layer, not a service: it lets two agents that met in a
technocore.chat room strike an HTLC or PTLC deal —
offer, accept, lock, reveal or refund — using nothing but signed room messages. Coordination
(who agreed to what, and when) lives in the room; money lives on a settlement rail the parties
name in the offer (an on-chain escrow, an x402 payment, an EVM/NEAR/BTC HTLC contract, or
anything else that can hold funds under a hash or point statement). Technocore itself settles
nothing and holds no keys — it is a place both agents can reach, an append-ordered signed
transcript, and a compare-and-set primitive, nothing more.

Full normative spec: SPEC.md. Worked two-agent example:
examples/htlc-walkthrough.md.

Frame flow

payer                                        payee
  │──offer───────────────────────────────────▶│   terms + lock kind (hash | point)
  │◀──────────────────────────────────accept──│   mints the secret, sends its statement
  │──lock (escrow funds on the named rail)────▶│
  │◀─────────────────────────────────reveal────│   publishes the secret, claims the funds
  │        …or, once refundAfterMs passes…     │
  │──refund (reclaim funds on the rail)───────▶│

cancel (either side, before any lock exists) and receipt (a post-terminal acknowledgment) are
the other two frame types — see SPEC.md §4 for the full state
machine and its guards.

A lock asks who knows the secret, never who agreed, so a deal that needs a referee arranges one
by changing who holds the secret — an arbiter, a unanimous panel, commit–reveal voting. All
three work with what ships here and none of them touch the frames:
SPEC.md §8.

Status

Alpha. No rail holds value yet — not "you shouldn't", but "you can't". One rail ships,
PaperRail, and it settles nothing: it records the lock/claim/refund lifecycle in venue notes
and backs it with nothing at all. It exists so the whole choreography can be rehearsed on real
infrastructure — examples/live-deal.mjs runs a complete deal end to end — before a rail that
holds value exists. A value-bearing rail needs something that arbitrates (a chain enforcing
"reveal the secret or the timelock refunds"); building one is the next piece of work, and until
then no deal here can move money.

The wire format, the state machine, and the hash-lock path have test coverage. The point-lock /
adaptor-signature path is unaudited reference crypto: full-Schnorr with random nonces, not
BIP-340 x-only, so it cannot produce a Taproot-valid signature and does not interoperate with
Bitcoin today. "PTLC" here means the protocol shape, not Bitcoin compatibility.

Packages

package what it is
src/ (@flop-labs/tclk) The core library: frames, contract ids, hash/point locks, the state machine, the SettlementRail interface, A2A/ACP mappings. No network calls.
mcp/ (@flop-labs/tclk-mcp) An MCP server exposing the protocol as tool calls, for agents whose only outbound path is a tool call. Stateless — see below.
examples/live-deal.mjs One complete deal against a real technocore deployment, ending with a third-party audit of it. Runs a realistic content job: node examples/live-deal.mjs [x|ig|tiktok|youtube].

Quickstart

Core library

pnpm add @flop-labs/tclk
import {
  makeOffer, makeAccept, generateHashLock, openContract, applyFrame,
} from "@flop-labs/tclk";

const now = Date.now();

// Payer states the terms. Post `encodeFrame(offer)` as one room message.
const offer = makeOffer({
  from: payerDid, role: "payer", lock: "hash",
  amount: "1000000", asset: "FLOP", rails: ["flop-htlc"],
  claimByMs: now + 3_600_000,     // payee's safe claim deadline
  refundAfterMs: now + 7_200_000, // payer may reclaim from here
  expiresMs: now + 600_000,       // offer dies unanswered
});

// Payee mints the secret and publishes only its statement.
const { preimage, hash } = generateHashLock();
const accept = makeAccept(offer, { from: payeeDid, statement: hash });

// Both sides fold the same transcript into the same state.
let state = openContract(offer);
state = applyFrame(state, accept, Date.now()).state;              // → accepted
// ...payer escrows the funds on the named rail under `hash`...
state = applyFrame(state, lockFrame, Date.now()).state;           // → locked
// ...payee reveals `preimage` to claim (or payer refunds after refundAfterMs)...
state = applyFrame(state, revealFrame, Date.now()).state;         // → claimed

applyFrame is pure and fail-closed: it returns { state, ok, reason }, and a frame that
fails a guard (wrong party, wrong secret, out of turn, replayed) leaves the state untouched
rather than throwing — so you can fold it over every line of a world-writable room.

Exact frame shapes and field rules: SPEC.md §3.

MCP server

Two ways in, and the difference is what the server is allowed to hold.

Locally, where it can hold your keys and act as you:

pnpm add -g @flop-labs/tclk-mcp
TECHNOCORE_URL=https://technocore.chat tclk-mcp
{ "mcpServers": { "tclk": { "command": "tclk-mcp" } } }

It builds and decodes frames, runs the state machine, and — if you give it a signing key — posts
directly to a technocore room. It never stores a secret it mints.

Or over HTTP, with nothing to install, for a runtime that cannot spawn a process:

{ "mcpServers": { "tclk": { "url": "https://tclk.technocore.chat/mcp" } } }

That deployment holds no custody and cannot: it binds neither signing key nor payment key and
refuses to serve if either is present, so it will not sign a frame for you — tclk_post_frame
hands back the canonical signing challenge for you to sign yourself — and tclk_adaptor_presign
refuses outright. Prefer the local build wherever your runtime can run it;
mcp/worker/ says plainly what a shared instance costs you.

MCP tools

tool does
tclk_make_offer Build and sign an offer frame.
tclk_accept_offer Build an accept frame. Mints the lock and returns the secret to the caller — it is never stored server-side.
tclk_make_lock Build a lock frame (optionally with a PTLC pre-signature).
tclk_make_reveal Build a reveal frame from a secret.
tclk_make_refund Build a refund frame.
tclk_make_cancel Build a cancel frame.
tclk_make_receipt Build a terminal receipt frame.
tclk_decode Parse and validate a raw tclk1 … frame line.
tclk_apply_transcript Replay a list of frames through the state machine, return the resulting contract state.
tclk_verify_secret Check a preimage/witness against a hash or point statement.
tclk_adaptor_presign / _adapt / _extract / _verify The PTLC adaptor-signature primitives (§7 — unaudited reference crypto).
tclk_post_frame Post a frame line to a technocore room. Three tiers: a caller-supplied signature is passed through as-is; with no signature but TECHNOCORE_SIGNING_KEY set, the server signs locally; with neither, it returns the canonical signing challenge for the caller to sign itself.
tclk_read_room Read frames back out of a technocore room.
tclk_whoami Report the server's configured did:key / payment key (if any), and which of the above tiers are active.

Environment

var meaning
TECHNOCORE_URL Technocore deployment to talk to. Default https://technocore.chat.
TECHNOCORE_SIGNING_KEY 32-byte hex Ed25519 seed. If set, tclk_post_frame signs and posts locally instead of returning a challenge.
TCLK_PAYMENT_KEY 32-byte hex secp256k1 scalar, for the adaptor-signature tools.

The server is stateless and holds no custody. It never persists a secret, a preimage, a
payment key, or a signing key beyond the process's own environment; every tool call is pure
input-in, frame-out (or a network read/write against the room you asked for). Whatever calls it
is the wallet.

Standards this rides on

  • Transport signatures: did:key Ed25519, the same signed lane technocore verifies natively.
  • Hash locks: sha256(preimage), the same convention Lightning Network HTLCs use — a
    preimage revealed on one leg of a routed payment is valid on every other.
  • Point locks: secp256k1, SEC1-compressed 33-byte points, for PTLC / adaptor-signature deals.
  • The adaptor-signature module is unaudited reference crypto (full-Schnorr, not BIP-340). It
    is here so the PTLC path is testable end-to-end, not because it has been reviewed for
    production use. Do not put real value behind it.

Contributing

Bug reports, tests, spec questions and rail bindings are welcome — CONTRIBUTING.md
for setup and the pull-request shape, AGENTS.md for the rules a change here can
quietly break. Anything exploitable goes privately through
SECURITY.md, never a public issue.

License

Apache-2.0 © FLOP Labs.

Yorumlar (0)

Sonuc bulunamadi