Codync
A free, open-source 1:1 alternative to Grok Bot and Muse. Message Claude Code, Codex, Cursor and 40+ coding agents as persistent bots from your iPhone, Mac or Linux desktop. Group chats, threads, appr
Read Mezo and pay for it in MUSD with no BTC for gas: a lens contract, an MCP server and an x402 pay-per-call endpoint, running on Mezo testnet.
Developer toolsTypeScript · JavaScriptGitHub @Kylne700OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Let an AI agent read Mezo and pay for those reads in MUSD, with no BTC for gas.
Taken from the repository README
Loading the full README.
Read the full README ↗Let an AI agent read Mezo and pay for those reads in MUSD, with no BTC for gas.
Built for the Mezo Buildathon on Akindo, Wave 1 (build period 16-26 October 2026), Track 2: Access and Distribution. First commit 2026-10-18. Mezo testnet only.
Who it is for: developers who give an AI agent a Mezo wallet, MUSD borrowers who ask an agent where their trove ranks for redemption, and teams that sell Mezo reads over HTTP with their own payee and price. Some coding is needed (one MCP config entry, or a Worker deploy). Desktop and terminal first; the console also works on a phone (checked at 390 and 320 px wide). The toolkit itself has no region checks.
Live demo: https://mezo-agent-toolkit.kylne700.workers.dev
Check it in a minute (no key, no funds): npm ci, then npm run smoke (about 40 s; 23 checks: every lens answer equals a direct read of the protocol at one pinned block, and an unpaid call to the endpoint gets a 402; it ends with SMOKE PASSED). To see it first: the demo video, the deck and the live console.
Built by Kylne700 with AI coding agents (Claude Code): a lead session plans, reviews and checks; sub-agents write the code.
Three parts, all on Mezo testnet (chain 31611):
MezoLens, a read-only contract that answers the questions an agent actually asks about Mezo in one eth_call each: how healthy is this MUSD trove, where does it stand in the redemption queue, what does this swap quote and cost in price impact, which veBTC / veMEZO locks does this wallet hold.npm run serve) that serves those reads for 0.001 MUSD per call using x402 through a third-party facilitator (facilitator.vativ.io), which settles on Mezo. The buyer signs a permit; the facilitator sends the transaction and pays the BTC gas. The same app is also packaged as a Cloudflare Worker with a console page; it is deployed (see Live), and Deploy your own shows how to run your own.npm run mcp, stdio) with five tools: trove_health, redemption_risk, pool_quote, ve_locks and pay_and_fetch. pay_and_fetch pays x402 servers in MUSD under hard spend limits that the operator sets in the server's environment and that no tool call can change.Everything below was run for real on testnet. The logs are in evidence/.
| Criterion | Where to look |
|---|---|
| Mezo Integration | Mezo integration: contract, address, call, why: the ten contracts in the table, with the calls used and why. Transactions: 18 testnet transactions in one table, each linked to the explorer. |
| Product and Business Viability | Deck slides 1, 9 and 10 (the problem, who pays, Wave 2) and Limits, stated plainly. |
| Technical Implementation | How the numbers were checked: the tests, a smoke run against the chain, an MCP session and a Worker smoke. CI runs the typecheck, the tests and the repo checks on every push. |
| User Experience | The live console and console-qa.log (51 checks: light and dark at 1280 and 390 px, light at 320 px, focus rings, no sideways overflow). |
| Submission Materials | The demo video (1:33) and the deck (11 slides). |
All addresses are Mezo testnet and have code on chain (checked by the smoke test).
| Contract | Address | What the toolkit calls | Why |
|---|---|---|---|
| MezoLens (ours, source verified on the explorer, MIT) | 0xBDfD1C0B544319E25b4b99ee1f355e55230f6130 | troveHealth, systemSnapshot, redemptionQueue(borrower, cursor, maxSteps), poolQuote, veLocks | One consistent read per question instead of many RPC round trips; the redemption queue is walked on chain, up to 300 nodes per call, in pages with a cursor |
| MUSD token | 0x118917a40FAF1CD7a13dB0Ef56C86De7973Ac503 | The x402 payment asset: the buyer signs an EIP-2612 permit for exactly the price; the settlement transaction emits Approval and Transfer buyer to payee. balanceOf in the gate and session scripts | MUSD is both the unit the reads are priced in and what the agent pays with, and the agent spends no BTC: in the paid runs its BTC balance did not change |
| x402 Permit2 proxy | 0x402085c248EeA27D92E8b30b2C58ed07f9E20001 | Target of every settlement transaction (sent by the facilitator, not by the buyer) | This is how a payment is settled on chain; the toolkit checks it on the explorer for each payment |
| TroveManager | 0xE47c80e8c23f6B4A1aE41c34837a0599D5D16bb0 | getTroveStatus, getEntireDebtAndColl, MCR, CCR, getTCR, getEntireSystemColl, getEntireSystemDebt, checkRecoveryMode | Trove ratio, debt, liquidation price, system ratio, recovery mode |
| SortedTroves |
Also used: Mezo's native BTC and MEZO ERC-20 precompiles (0x7b7C…0000, 0x7b7C…0001) as token addresses in pool quotes, the Mezo testnet RPC https://rpc.test.mezo.org and the third-party x402 facilitator https://facilitator.vativ.io/supported.
| What | Transaction |
|---|---|
| Lens deployed (block 16229406, 10651 bytes of code) | 0x4c673819…821dd1 |
| BTC to MUSD swap on the Mezo DEX, to fund the buyer (0.0002 BTC for 15.74 MUSD) | 0xe43a7aaf…c5be |
| First paid call settled through the facilitator (the day-one gate, log) | 0x1499eccd…7b9d |
402 then 200 on all four paid routes (evidence/gate-402-then-200.log) | 0xb2063d3a…2aa8, 0x2697a4f4…6a9c, 0x21e1ec30…81ea, 0x591aa181…6b18 |
Two payments made by an AI-agent tool call over MCP (evidence/mcp-session.log) | , |
In every settlement the explorer shows the transaction sent by the facilitator to the x402 proxy, one MUSD Transfer of exactly 0.001 MUSD from the buyer to the payee, and a buyer BTC balance and nonce that did not change.
trove_health for the tail of the redemption queue (block 16230202):
Trove is below the 110% minimum ratio (109.73%) and can be liquidated.
Every answer carries the block it was read at, exact integers under raw (big ones as strings), and readable numbers that are cut off, never rounded. redemption_risk answers: how many redeemable troves and how much MUSD stand in front of this trove, how many below-minimum troves a redemption skips, which trove would be hit first, and whether the walk finished or hit the step cap.
The Worker on Cloudflare, Mezo testnet only: https://mezo-agent-toolkit.kylne700.workers.dev
It was deployed on 2026-10-19 and checked there with npm run worker:smoke -- --url https://mezo-agent-toolkit.kylne700.workers.dev (results under How the numbers were checked). To run the same Worker on your machine instead, npm run dev serves it at http://127.0.0.1:8787.
https://mezo-agent-toolkit.kylne700.workers.dev/ is the console page: what this is, the network, the price of one call in MUSD, the payee and the lens with explorer links, a curl that prints the live 402 challenge, an MCP configuration for pay_and_fetch, and the latest paid calls, read from the chain.https://mezo-agent-toolkit.kylne700.workers.dev/v1/trove/<address> (also /v1/redemption/<address>, /v1/ve/<address> and /v1/pool/quote) is the paid API. Without a payment it answers 402 and the x402 challenge; with one, 200 and the data.https://mezo-agent-toolkit.kylne700.workers.dev/status is the price, the payee and the last settlement that Worker instance saw, as JSON. https://mezo-agent-toolkit.kylne700.workers.dev/api/payments is the recent payments to the payee, as JSON, read from the chain and kept for 45 seconds.The same challenge from a terminal:
curl -si https://mezo-agent-toolkit.kylne700.workers.dev/v1/trove/0xDA04759E54728B6636Fe48F7c9795c7B609bAaAa | grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 -d
The live host is already on the default allow list of pay_and_fetch (LIVE_HOSTS in src/mcp-env.ts), so an agent host that gives the MCP server a funded key file can pay it with no further setting. For a Worker of your own, list its host first (step 5 of Deploy your own).
Needs Node 22.12 or newer (22, 24 or 26). Reading needs no key and no funds.
npm ci
npm test # 173 unit and contract tests, offline
npm run smoke # live, read-only: the lens against direct reads of the protocol, plus the unpaid 402 challenge
npm run serve # the pay-per-call endpoint on 127.0.0.1:8402 (PORT, HOST, PAYEE_ADDRESS)
npm run dev # the same endpoint plus the console page, as a Cloudflare Worker on 127.0.0.1:8787, through wrangler dev (no login, no deploy)
npm run mcp # the MCP server on stdio
PAYEE_ADDRESS is where payments go; the default is a throwaway testnet address.
Add it to the host's MCP configuration with the repository as the working directory (shown as JSON; the exact file depends on the host):
{
"mcpServers": {
"mezo": {
"command": "node",
"args": ["--import", "tsx", "src/mcp.ts"],
"cwd": "/path/to/mezo-agent-toolkit",
"env": {
"MEZO_KEY_FILE": "/path/to/funded-testnet.key",
"MEZO_MAX_PER_CALL_MUSD": "0.01",
"MEZO_MAX_PER_SESSION_MUSD": "0.1",
"MEZO_PAY_ALLOWED_HOSTS": "mezo-agent-toolkit.kylne700.workers.dev"
}
}
}
}
The four read tools work with no environment at all. pay_and_fetch is off unless MEZO_KEY_FILE names a file with a funded Mezo testnet key (64 hex characters, the server reads it itself and never prints it). Limits default to 0.01 MUSD per call and 0.1 MUSD per session; a value that does not parse switches payments off instead of falling back. MEZO_PAY_ALLOWED_HOSTS is a comma-separated list of the only hosts the tool may call (host means any port, host:port that port only). Unset or blank, it is 127.0.0.1:8402,localhost:8402 (our own endpoint as npm run serve starts it) plus mezo-agent-toolkit.kylne700.workers.dev (the live Worker, from the LIVE_HOSTS list in src/mcp-env.ts), and nothing else. Add a seller's host to pay it. A Worker of your own: its host (host only, no https://) goes into the LIVE_HOSTS list or into MEZO_PAY_ALLOWED_HOSTS; a test covers the LIVE_HOSTS line, the environment variable is what the Worker smoke uses to pay (it lists the host of the Worker it checks, for example 127.0.0.1:8787), and the console page's MCP snippet already names the host it is served from.
These need MEZO_KEY_FILE pointing at a funded Mezo testnet key (the faucet gives testnet BTC; scripts/swap.ts swaps some of it for MUSD).
npm run gate # 402 then 200 on the four paid routes, four payments of 0.001 MUSD
npm run mcp:session # the real stdio server, every tool, two payments of 0.001 MUSD
npm run worker:smoke # starts the Worker with wrangler dev, checks it, pays it once (0.001 MUSD) and rewrites evidence/worker-smoke.log; add `-- --no-pay` to pay nothing and write no log (it still reads the key file), or `-- --url <address>` to check a Worker that is already running, such as the deployed one (it starts nothing and writes no log)
The lens itself was deployed with npx tsx scripts/deploy.ts after npm run build:contracts (it needs the funded key above and refuses to deploy again when the recorded address still has code; --force overrides). Its source was verified on the explorer with npx tsx scripts/verify.ts, which needs no key. Neither has an npm script.
You need a free Cloudflare account. The Worker holds no secret, only the payee's address. wrangler is not a dependency of this repository (it would add LGPL image libraries, which npm run check:licences rejects); npm run dev and npm run deploy run [email protected] through npx --yes, which downloads it on first use.
npm cinpx --yes [email protected] login and sign in to Cloudflare in the browser.wrangler.toml, set PAYEE_ADDRESS to your own testnet address to receive the payments (the default is a throwaway one). PRICE, RPC_URL and FACILITATOR_URL are in the same [vars] block.npm run deploy publishes the Worker mezo-agent-toolkit and prints its address, which looks like https://mezo-agent-toolkit.<your-subdomain>.workers.dev. Open it and check that <address>/status answers with JSON.LIVE_HOSTS in src/mcp-env.ts, or to MEZO_PAY_ALLOWED_HOSTS in the MCP server's environment.402 and an x402 v2 challenge: scheme exact, network eip155:31611, asset MUSD, amount 0.001 MUSD, with the EIP-2612 gas-sponsoring extension. Bad input gets 400 before any challenge, so nobody is asked to pay for a request that cannot succeed.pay_and_fetch makes a plain request first, and only if the server answers 402 does it sign a payment for the quoted amount. The permit it signs is for exactly that amount.url and nothing else, and its description tells the model the limits.pay_and_fetch then does not pay for that URL again until the chain shows the payment can no longer land: its Permit2 nonce still unused 90 seconds after its deadline, which is at most 300 seconds after signing. If the nonce was used, the payment landed and the seller did not deliver: that URL stays refused for the rest of the session, and the payment is lost (paid but empty). Our own server tries to prevent that case by finding the settlement on chain itself (below).Mezo's public RPC sometimes answers eth_getTransactionReceipt for a mined transaction with null or "method handler crashed". When that happens the facilitator reports success:false, unexpected_error and an empty transaction hash, although the transfer landed. In testing, between none and all four of the settlements in a run were hit, differing from run to run. Two payments of 0.001 MUSD were lost this way before the fix existed (0x51d022f4…12d0f8 and 0x4394ca66…062de13: the buyer paid and got a failure). Two more were lost in the payment review's first two live runs (evidence/mcp-session-review-1-run1.log, evidence/mcp-session-review-1-run2.log; the passing run after the fix: evidence/mcp-session-review-1-final.log), because the server's own check also read the transaction by hash: 0x9468a2af…b80d (the facilitator reported the receipt error) and 0x3b69ac81…74ee (the facilitator reported success). Read-only probes right after found the RPC answering null by hash, for the transaction and its receipt, for every transaction checked (both of run 2's payments among them), in checks minutes apart, while reads by block and index answered at once (evidence/rpc-by-hash-probe.log).
The paid endpoint asks the chain itself about every settlement, whatever the facilitator reports: it looks for a MUSD Transfer from the payer to the payee, of exactly the quoted amount, inside a transaction whose calldata contains this payment's own signature, and each transaction can vouch for one payment only. A reported success serves the data only when this finds the payment, so the facilitator's word alone is never enough. A reported failure is overruled when it finds the payment: the call succeeds, and the status page and the logs say the settlement was recovered from the chain. It reads that transaction by block and index, never by hash (above). If the payment is not found after seven looks two seconds apart (about 18 seconds), the buyer gets 402 and no data; if it had landed after all, that buyer has paid and got nothing, there is no refund, and pay_and_fetch does not pay for that URL again (above). The mechanism is covered by offline tests (test/app.test.ts: the payment is on chain and is this one; no transfer; an earlier payment of the same size; the wrong amount; one transaction vouching twice, also from two recoveries at once; an unreadable chain; a reported success the chain does not show; an RPC whose by-hash lookups answer nothing; a node that shows the transfer only from the fourth look; one search per settlement). Live: the final code's session (evidence/mcp-session-review-1-final.log) checked both settlements on chain after the facilitator reported success; the two runs before the last fix are kept as run1 and run2. Overruling a reported failure has not happened live on the final code; a read-only replay of the final recovery code against the real chain found the run2 payment in about one second.
| Check | Result (committed evidence) |
|---|---|
npm test | 173 tests in 10 files: the lens contract against mock Mezo contracts in an in-process EVM (including the paged redemption walk), the spend guard, the buyer against a stub facilitator, the HTTP app, the MCP server over stdio, the Worker (its entry file, its settings, the console page with its security headers, the recent-payments reader and the allowed-host list), and negative tests that plant a fake key, a fake denylist term, a home path, an email and bad licences and expect the three repo checks to fail |
npm run smoke | 23 checks passed (evidence/smoke.log). At one pinned block, the lens's trove health (two troves), system snapshot, redemption queue (one call, paged two nodes per call, and stopped by the step cap), three pool quotes (one with 7.05% price impact) and a live veBTC lock equal reads taken straight from TroveManager, SortedTroves, PriceFeed, HintHelpers, the router and veBTC/veMEZO, field by field, and the shown text equals the exact value cut off. Mutating the comparison code made them fail. It also checks that every address in the table above has code on chain and is one the code uses, and that every transaction this README links succeeded on the explorer (11 when the committed log was taken; the README links more now and the script checks whatever it finds) |
| x402 gate | 402 then 200 on all four paid routes, four settlements confirmed (evidence/gate-402-then-200.log) |
npm run mcp:session | 29 checks passed (evidence/mcp-session.log): the five tools are listed, pay_and_fetch takes only a url, every read answer equals direct reads at the block it names, two payments settle (explorer confirms status, block, sender, token transfer), a $0.05 price is refused against a 0.002 MUSD limit, a third payment is refused by the session limit with the facilitator never asked, a host outside the allow list and a bad URL are refused, a free URL is fetched without paying, the buyer's MUSD fell by exactly 0.002 while its BTC balance and nonce did not move, the server process exited, and no answer or log line contained the key, its path or a home path. After the payment review the same 29 checks passed on the final code () |
facilitator.vativ.io). If it is down, paid calls fail; the free read tools do not depend on it. Its receipt flake is described above.pay_and_fetch; this keeps reads usable with no wallet, and shows paying in MUSD where an agent needs to buy data from someone else.pay_and_fetch calls only the hosts on its allow list, by default our local endpoint and the live Worker, and it only ever pays MUSD on Mezo testnet. Listing a bare host such as 127.0.0.1 opens every port on it to a plain GET.raw is exact./status shows, are kept in the running instance, and Cloudflare decides how many instances run and when one is replaced. Another instance does not know them: a payment sent at the same moment to two instances could be served twice (the answers are public chain data), and /status can show a different last settlement or none. On the deployed Worker /status did not show the payment just made in 2 of the 4 paid runs of 2026-10-19; a payment served twice by two instances was not tested./, /api/payments and the favicon asks the facilitator what it supports before it answers (the x402 library does that when the app is built). If the facilitator is down they answer 502 and say so; the console page and the payments list still work./api/payments reads the public RPC. At most one scan per 45 seconds per instance; if the RPC fails, the last good answer is served and marked stale. A scan goes back at most 114,000 blocks (12 windows of 9,500, because the RPC refuses queries over 10,000 blocks), roughly five and a half to six days depending on the block time, and the page says which blocks it covered. An older payment is not listed.The code in this repository was written for it, with one exception: the video scripts in scripts/video start from the author's own MIT-licensed Sealdrop video chain (github.com/Kylne700/sealdrop). lib.mjs and listen.py are copied; config.mjs, tts.mjs, narration.mjs and asr-compare.mjs are adapted (the first lines of each file say so). The other video scripts (take.ts, record-live.mjs, scenes.mjs, assemble.mjs, post.mjs, build.sh) and scripts/deck/build.mjs were written for this repository.
Assets: docs/fonts/ holds Inter and JetBrains Mono (SIL Open Font License 1.1, the licence texts sit next to the files); the deck and the video use them. The video's synthetic voice is Kokoro, run from a folder outside this repository, and its files are not included. The code depends on the packages in package.json (viem, hono, zod, the MCP SDK and the x402 packages, MIT or Apache-2.0).
MIT, see LICENSE. Dependency licences are checked by npm run check:licences.
0x722E4D24FD6Ff8b0AC679450F3D91294607268fA |
getLast, getPrev, getSize, contains |
| The redemption order: a redemption starts at the tail, so the walk goes from the tail towards the borrower |
| PriceFeed | 0x86bCF0841622a5dAC14A313a15f96A95421b9366 | fetchPrice | BTC/USD price for every ratio and liquidation price |
| Pool router (Mezo DEX) | 0x9a1ff7FE3a0F69959A3fBa1F1e5ee18e1A9CD7E9 | defaultFactory, poolFor, getReserves, getAmountsOut | Swap quote and price impact (a probe at 1% of the amount against the full amount) |
| veBTC | 0xB63fcCd03521Cf21907627bd7fA465C129479231 | balanceOf, ownerToNFTokenIdList, locked, balanceOfNFT, voted | Locks of a wallet: amount, unlock time, voting power, whether it has voted |
| veMEZO | 0xaCE816CA2bcc9b12C59799dcC5A959Fb9b98111b | balanceOf, ownerToNFTokenIdList, locked, votingPowerOfNFT, voted | Same, for veMEZO |
| HintHelpers | 0x4e4cBA3779d56386ED43631b4dCD6d8EacEcBCF6 | getRedemptionHints, in the verification scripts only | An independent answer to "which trove would a redemption hit first", to compare with the lens |
0x7b35e64c…0fcbThe same two payments on the code after the payment review (evidence/mcp-session-review-1-final.log) | 0xb15e02af…9119, 0x1113ccc1…b1c9 |
Two payments to the Worker running under wrangler dev, made by pay_and_fetch (evidence/worker-smoke-run1.log, evidence/worker-smoke.log) | 0xaad142ca…84b1, 0x779df435…d4d8 |
Two payments to the Worker deployed on Cloudflare, made by npm run worker:smoke -- --url on 2026-10-19 (attached runs write no log) | 0x9c246dc4…b50cd2, 0xcd77cf7b…8f7f6f |
Two payments to the deployed Worker in the video take of 2026-10-19, by a plain x402 buyer and by pay_and_fetch (evidence/video-take-2026-10-19.log) | 0x72589fc2…085a9a, 0x74482a3e…675404 |
| One more payment to the deployed Worker, from a smoke run after the take | 0xbf2c843a…a0ff8e |
npm run worker:smoke | 28 checks passed against the Worker under wrangler dev (evidence/worker-smoke.log; the first paid run, with an earlier console page, also passed 28: evidence/worker-smoke-run1.log): the console page (a CSP that allows only its own inline script and style, nothing loaded from outside, the price, payee and lens as /status reports them, and the curl line on the page prints the same challenge); /status; /api/payments (10 payments read from the chain, the second call answered from the cache); the 402 challenge (x402 v2, 0.001 MUSD to the payee, gas sponsoring); a bad address gets 400 before any challenge and a malformed payment header gets 402. Through the MCP server (limits 0.01 per call, 0.1 in total, only 127.0.0.1:8787 allowed) localhost:8787 is refused and no MUSD moves, then one pay_and_fetch pays 0.001 MUSD and returns the trove health that was asked for. The buyer's MUSD fell by exactly 0.001 and the payee's rose by exactly that, the buyer sent no transaction, the explorer confirms the settlement, /status and /api/payments show it, and nothing the MCP server or the Worker printed contains the key. Against the Worker deployed on Cloudflare (-- --url, 2026-10-19; attached runs write no log, so the settlements in the table above are the record): 18 checks passed without payment, and 25 passed in each of two runs that paid 0.001 MUSD. The first paid run failed its /status check because another Worker instance answered, although its payment had settled; the script now reports that case as not checked on a deployed Worker |
| Console page in a browser | 51 checks passed (evidence/console-qa.log; scripts/console-qa.mjs, headless Chromium, run by hand because playwright-core and axe-core are not dependencies): light and dark at 1280 px and 390 px, and light at 320 px. The page's own script runs under its CSP and an injected script does not; nothing is requested from outside; no console error; no sideways overflow; axe-core 4.14.0 finds 0 violations; Tab reaches every focusable element once with a focus ring of at least 2 px and 3:1 contrast; every link is at least 44 x 44 px. A script cannot judge how the page looks: the screenshots were looked at by hand and are not kept in the repository |
npm run check | no key value anywhere git could publish it (working tree, index and all history), no GPL, LGPL or AGPL package (the one weak-copyleft licence, MPL-2.0, appears only in dev tools), and the privacy denylist, home path and email scan are clean over every committed and evidence file |
wrangler deploy --dry-run reports a bundle of 2.66 MiB (0.48 MiB compressed).evidence/video-take-2026-10-18.log), 0.002 in two smoke runs against the deployed Worker, 0.002 in the two payments of the video take of 2026-10-19 (evidence/video-take-2026-10-19.log) and 0.001 in a third smoke run against it. Payments made after 2026-10-19 are not in this total; the console lists the latest ones.