verify402-mcp 1.0.6 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +17 -7
- package/index.mjs +12 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,13 +10,13 @@ dedicated hot wallet funded with **Base Sepolia testnet USDC** (`eip155:84532`).
|
|
|
10
10
|
The analysis reads mainnet chain data, but the demo never settles mainnet
|
|
11
11
|
payments. The bridge never signs or sends a trade.
|
|
12
12
|
|
|
13
|
-
> **Published package note:** `verify402-mcp@1.0.
|
|
13
|
+
> **Published package note:** `verify402-mcp@1.0.7` is published to npm and
|
|
14
14
|
> defaults paid calls to Base Sepolia testnet (`eip155:84532`) for the public
|
|
15
15
|
> demo. Base mainnet (`eip155:8453`) requires an explicit `VERIFY402_NETWORKS`
|
|
16
16
|
> opt-in in a separate deployment and is not enabled by this release. The
|
|
17
|
-
> previously published `1.0.
|
|
18
|
-
> and used Base mainnet by default. Do not republish or
|
|
19
|
-
>
|
|
17
|
+
> previously published `1.0.6` package is immutable; `1.0.5` and `1.0.4` are
|
|
18
|
+
> also immutable, and `1.0.4` used Base mainnet by default. Do not republish or
|
|
19
|
+
> overwrite any of them.
|
|
20
20
|
|
|
21
21
|
## Tools
|
|
22
22
|
|
|
@@ -41,6 +41,15 @@ resource is CAUTION `resource_identity_unverified` and `resource identity` is
|
|
|
41
41
|
listed in `notChecked`. The bridge forwards this policy to the server; the
|
|
42
42
|
server enforces it.
|
|
43
43
|
|
|
44
|
+
Two optional caller-supplied checks are forwarded as-is:
|
|
45
|
+
|
|
46
|
+
- `payment.idempotencyKey` + `policy.obligation.settledKeys` rejects a key the
|
|
47
|
+
caller already settled; `policy.obligation.spentUsd` + `grantUsd` rejects
|
|
48
|
+
cumulative spend over the grant. The bridge does **not** persist this state.
|
|
49
|
+
- `policy.sellerPayoutWallets` binds `payTo` to the seller's known payout
|
|
50
|
+
addresses. A mismatch is BLOCK. This is a caller binding, not independent
|
|
51
|
+
proof that the seller controls the wallet.
|
|
52
|
+
|
|
44
53
|
The gate is advisory at this layer: the bridge does not hold the agent's
|
|
45
54
|
transaction key and cannot stop an agent that ignores the answer. Enforcement
|
|
46
55
|
belongs in the executor that signs — verify the receipt, then sign. See
|
|
@@ -201,9 +210,10 @@ Once configured, your agent automatically sees the tools in its context. You can
|
|
|
201
210
|
can authorize; they do **not** protect a compromised private key.
|
|
202
211
|
- `preflight_gate` is a check, not a guarantee. Read `notChecked`: it does not
|
|
203
212
|
screen recipient reputation or sanctions, audit contracts, simulate full
|
|
204
|
-
balance deltas, audit the counterparty,
|
|
205
|
-
|
|
206
|
-
|
|
213
|
+
balance deltas, audit the counterparty, independently prove payee ownership,
|
|
214
|
+
persist an obligation ledger across processes, scan tool descriptions or
|
|
215
|
+
responses for prompt injection, or protect against MEV. It catches the
|
|
216
|
+
measurable signing mistakes, not every scam.
|
|
207
217
|
- Use the [reference executor](https://github.com/a32116150-ctrl/verify402/blob/master/examples/preflight-guard.mjs)
|
|
208
218
|
when you want enforcement rather than advice.
|
|
209
219
|
|
package/index.mjs
CHANGED
|
@@ -42,7 +42,7 @@ installConsoleRedaction();
|
|
|
42
42
|
const IS_MAIN = isMainModule();
|
|
43
43
|
if (IS_MAIN) config();
|
|
44
44
|
|
|
45
|
-
const VERSION = "1.0.
|
|
45
|
+
const VERSION = "1.0.7";
|
|
46
46
|
const EVM_PRIVATE_KEY = process.env.EVM_PRIVATE_KEY;
|
|
47
47
|
// Normalise once so the axios base URL, the payment policy prefix, and the
|
|
48
48
|
// per-tool expected resource are all the same string (no trailing slash).
|
|
@@ -222,7 +222,9 @@ const DESCRIPTIONS = {
|
|
|
222
222
|
"operator before signing. The receipt expires (default 90s): call again rather than reuse it. " +
|
|
223
223
|
"Free. Pass `from` (the wallet that will sign) to enable simulation and balance checks. For " +
|
|
224
224
|
"kind=transaction, chainId is REQUIRED (400 missing_chain without it). For payment intents " +
|
|
225
|
-
"with no `from` or no proof, the response is PASS with structural_only:true and names what was not checked."
|
|
225
|
+
"with no `from` or no proof, the response is PASS with structural_only:true and names what was not checked. " +
|
|
226
|
+
"Optional caller-supplied checks: policy.sellerPayoutWallets binds payTo to the seller's payout addresses; " +
|
|
227
|
+
"policy.obligation checks a local settled-key ledger and cumulative spend against a grant. The gate does not persist either state.",
|
|
226
228
|
verify_arbitrage:
|
|
227
229
|
"Ask verify402 whether a cross-venue arbitrage opportunity is REAL, right now. " +
|
|
228
230
|
"Quotes come from Uniswap's canonical QuoterV2 and each DEX router at one pinned block. " +
|
|
@@ -268,6 +270,7 @@ async function main() {
|
|
|
268
270
|
amount: z.string().describe("RAW amount in the asset's smallest unit, as a string"),
|
|
269
271
|
payTo: z.string().describe("Recipient address from the 402 challenge"),
|
|
270
272
|
resource: z.string().optional().describe("The resource URL the payment is for"),
|
|
273
|
+
idempotencyKey: z.string().max(256).optional().describe("Caller-local payment idempotency key (not the paid-route x-idempotency-key header); enables the policy.obligation replay check"),
|
|
271
274
|
maxTimeoutSeconds: z.number().optional().describe("maxTimeoutSeconds from the 402 challenge"),
|
|
272
275
|
extra: z.object({
|
|
273
276
|
validAfter: z.number().optional(),
|
|
@@ -289,6 +292,13 @@ async function main() {
|
|
|
289
292
|
allowedAssets: z.array(z.string()).optional().describe("Allowlist of payment assets"),
|
|
290
293
|
allowedFacilitators: z.array(z.string()).optional().describe("Allowlist of x402 facilitators"),
|
|
291
294
|
expectedResource: z.string().optional().describe("The exact resource URL the agent intends to pay for"),
|
|
295
|
+
allowedResourceHosts: z.array(z.string()).optional().describe("Bare hostnames allowed in payment.resource; a foreign host is BLOCK"),
|
|
296
|
+
sellerPayoutWallets: z.array(z.string()).optional().describe("Caller-supplied seller payout addresses; a payTo mismatch is BLOCK. This is a binding, not independent ownership proof"),
|
|
297
|
+
obligation: z.object({
|
|
298
|
+
settledKeys: z.array(z.string()).optional().describe("Payment idempotency keys already settled"),
|
|
299
|
+
spentUsd: z.number().nonnegative().optional().describe("Already spent under the grant, in USD"),
|
|
300
|
+
grantUsd: z.number().nonnegative().optional().describe("Total grant in USD; spentUsd and grantUsd must be supplied together"),
|
|
301
|
+
}).optional().describe("Caller-supplied local obligation state. The public gate does not persist it"),
|
|
292
302
|
forbidUnlimitedApproval: z.boolean().optional().describe("Turn an unlimited approve into a BLOCK"),
|
|
293
303
|
maxTimeoutSeconds: z.number().optional().describe("Reject challenges with a longer timeout"),
|
|
294
304
|
}).optional().describe("Operator policy. Omit for structural checks only."),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "verify402-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"mcpName": "io.github.a32116150-ctrl/verify402-mcp",
|
|
5
5
|
"description": "MCP server for verify402: a free, fail-closed preflight gate before signing, plus five paid on-chain checks paid per call via x402.",
|
|
6
6
|
"type": "module",
|