
Security News
Ruby's Bundler 4.0.18 Extends Cooldown to bundle lock and bundle cache
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
@relayos/mcp-paywall
Advanced tools
Zero-friction x402 RLUSD payment layer for Model Context Protocol tools
Add pay-per-call RLUSD micropayments to any MCP tool server in one line of code.
npm i @relayos/mcp-paywall
Requires Node >= 22. Peer deps: @modelcontextprotocol/sdk >= 1.0.0, zod >= 3.0.0.
Wrap your existing MCP tool handler with paywall(). That's it. No payment infra to run.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { paywall, paywallSchema } from "@relayos/mcp-paywall";
import { z } from "zod";
const server = new McpServer({ name: "my-data-server", version: "1.0.0" });
server.tool(
"fetch-prices",
"Fetches proprietary price data",
paywallSchema({ symbol: z.string() }),
paywall(
{
priceRlusd: 0.10, // $0.10 RLUSD per call
recipient: "rYourXRPLAddress",
network: "xrpl_mainnet",
},
async ({ symbol }) => ({
content: [{ type: "text", text: JSON.stringify(await getPrices(symbol)) }],
})
)
);
paywallSchema(shape) — extends your Zod shape with the optional _relay_payment field so MCP lets the proof throughpaywall(config, handler) — returns a drop-in replacement handler that enforces payment before executionOn the client side, agentWallet() intercepts 402 responses, signs an XRPL payment, and retries — transparently.
import { agentWallet } from "@relayos/mcp-paywall";
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
const mcp = new Client({ name: "my-agent", version: "1.0.0" });
// ... connect mcp to your transport
const wallet = agentWallet({
seed: process.env.AGENT_SEED!, // XRPL wallet seed — held in memory only
network: "xrpl_mainnet",
maxSpendPerCallRlusd: 1.0, // hard cap — never pays more than $1 per call
});
// Transparent auto-pay: call → 402 → sign → retry → result
const result = await wallet.callWithPayment(
(name, args) => mcp.callTool({ name, arguments: args }),
"fetch-prices",
{ symbol: "BTC" }
);
console.log(result.content[0].text);
The agent never pays more than maxSpendPerCallRlusd. If the server asks for more, the call throws before signing.
The 402 handshake follows the x402 protocol adapted for XRPL:
{ error: "PAYMENT_REQUIRED", code: 402, invoice: { priceRlusd, recipient, endpointId, expiresAt } } when no payment proof is presentAll verification happens locally on the server — no Relay API call required for the basic flow.
agentWallet() derives the XRPL address at construction time; the seed string is accessed only at signing time and never storedmaxSpendPerCallRlusd is enforced before any signing; mismatched invoices are rejected, not renegotiatedexpiresAt Unix timestamp; stale proofs are rejected on both sidespaywall() call creates an isolated replay store; multi-tool servers can't cross-contaminatepaywall(config, handler)Wraps an MCP tool handler behind an RLUSD paywall.
function paywall<P extends Record<string, unknown>>(
config: PaywallConfig,
handler: ToolHandler<Omit<P, "_relay_payment">>
): ToolHandler<P & { _relay_payment?: string }>
PaywallConfig
| Field | Type | Required | Description |
|---|---|---|---|
priceRlusd | number | yes | Price in RLUSD per tool call |
recipient | string | yes | XRPL classic address receiving payment |
network | "xrpl_mainnet" | "xrpl_testnet" | yes | XRPL network |
description | string | no | Human-readable description of what is being sold |
relayApiUrl | string | no | If set, submits the tx to Relay for on-chain settlement confirmation |
gracePeriodMs | number | no | Payment window in ms. Default: 300_000 (5 min) |
paywallSchema(shape)Extends any Zod raw shape with the optional _relay_payment field.
function paywallSchema<T extends ZodRawShape>(
shape: T
): T & { _relay_payment: ZodOptional<ZodString> }
Use this whenever you declare the tool schema so MCP passes the proof through instead of stripping it as an unknown field.
agentWallet(config)Creates an autonomous XRPL signing wallet for agent-side auto-pay.
function agentWallet(config: AgentWalletConfig): AgentWallet
AgentWalletConfig
| Field | Type | Required | Description |
|---|---|---|---|
seed | string | yes | XRPL wallet seed. Held in memory only — never logged or transmitted |
network | "xrpl_mainnet" | "xrpl_testnet" | yes | XRPL network |
maxSpendPerCallRlusd | number | yes | Hard cap per call — agent refuses to pay more than this |
relayApiUrl | string | no | Relay API base URL for server reputation checks before paying |
minServerReputationScore | number | no | Reject servers whose on-chain reputation is below this score |
AgentWallet
interface AgentWallet {
readonly address: string; // XRPL classic address of the agent
callWithPayment(
callTool: (name: string, args: Record<string, unknown>) => Promise<CallToolResult>,
toolName: string,
toolArgs: Record<string, unknown>
): Promise<CallToolResult>;
}
// The 402 challenge body returned by a paywalled tool
interface PaymentInvoice {
version: "1.0";
priceRlusd: number;
recipient: string; // XRPL classic address
network: Network;
endpointId: string; // Unique per paywall() registration — prevents cross-tool replays
expiresAt: number; // Unix timestamp
}
// Base64-encoded JSON: { scheme, network, payload: signed_tx_blob }
type PaymentProof = string;
type Network = "xrpl_mainnet" | "xrpl_testnet";
Additional exports: is402Response, extract402Invoice, buildInvoice, verifyPayment, createInMemoryReplayStore — see source for full signatures.
MIT — timwal78/squeezeos
FAQs
Zero-friction x402 RLUSD payment layer for Model Context Protocol tools
We found that @relayos/mcp-paywall demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.