DEV Community

razashariff
razashariff

Posted on

We Sent a Cryptographically-Signed AI Agent Payment Over 868 MHz Radio. No Internet. No Cloud. Just Trust.

We Sent a Cryptographically-Signed AI Agent Payment Over 868 MHz Radio. No Internet. No Cloud. Just Trust.

By Raza Sharif, CEO/Founder | contact@agentsign.dev


Airplane mode. Two Heltec LoRa boards. A signed MCPS frame crossed 868 MHz radio and settled in under 2 seconds.

No internet. No Lightning node. No cloud infrastructure. No blockchain.

Just a cryptographic signature, a nonce, and a trust level — travelling at the speed of radio.

This is what happened, how we built it, and why it matters for every AI agent you are shipping right now.


The Problem Nobody Is Talking About

MCP (Model Context Protocol) has 97 million SDK downloads. Over 13,000 servers are publicly listed. It is the fastest-growing AI integration standard in history.

It shipped with no message signing.

Not "limited signing." Not "optional signing." Zero. Any process on the network can forge a tool call. Any captured frame can be replayed indefinitely. A server has no cryptographic way to verify the agent calling it is who it claims to be.

Here is what a standard MCP tool call looks like on the wire today:

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "transfer",
    "arguments": { "to": "agent_b", "amount": 1000 }
  }
}
Enter fullscreen mode Exit fullscreen mode

No signature. No nonce. No identity. If you capture that frame, you can replay it forever.

OWASP confirmed prompt injection, tool poisoning, and authentication bypass as the top three MCP threats — all exploitable on standard implementations today. Gartner reported a 1,700% increase in agent security enquiries in 2026. The industry is waking up to a problem that was baked in from day one.

We built the security model for secure MCP use.


MCPS — Model Context Protocol Security

MCPS is an IETF internet draft that adds cryptographic signing to every MCP message. ECDSA P-256. Per-message nonces. Timestamp validation. L0–L4 trust levels. Drop-in compatible with the existing MCP spec.

Every MCPS frame looks like this:

MCPS:1:<agentHash>:<serverHash>:<amountHex>:<nonce>:<timestamp>:<P256sig>:<memo>

Example:
MCPS:1:a3f8c2d1:b7e94a20:0x03E8:a1b2c3d4:1746543210:MEQCIHx9...==:transfer
       ↑version ↑agent    ↑server ↑amount  ↑nonce    ↑unix ts  ↑sig44     ↑memo
Enter fullscreen mode Exit fullscreen mode

The server verifies the signature before executing anything. The nonce is stored and rejected if seen again. The trust level gates what the agent is permitted to do.

Seven npm packages. A Java Keycloak mapper. Python and Go implementations. The x-agent-trust extension is now on the official OpenAPI extension registry — PR #67, merged April 2026, approved by Microsoft and the OpenAPI TDC.

That is the protocol. Now here is what we did with it.


The Build: MCPS Over 868 MHz LoRa Radio

We wanted to know: how transport-agnostic is MCPS really?

So we stripped away every assumption. No TCP/IP. No Wi-Fi. No internet. We put the phone into airplane mode and routed an MCPS payment frame across a 868 MHz LoRa radio mesh.

Hardware

Two Heltec WiFi LoRa 32 V3 boards running Meshtastic firmware:

  • c758 — TX board. Paired with an iPhone via BLE. Receives MCPS frames from our iOS app and transmits over 868 MHz LoRa.
  • 84cc — RX board. Paired with a Mac via BLE. Receives incoming LoRa frames and forwards to the lnode-mesh backend.

Architecture

┌─────────────────────────────────────────────────────────┐
│  iPhone (Airplane Mode)                                 │
│  iOS App — signs MCPS frame — sends via BLE             │
└────────────────────────┬────────────────────────────────┘
                         │ BLE
                         ▼
┌─────────────────────────────────────────────────────────┐
│  Heltec c758 — TX Board                                 │
│  Transmits over 868 MHz LoRa                            │
└────────────────────────┬────────────────────────────────┘
                         │ 868 MHz LoRa (radio)
                         ▼
┌─────────────────────────────────────────────────────────┐
│  Heltec 84cc — RX Board                                 │
│  Receives over 868 MHz LoRa                             │
└────────────────────────┬────────────────────────────────┘
                         │ BLE
                         ▼
┌─────────────────────────────────────────────────────────┐
│  Mac — ble-listener.py                                  │
│  Meshtastic protobuf decode → POST /radio/receive       │
└────────────────────────┬────────────────────────────────┘
                         │ HTTP localhost
                         ▼
┌─────────────────────────────────────────────────────────┐
│  lnode-mesh.js — Node.js backend                        │
│  Verify MCPS sig → check nonce → update balances        │
│  SETTLED ✓                                              │
└─────────────────────────────────────────────────────────┘

Zero internet in the chain. Phone in airplane mode throughout.
Enter fullscreen mode Exit fullscreen mode

The iOS App

The app builds a valid MCPS frame, signs it with ECDSA P-256, and sends it to the c758 board via BLE using the Meshtastic TORADIO characteristic. The key part was getting the Meshtastic 2.x protobuf encoding right — specifically FIXED32 wire type for the broadcast destination address (0xFFFFFFFF) and the correct field numbers for ToRadio.

// MeshtasticBLE.swift — encode broadcast destination correctly
private func encodeFixed32(fieldNumber: Int, value: UInt32) -> Data {
    var data = Data()
    data.append(UInt8((fieldNumber << 3) | 5)) // wire type 5 = 32-bit fixed
    data.append(UInt8(value & 0xFF))
    data.append(UInt8((value >> 8) & 0xFF))
    data.append(UInt8((value >> 16) & 0xFF))
    data.append(UInt8((value >> 24) & 0xFF))
    return data
}
Enter fullscreen mode Exit fullscreen mode

The BLE Listener

ble-listener.py runs on the Mac, connects to the 84cc board via BLE, decodes the Meshtastic protobuf FromRadio stream, extracts text messages, and POSTs any MCPS frame to the settlement backend.

# ble-listener.py — detect and forward MCPS frames
if text.startswith("MCPS:"):
    result = post_to_backend(text, rssi=pkt.rx_rssi, snr=pkt.rx_snr)
    verdict = result.get("verdict", "?")
    # → SETTLED ✓
Enter fullscreen mode Exit fullscreen mode

The Settlement Backend

lnode-mesh.js receives the frame, verifies the ECDSA signature, checks the nonce against a replay store, validates the trust level, and updates agent balances. It is the same MCPS settlement logic that runs in our cloud stack — unmodified — now running over radio.


The Moment It Worked

  ╔══════════════════════════════════════════════╗
  ║  MCPS PAYMENT RECEIVED OVER 868 MHz RADIO    ║
  ╠══════════════════════════════════════════════╣
  ║  Frame: MCPS:1:a3f8c2:b7e94a:0x03E8:a1b2..   ║
  ║  RSSI:  -7 dBm                               ║
  ║  SNR:   6.5 dB                               ║
  ╠══════════════════════════════════════════════╣
  ║  Verdict: SETTLED ✓                          ║
  ║  agent_a: 9000 sats                          ║
  ║  agent_b: 11000 sats                         ║
  ╚══════════════════════════════════════════════╝
Enter fullscreen mode Exit fullscreen mode

Phone in airplane mode. No Wi-Fi. No mobile data. No internet anywhere in the chain.

RSSI -7 dBm. SNR 6.5 dB. Clean signal. Clean settlement.

First MCPS-signed agent transaction over radio. Done.


Why This Matters Beyond the Demo

We are not trying to build Stripe over LoRa. That is not the point.

The point is this: MCPS is transport-agnostic. The signing, the nonce, the trust level — they live in the frame, not in the network. HTTP, WebSocket, stdio, gRPC, BLE, 868 MHz radio — it does not matter. The trust travels with the data.

That has real consequences:

1. Disconnected environments
Agents operating in disaster zones, remote industrial sites, or air-gapped networks can still execute cryptographically-attributed transactions. When connectivity returns, settlement syncs. The signed log is the audit trail.

2. Incentivised mesh routing
Every relay hop can earn a signed micro-credit. Pay-per-forward with cryptographic receipt. No internet required for accounting — only for final settlement.

3. IoT and sensor data markets
Remote sensors publish data over mesh. Agents subscribe and pay. Deferred settlement when they reconnect. Metered access with a tamper-proof ledger.

4. The real insight for cloud deployments
If MCPS works on a 250 bps radio link in airplane mode, it works in your Kubernetes cluster. It works in your CI pipeline. It works in your agentic commerce stack. If the most constrained transport you can imagine handles it, your infrastructure certainly can.

Protocol-agnostic trust was always the goal. Radio just proved it.


The Broader Stack

lnode-mesh is one piece. The full picture:

Layer Component What it does
Identity AgentPass Agent registry, trust scoring L0–L4, AML/sanctions screening (75K+ entries)
Signing MCPS ECDSA P-256 per-message signing, nonce replay protection, IETF draft
Transport ATTP Agent Trust Transport Protocol — 5 protocol bindings, IETF draft
Scanning CyberSecClaw One import, secure-by-default agents. Identity, injection blocking, audit trail
Marketplace LATTP Find, scan, and pay for verified MCP services. DAST on every call
DAST Cybersecify 25+ OWASP MCP checks, active exploitation probes, CI/CD integration

All of it runs over any transport. Including radio.


Standards

This work is not a side project. It is submitted, published, and independently citable:


Get the Code

The lnode-mesh stack (iOS app + BLE listener + settlement backend) is private. If you are working on:

  • Agent infrastructure for disconnected environments
  • Incentivised mesh networking
  • Air-gapped payment resilience
  • MCPS integration for your platform

Reach out directly: contact@agentsign.dev

npm packages (public): mcps-core, agentpass, agentsign, mcps-openclaw, mcp-secure

npm install mcps-core agentpass
Enter fullscreen mode Exit fullscreen mode

Bottom Line

We built agents that transact over crypto. Then we added radio.

Not because it was easy. Because it proved the thing that matters: trust is a property of the message, not the network.

Sign it. Verify it. Settle it. Anywhere.


Raza Sharif — CEO/Founder]
*CyberSecAI Ltd | contact@agentsign.dev | Patent Pending

Top comments (0)