@absol-labs/agent 0.9.1 → 0.11.0
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 +184 -26
- package/dist/capability/invocation-capability.d.ts +18 -6
- package/dist/capability/invocation-capability.d.ts.map +1 -1
- package/dist/capability/invocation-capability.js.map +1 -1
- package/dist/cli/amounts.d.ts +26 -0
- package/dist/cli/amounts.d.ts.map +1 -0
- package/dist/cli/amounts.js +71 -0
- package/dist/cli/amounts.js.map +1 -0
- package/dist/cli/args.d.ts +32 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +119 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/attesters.d.ts +51 -0
- package/dist/cli/attesters.d.ts.map +1 -0
- package/dist/cli/attesters.js +58 -0
- package/dist/cli/attesters.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +5 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/commands/claim.d.ts +13 -0
- package/dist/cli/commands/claim.d.ts.map +1 -0
- package/dist/cli/commands/claim.js +102 -0
- package/dist/cli/commands/claim.js.map +1 -0
- package/dist/cli/commands/close.d.ts +3 -0
- package/dist/cli/commands/close.d.ts.map +1 -0
- package/dist/cli/commands/close.js +55 -0
- package/dist/cli/commands/close.js.map +1 -0
- package/dist/cli/commands/discover.d.ts +3 -0
- package/dist/cli/commands/discover.d.ts.map +1 -0
- package/dist/cli/commands/discover.js +183 -0
- package/dist/cli/commands/discover.js.map +1 -0
- package/dist/cli/commands/invoke.d.ts +3 -0
- package/dist/cli/commands/invoke.d.ts.map +1 -0
- package/dist/cli/commands/invoke.js +142 -0
- package/dist/cli/commands/invoke.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +3 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +113 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/open.d.ts +3 -0
- package/dist/cli/commands/open.d.ts.map +1 -0
- package/dist/cli/commands/open.js +331 -0
- package/dist/cli/commands/open.js.map +1 -0
- package/dist/cli/commands/reclaim-unverified.d.ts +3 -0
- package/dist/cli/commands/reclaim-unverified.d.ts.map +1 -0
- package/dist/cli/commands/reclaim-unverified.js +172 -0
- package/dist/cli/commands/reclaim-unverified.js.map +1 -0
- package/dist/cli/commands/reclaim.d.ts +33 -0
- package/dist/cli/commands/reclaim.d.ts.map +1 -0
- package/dist/cli/commands/reclaim.js +308 -0
- package/dist/cli/commands/reclaim.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +43 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/streams.d.ts +3 -0
- package/dist/cli/commands/streams.d.ts.map +1 -0
- package/dist/cli/commands/streams.js +257 -0
- package/dist/cli/commands/streams.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +3 -0
- package/dist/cli/commands/watch.d.ts.map +1 -0
- package/dist/cli/commands/watch.js +55 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/config.d.ts +61 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +140 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/context.d.ts +29 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/context.js +2 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/deps.d.ts +191 -0
- package/dist/cli/deps.d.ts.map +1 -0
- package/dist/cli/deps.js +277 -0
- package/dist/cli/deps.js.map +1 -0
- package/dist/cli/descriptor.d.ts +61 -0
- package/dist/cli/descriptor.d.ts.map +1 -0
- package/dist/cli/descriptor.js +78 -0
- package/dist/cli/descriptor.js.map +1 -0
- package/dist/cli/errors.d.ts +48 -0
- package/dist/cli/errors.d.ts.map +1 -0
- package/dist/cli/errors.js +129 -0
- package/dist/cli/errors.js.map +1 -0
- package/dist/cli/escape-hatch.d.ts +50 -0
- package/dist/cli/escape-hatch.d.ts.map +1 -0
- package/dist/cli/escape-hatch.js +45 -0
- package/dist/cli/escape-hatch.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +7 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/listings.d.ts +15 -0
- package/dist/cli/listings.d.ts.map +1 -0
- package/dist/cli/listings.js +56 -0
- package/dist/cli/listings.js.map +1 -0
- package/dist/cli/mandate.d.ts +66 -0
- package/dist/cli/mandate.d.ts.map +1 -0
- package/dist/cli/mandate.js +61 -0
- package/dist/cli/mandate.js.map +1 -0
- package/dist/cli/output.d.ts +33 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +34 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/preflight.d.ts +38 -0
- package/dist/cli/preflight.d.ts.map +1 -0
- package/dist/cli/preflight.js +72 -0
- package/dist/cli/preflight.js.map +1 -0
- package/dist/cli/privy.d.ts +83 -0
- package/dist/cli/privy.d.ts.map +1 -0
- package/dist/cli/privy.js +230 -0
- package/dist/cli/privy.js.map +1 -0
- package/dist/cli/progress.d.ts +36 -0
- package/dist/cli/progress.d.ts.map +1 -0
- package/dist/cli/progress.js +40 -0
- package/dist/cli/progress.js.map +1 -0
- package/dist/cli/run.d.ts +25 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +173 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/cli/scan-range.d.ts +55 -0
- package/dist/cli/scan-range.d.ts.map +1 -0
- package/dist/cli/scan-range.js +57 -0
- package/dist/cli/scan-range.js.map +1 -0
- package/dist/cli/spend-policy.d.ts +60 -0
- package/dist/cli/spend-policy.d.ts.map +1 -0
- package/dist/cli/spend-policy.js +65 -0
- package/dist/cli/spend-policy.js.map +1 -0
- package/dist/cli/status.d.ts +90 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +252 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/cli/timeout.d.ts +30 -0
- package/dist/cli/timeout.d.ts.map +1 -0
- package/dist/cli/timeout.js +55 -0
- package/dist/cli/timeout.js.map +1 -0
- package/dist/cli/version.d.ts +12 -0
- package/dist/cli/version.d.ts.map +1 -0
- package/dist/cli/version.js +22 -0
- package/dist/cli/version.js.map +1 -0
- package/dist/cli/wallet.d.ts +164 -0
- package/dist/cli/wallet.d.ts.map +1 -0
- package/dist/cli/wallet.js +234 -0
- package/dist/cli/wallet.js.map +1 -0
- package/dist/frameworks/crewai.d.ts +10 -0
- package/dist/frameworks/crewai.d.ts.map +1 -1
- package/dist/frameworks/crewai.js +12 -2
- package/dist/frameworks/crewai.js.map +1 -1
- package/dist/gateway/caller-auth-gateway.d.ts +38 -3
- package/dist/gateway/caller-auth-gateway.d.ts.map +1 -1
- package/dist/gateway/caller-auth-gateway.js +25 -1
- package/dist/gateway/caller-auth-gateway.js.map +1 -1
- package/dist/gateway/http-server.d.ts +53 -0
- package/dist/gateway/http-server.d.ts.map +1 -1
- package/dist/gateway/http-server.js +189 -4
- package/dist/gateway/http-server.js.map +1 -1
- package/dist/gateway/server-entry.d.ts +1 -0
- package/dist/gateway/server-entry.js +1 -0
- package/dist/gateway/server-entry.js.map +1 -1
- package/dist/gateway/x402-mode.d.ts +123 -0
- package/dist/gateway/x402-mode.d.ts.map +1 -0
- package/dist/gateway/x402-mode.js +212 -0
- package/dist/gateway/x402-mode.js.map +1 -0
- package/dist/index.d.ts +6 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -3
- package/dist/index.js.map +1 -1
- package/dist/mandates/env.d.ts +3 -2
- package/dist/mandates/env.d.ts.map +1 -1
- package/dist/mandates/env.js +3 -2
- package/dist/mandates/env.js.map +1 -1
- package/dist/mcp/http-server.d.ts +1 -0
- package/dist/mcp/http-server.js +1 -0
- package/dist/mcp/http-server.js.map +1 -1
- package/dist/mcp/server.d.ts +49 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +533 -25
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/service-invoker.d.ts +97 -0
- package/dist/mcp/service-invoker.d.ts.map +1 -0
- package/dist/mcp/service-invoker.js +167 -0
- package/dist/mcp/service-invoker.js.map +1 -0
- package/dist/mcp/stdio.d.ts +1 -0
- package/dist/mcp/stdio.js +1 -0
- package/dist/mcp/stdio.js.map +1 -1
- package/dist/sdk/client.d.ts +25 -1
- package/dist/sdk/client.d.ts.map +1 -1
- package/dist/sdk/client.js +20 -1
- package/dist/sdk/client.js.map +1 -1
- package/dist/sdk/invoke.d.ts +19 -4
- package/dist/sdk/invoke.d.ts.map +1 -1
- package/dist/sdk/invoke.js +69 -5
- package/dist/sdk/invoke.js.map +1 -1
- package/dist/x402/delivery-oracle.d.ts +108 -0
- package/dist/x402/delivery-oracle.d.ts.map +1 -0
- package/dist/x402/delivery-oracle.js +174 -0
- package/dist/x402/delivery-oracle.js.map +1 -0
- package/dist/x402/facilitator-server-entry.d.ts +3 -0
- package/dist/x402/facilitator-server-entry.d.ts.map +1 -0
- package/dist/x402/facilitator-server-entry.js +27 -0
- package/dist/x402/facilitator-server-entry.js.map +1 -0
- package/dist/x402/facilitator-server.d.ts +73 -0
- package/dist/x402/facilitator-server.d.ts.map +1 -0
- package/dist/x402/facilitator-server.js +305 -0
- package/dist/x402/facilitator-server.js.map +1 -0
- package/dist/x402/facilitator.d.ts +69 -17
- package/dist/x402/facilitator.d.ts.map +1 -1
- package/dist/x402/facilitator.js +76 -33
- package/dist/x402/facilitator.js.map +1 -1
- package/dist/x402/payment-requirements.d.ts +106 -0
- package/dist/x402/payment-requirements.d.ts.map +1 -0
- package/dist/x402/payment-requirements.js +138 -0
- package/dist/x402/payment-requirements.js.map +1 -0
- package/dist/x402/relayer.d.ts +41 -0
- package/dist/x402/relayer.d.ts.map +1 -0
- package/dist/x402/relayer.js +64 -0
- package/dist/x402/relayer.js.map +1 -0
- package/dist/x402/resource-index.d.ts +75 -0
- package/dist/x402/resource-index.d.ts.map +1 -0
- package/dist/x402/resource-index.js +126 -0
- package/dist/x402/resource-index.js.map +1 -0
- package/dist/x402/verified-delivery-facilitator.d.ts +285 -0
- package/dist/x402/verified-delivery-facilitator.d.ts.map +1 -0
- package/dist/x402/verified-delivery-facilitator.js +423 -0
- package/dist/x402/verified-delivery-facilitator.js.map +1 -0
- package/dist/zktls/t2-delivery-proof.d.ts +6 -6
- package/docs/agent-layer.md +14 -9
- package/docs/cli.md +705 -0
- package/docs/crewai.md +6 -2
- package/docs/eliza.md +6 -1
- package/docs/mcp-hosted.md +7 -5
- package/docs/mcp-reference.md +175 -0
- package/docs/quickstart.md +36 -9
- package/docs/threat-model.md +4 -3
- package/docs/x402.md +648 -0
- package/package.json +33 -10
- package/src/capability/invocation-capability.ts +17 -1
- package/src/cli/amounts.ts +102 -0
- package/src/cli/args.ts +150 -0
- package/src/cli/attesters.ts +86 -0
- package/src/cli/bin.ts +5 -0
- package/src/cli/commands/claim.ts +126 -0
- package/src/cli/commands/close.ts +69 -0
- package/src/cli/commands/discover.ts +228 -0
- package/src/cli/commands/invoke.ts +178 -0
- package/src/cli/commands/mcp.ts +135 -0
- package/src/cli/commands/open.ts +397 -0
- package/src/cli/commands/reclaim-unverified.ts +218 -0
- package/src/cli/commands/reclaim.ts +377 -0
- package/src/cli/commands/status.ts +56 -0
- package/src/cli/commands/streams.ts +344 -0
- package/src/cli/commands/watch.ts +70 -0
- package/src/cli/config.ts +208 -0
- package/src/cli/context.ts +30 -0
- package/src/cli/deps.ts +528 -0
- package/src/cli/descriptor.ts +133 -0
- package/src/cli/errors.ts +162 -0
- package/src/cli/escape-hatch.ts +92 -0
- package/src/cli/index.ts +27 -0
- package/src/cli/listings.ts +77 -0
- package/src/cli/mandate.ts +126 -0
- package/src/cli/output.ts +63 -0
- package/src/cli/preflight.ts +88 -0
- package/src/cli/privy.ts +396 -0
- package/src/cli/progress.ts +75 -0
- package/src/cli/run.ts +209 -0
- package/src/cli/scan-range.ts +76 -0
- package/src/cli/spend-policy.ts +139 -0
- package/src/cli/status.ts +381 -0
- package/src/cli/timeout.ts +64 -0
- package/src/cli/version.ts +21 -0
- package/src/cli/wallet.ts +372 -0
- package/src/frameworks/crewai.ts +13 -2
- package/src/gateway/caller-auth-gateway.ts +77 -6
- package/src/gateway/http-server.ts +280 -6
- package/src/gateway/server-entry.ts +1 -0
- package/src/gateway/x402-mode.ts +350 -0
- package/src/index.ts +40 -5
- package/src/mandates/env.ts +3 -2
- package/src/mcp/http-server.ts +1 -0
- package/src/mcp/server.ts +706 -30
- package/src/mcp/service-invoker.ts +285 -0
- package/src/mcp/stdio.ts +1 -0
- package/src/sdk/client.ts +33 -1
- package/src/sdk/invoke.ts +90 -12
- package/src/x402/delivery-oracle.ts +285 -0
- package/src/x402/facilitator-server-entry.ts +35 -0
- package/src/x402/facilitator-server.ts +445 -0
- package/src/x402/facilitator.ts +125 -46
- package/src/x402/payment-requirements.ts +231 -0
- package/src/x402/relayer.ts +122 -0
- package/src/x402/resource-index.ts +228 -0
- package/src/x402/verified-delivery-facilitator.ts +744 -0
package/docs/crewai.md
CHANGED
|
@@ -33,9 +33,13 @@ from crewai import Agent, Crew, Task
|
|
|
33
33
|
from crewai.mcp import MCPServerStdio
|
|
34
34
|
from crewai.mcp.filters import create_static_tool_filter
|
|
35
35
|
|
|
36
|
+
# `metrik-mcp` is the executable this package publishes. It resolves anywhere
|
|
37
|
+
# `@absol-labs/agent` is installed (npm/pnpm link it into node_modules/.bin) and
|
|
38
|
+
# via `npx --package @absol-labs/agent metrik-mcp`. The old default was
|
|
39
|
+
# `pnpm mcp:stdio`, which only ever resolved inside the agent repository.
|
|
36
40
|
metrik_mcp = MCPServerStdio(
|
|
37
|
-
command="
|
|
38
|
-
args=[
|
|
41
|
+
command="metrik-mcp",
|
|
42
|
+
args=[],
|
|
39
43
|
env={
|
|
40
44
|
"METRIK_AGENT_RPC_URL": "https://base-sepolia.example.invalid",
|
|
41
45
|
"METRIK_AGENT_ESCROW": "0x0000000000000000000000000000000000000000",
|
package/docs/eliza.md
CHANGED
|
@@ -50,6 +50,7 @@ runnable-shaped example lives in
|
|
|
50
50
|
|
|
51
51
|
```ts
|
|
52
52
|
import { http } from "viem";
|
|
53
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
53
54
|
import { baseSepolia } from "viem/chains";
|
|
54
55
|
import { createMetrikElizaPlugin } from "@absol-labs/agent/eliza";
|
|
55
56
|
import { createWalletBackedAgentClient } from "@absol-labs/agent";
|
|
@@ -65,7 +66,11 @@ const { agentClient } = await createWalletBackedAgentClient(
|
|
|
65
66
|
escrow: process.env.METRIK_AGENT_ESCROW! as `0x${string}`,
|
|
66
67
|
},
|
|
67
68
|
},
|
|
68
|
-
{
|
|
69
|
+
{
|
|
70
|
+
injectedAccount: privateKeyToAccount(
|
|
71
|
+
process.env.METRIK_AGENT_PRIVATE_KEY as `0x${string}`,
|
|
72
|
+
),
|
|
73
|
+
},
|
|
69
74
|
);
|
|
70
75
|
|
|
71
76
|
const metrikPlugin = createMetrikElizaPlugin({ agentClient });
|
package/docs/mcp-hosted.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# Hosted MCP over Streamable HTTP
|
|
2
2
|
|
|
3
3
|
The agent lane ships two MCP transports over the **same** tool set
|
|
4
|
-
(`
|
|
5
|
-
and the optional
|
|
4
|
+
(`discover_services`, `hire_verified_service`, `invoke_service`,
|
|
5
|
+
`check_stream_status`, `reclaim_unspent`, `list_streams`, and the optional
|
|
6
|
+
`prove_https_response` — see [`mcp-reference.md`](./mcp-reference.md)):
|
|
6
7
|
|
|
7
|
-
- **stdio** (`src/mcp/stdio.ts
|
|
8
|
-
|
|
8
|
+
- **stdio** (`src/mcp/stdio.ts`) — local dev, one process per caller. Started with
|
|
9
|
+
the published `metrik-mcp` executable (`npx --package @absol-labs/agent metrik-mcp`),
|
|
10
|
+
or `pnpm mcp:stdio` inside this repository.
|
|
9
11
|
- **Streamable HTTP** (`src/mcp/http.ts` + `src/mcp/http-server.ts`,
|
|
10
12
|
`pnpm mcp:http`) — a hosted, **multi-tenant**, per-caller-authenticated
|
|
11
13
|
endpoint suitable for deployment. This document covers the HTTP transport.
|
|
@@ -78,7 +80,7 @@ network but need distinct wallets override only the wallet vars in their `env`.
|
|
|
78
80
|
|
|
79
81
|
```bash
|
|
80
82
|
export METRIK_AGENT_RPC_URL="https://base-sepolia.example/rpc"
|
|
81
|
-
export METRIK_AGENT_ESCROW="
|
|
83
|
+
export METRIK_AGENT_ESCROW="0x0f09f36Ccc05A7c9882F438721C08De314dFd46C" # StreamEscrowV2 — NOT the retired V1 escrow
|
|
82
84
|
export METRIK_AGENT_USDC="0x036CbD53842c5426634e7929541eC2318f3dCF7e"
|
|
83
85
|
# ... wallet vars (private key or CDP) ...
|
|
84
86
|
export METRIK_MCP_TENANTS='[{"id":"acme","token":"REPLACE_WITH_SECRET"}]'
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# MCP tool reference
|
|
2
|
+
|
|
3
|
+
The canonical description of what `@absol-labs/agent`'s MCP server offers an
|
|
4
|
+
agent, what each tool costs, and what it refuses to do. Both transports — stdio
|
|
5
|
+
(`metrik-mcp`) and hosted Streamable HTTP (`metrik-mcp-http`, see
|
|
6
|
+
[`mcp-hosted.md`](./mcp-hosted.md)) — serve exactly this set.
|
|
7
|
+
|
|
8
|
+
The names and descriptions here are the ones in `METRIK_MCP_TOOLS`
|
|
9
|
+
(`src/mcp/server.ts`); a clean-install check asserts the published `metrik-mcp`
|
|
10
|
+
binary really offers them (`scripts/check-packed-package.mjs`).
|
|
11
|
+
|
|
12
|
+
## What you are buying: TIME, not calls
|
|
13
|
+
|
|
14
|
+
A stream rents an endpoint that the oracle keeps probing. **The meter runs on
|
|
15
|
+
availability that VERIFIED, not on the requests you send.** Cost is
|
|
16
|
+
`ratePerSecondUsdc x verified seconds`, capped at the escrowed budget. One
|
|
17
|
+
request and a thousand requests cost the same second, and the clock keeps
|
|
18
|
+
running while you send none.
|
|
19
|
+
|
|
20
|
+
A reviewer who opened a stream, made a single `invoke_service` call and was
|
|
21
|
+
billed for 302 seconds was billed exactly as designed. `reclaim_unspent` stops
|
|
22
|
+
the clock; nothing else does, and **nothing pushes money back on its own**.
|
|
23
|
+
|
|
24
|
+
The escrow proves _delivery_, not _correctness_. An endpoint that answers, on
|
|
25
|
+
time, in the right shape, is what gets paid — whether its answer is any good is
|
|
26
|
+
an economic question, not a cryptographic one.
|
|
27
|
+
|
|
28
|
+
## The tools
|
|
29
|
+
|
|
30
|
+
| Tool | Moves funds | What it does |
|
|
31
|
+
| ----------------------- | ----------- | ------------------------------------------------------------------------------- |
|
|
32
|
+
| `discover_services` | no | Lists marketplace services whose operator signature verifies. |
|
|
33
|
+
| `hire_verified_service` | **yes** | Escrows USDC and opens a per-second stream. **Starts the meter.** |
|
|
34
|
+
| `invoke_service` | no | Calls the service the stream is paying for. Adds no cost. |
|
|
35
|
+
| `check_stream_status` | no | Reads live status, settled amount, claimable/reclaimable. |
|
|
36
|
+
| `reclaim_unspent` | **yes** | Closes the stream (**stops the meter**) and returns unspent USDC to the buyer. |
|
|
37
|
+
| `list_streams` | no | Lists the streams this server opened. |
|
|
38
|
+
| `prove_https_response` | no | Buyer-side zkTLS proof of a response. Registered only with Reclaim credentials. |
|
|
39
|
+
|
|
40
|
+
### `discover_services`
|
|
41
|
+
|
|
42
|
+
`category?`, `limit?`. Returns `serviceRef`, `operator`, `publicUrl`, `access`,
|
|
43
|
+
`accessUrl` per listing.
|
|
44
|
+
|
|
45
|
+
The registry is an **untrusted transport**: every `serviceRef` is re-derived
|
|
46
|
+
from the signed record and the operator's signature recovered, so a compromised
|
|
47
|
+
registry can neither invent an operator to pay nor redirect an invocation. Rows
|
|
48
|
+
that fail verification are dropped. An unreachable registry is an **error**, not
|
|
49
|
+
an empty list — "zero services" and "could not reach the marketplace" must never
|
|
50
|
+
read the same.
|
|
51
|
+
|
|
52
|
+
### `hire_verified_service`
|
|
53
|
+
|
|
54
|
+
`operator`, `serviceRef`, `budgetUsdc`, `ratePerSecondUsdc`, `durationSeconds?`.
|
|
55
|
+
All USDC amounts are **atomic 6-decimal units** (`1 USDC = "1000000"`).
|
|
56
|
+
|
|
57
|
+
Bounded by the server's own signed spend mandate (per-stream, cumulative, rate,
|
|
58
|
+
duration, operator allowlist, expiry), configured through
|
|
59
|
+
`METRIK_AGENT_MANDATE_*`. An MCP caller cannot produce an EIP-712 signature, so
|
|
60
|
+
the mandate is never a tool argument — the server holds it and fails closed
|
|
61
|
+
without one.
|
|
62
|
+
|
|
63
|
+
`operator` is the wallet that gets paid, and it arrives as a separate argument
|
|
64
|
+
from `serviceRef`. The pair is cross-checked against the verified registry, and
|
|
65
|
+
the check **fails closed**: the hire proceeds only on a positive match.
|
|
66
|
+
|
|
67
|
+
A contradicted pairing escrows a buyer's USDC to a stranger for someone else's
|
|
68
|
+
service, and nothing downstream catches it — the escrow does not know who owns a
|
|
69
|
+
`serviceRef`, and the oracle verifies the real endpoint while the money accrues
|
|
70
|
+
elsewhere. A registry read that fails is no evidence the pairing is sound:
|
|
71
|
+
settlement does not depend on that HTTP endpoint being reachable from the MCP
|
|
72
|
+
host, so during an outage the bug would be fully live. An unlisted `serviceRef`
|
|
73
|
+
is refused for the same reason — a hostile registry cannot forge a match, but it
|
|
74
|
+
can suppress a row, which would otherwise downgrade a contradiction into a pass.
|
|
75
|
+
|
|
76
|
+
Refusing strands nothing: no USDC has moved and the same call succeeds once the
|
|
77
|
+
registry answers. If you must accept that risk,
|
|
78
|
+
`METRIK_AGENT_ALLOW_UNVERIFIED_OPERATOR=true` downgrades "could not verify" to a
|
|
79
|
+
warning on the result. It is operator-set input only — never a tool argument,
|
|
80
|
+
because the caller being asked to relax a fund-safety check is the LLM the check
|
|
81
|
+
exists to constrain — and it never overrides a positive contradiction.
|
|
82
|
+
|
|
83
|
+
The result carries a `metering` block: the rate, the budget, the maximum this
|
|
84
|
+
stream can ever spend, and what starts and stops the clock.
|
|
85
|
+
|
|
86
|
+
### `invoke_service`
|
|
87
|
+
|
|
88
|
+
`streamId`, `path?` (default `/`), `method?` (default `GET`), `headers?`,
|
|
89
|
+
`body?`, `ttlSeconds?` (default 60, max 300).
|
|
90
|
+
|
|
91
|
+
Signs a single-use EIP-712 `InvocationCapability` as the stream's buyer — scoped
|
|
92
|
+
to exactly this method and path — and calls the service through the operator's
|
|
93
|
+
caller-auth gateway.
|
|
94
|
+
|
|
95
|
+
- **The origin is not a parameter.** It is resolved from the operator-signed
|
|
96
|
+
listing for the stream's own `serviceRef`. An LLM-chosen base URL is precisely
|
|
97
|
+
the injection this refuses; there is no override.
|
|
98
|
+
- **The path cannot leave that origin.** The URL is resolved first and the
|
|
99
|
+
result is then proven to carry the signed origin and stay under the signed
|
|
100
|
+
base path — a prefix check on the raw path is not sufficient, because the URL
|
|
101
|
+
parser reads a backslash as a host separator for http(s). Backslashes and
|
|
102
|
+
control characters are rejected outright as well. Resolution happens **before**
|
|
103
|
+
the capability is signed, so a path that escapes never causes a buyer-signed
|
|
104
|
+
credential to exist.
|
|
105
|
+
- **Fails closed before any network call** if the stream is not active, has
|
|
106
|
+
expired, or does not belong to this server's wallet — each with an error that
|
|
107
|
+
names the next step.
|
|
108
|
+
- A gateway rejection is surfaced with its machine-readable reason
|
|
109
|
+
(`stream-not-funded`, `capability-expired`, `nonce-replayed`, …) and a next
|
|
110
|
+
step, rather than a bare `403`.
|
|
111
|
+
- Responses are capped at 64 KiB with `bodyTruncated` reported explicitly.
|
|
112
|
+
- It signs no transaction and moves no funds.
|
|
113
|
+
|
|
114
|
+
### `check_stream_status`
|
|
115
|
+
|
|
116
|
+
`streamId`. Returns the stream, `claimable`, `reclaimable`, and a `metering`
|
|
117
|
+
block. A stream id that does not exist on the configured escrow is reported as
|
|
118
|
+
such rather than as "closed" — an unset escrow slot decodes as an all-zero
|
|
119
|
+
struct instead of reverting.
|
|
120
|
+
|
|
121
|
+
### `reclaim_unspent`
|
|
122
|
+
|
|
123
|
+
`streamId`, `closeFirst?`. Closing is what stops the meter.
|
|
124
|
+
|
|
125
|
+
Authorized on the mandate owner's signature **alone** — never gated by mandate
|
|
126
|
+
expiry, revocation, or caps, because those must never strand a buyer's own
|
|
127
|
+
funds. It also works for a stream this server has no local record of (the
|
|
128
|
+
escrow itself enforces buyer-only recovery), so losing in-memory state cannot
|
|
129
|
+
stand between a buyer and their escrow.
|
|
130
|
+
|
|
131
|
+
### `list_streams`
|
|
132
|
+
|
|
133
|
+
No arguments. Every active stream listed is still accruing cost per verified
|
|
134
|
+
second, whether or not it is being invoked.
|
|
135
|
+
|
|
136
|
+
### `prove_https_response`
|
|
137
|
+
|
|
138
|
+
Registered **only** when Reclaim credentials are configured
|
|
139
|
+
(`RECLAIM_APP_ID` + `RECLAIM_APP_SECRET`). Generates a buyer-side zkTLS proof of an HTTPS response.
|
|
140
|
+
|
|
141
|
+
**Public listings only.** The Reclaim attestor fetches the URL itself, from its
|
|
142
|
+
own network position, and cannot carry this stream's single-use caller-auth
|
|
143
|
+
capability — so against a gated listing the only thing it could prove is its own
|
|
144
|
+
`403`. The tool says that instead of producing one. Use `invoke_service` for
|
|
145
|
+
gated services; that delivery is covered by the oracle's own verification.
|
|
146
|
+
|
|
147
|
+
The proof target is pinned to the stream's verified listing origin. A proof of
|
|
148
|
+
some other origin, stamped with this stream's delivery binding, would be
|
|
149
|
+
evidence of a delivery that did not happen here.
|
|
150
|
+
|
|
151
|
+
This is an L2 signal to be cross-checked with oracle/L1 evidence — not a
|
|
152
|
+
substitute for it.
|
|
153
|
+
|
|
154
|
+
## Configuration
|
|
155
|
+
|
|
156
|
+
`metrik mcp --print-config` prints the `mcpServers` block to paste into an MCP
|
|
157
|
+
client, already carrying every variable the server fails closed without. Secrets
|
|
158
|
+
in it are placeholders by design.
|
|
159
|
+
|
|
160
|
+
| Variable | Required | Meaning |
|
|
161
|
+
| ---------------------------------------- | -------- | ----------------------------------------------------------------------------------------------- |
|
|
162
|
+
| `METRIK_AGENT_RPC_URL` | **yes** | Base Sepolia RPC. |
|
|
163
|
+
| `METRIK_AGENT_ESCROW` | **yes** | The **StreamEscrowV2** address. The retired V1 escrow is refused. |
|
|
164
|
+
| `METRIK_AGENT_USDC` | **yes** | Settlement token. |
|
|
165
|
+
| `METRIK_AGENT_ESCROW_GENERATION` | no | `v2` (default, and the only supported value). Declared, not probed. |
|
|
166
|
+
| `METRIK_AGENT_CHAIN_ID` | no | Defaults to `84532`; nothing else is accepted. |
|
|
167
|
+
| `METRIK_AGENT_REGISTRY_URL` | no | Registry the invocation origin is verified against. |
|
|
168
|
+
| `METRIK_AGENT_ALLOW_UNVERIFIED_OPERATOR` | no | `true` downgrades an unverifiable operator pairing from a refusal to a warning. Off by default. |
|
|
169
|
+
| `METRIK_AGENT_MCP_STATE_FILE` | no | Persists the stream registry across restarts. |
|
|
170
|
+
| `METRIK_AGENT_MANDATE_*` | **yes** | The four spend ceilings. No ceiling, no server. |
|
|
171
|
+
| wallet vars | **yes** | `METRIK_AGENT_PRIVATE_KEY`, or the CDP/Privy set. |
|
|
172
|
+
|
|
173
|
+
The escrow generation is a **declared fact, not an inference**: the server
|
|
174
|
+
refuses the retired V1 address by name, because a wrong-generation read does not
|
|
175
|
+
revert — it returns confident nonsense about someone's money.
|
package/docs/quickstart.md
CHANGED
|
@@ -16,9 +16,15 @@ Base Sepolia constants used throughout (chainId **84532**):
|
|
|
16
16
|
|
|
17
17
|
| Thing | Address |
|
|
18
18
|
| ------ | -------------------------------------------- |
|
|
19
|
-
| Escrow | `
|
|
19
|
+
| Escrow | `0x0f09f36Ccc05A7c9882F438721C08De314dFd46C` |
|
|
20
20
|
| USDC | `0x036CbD53842c5426634e7929541eC2318f3dCF7e` |
|
|
21
21
|
|
|
22
|
+
The escrow above is **StreamEscrowV2**, the checkpoint-settled contract the
|
|
23
|
+
oracle and the dApp actually settle against. The retired V1 metered escrow
|
|
24
|
+
(`0x21948a5E…`) is not a valid target: its stream tuple diverges from V2's at
|
|
25
|
+
index 5, so a V2 read of it does not revert — it decodes other fields into
|
|
26
|
+
correctly-named ones and reports a confident wrong answer.
|
|
27
|
+
|
|
22
28
|
A complete, runnable version of this journey lives in
|
|
23
29
|
[`scripts/e2e-cdp.ts`](../scripts/e2e-cdp.ts) (the live CI E2E, metrik-agent#32) — treat
|
|
24
30
|
it as the working reference.
|
|
@@ -34,8 +40,8 @@ pnpm add @absol-labs/agent
|
|
|
34
40
|
`@absol-labs/agent` and its `@absol-labs/*` dependencies are published to the **public
|
|
35
41
|
npm registry** — no `.npmrc`, scope registry, or auth token is required to install.
|
|
36
42
|
|
|
37
|
-
**Runtime:** Node **20.
|
|
38
|
-
|
|
43
|
+
**Runtime:** Node **20.19+, 22 LTS or 24** (the package pins `engines.node` to
|
|
44
|
+
`>=20.19 <25`). The Coinbase AgentKit action reads decorator metadata via
|
|
39
45
|
`reflect-metadata`, which only exists in the **built** output (`tsc` emits decorator
|
|
40
46
|
metadata; `tsx`/esbuild does not) — so `import "reflect-metadata"` **before** importing
|
|
41
47
|
the package, and for the AgentKit path import from the built package, not raw `.ts`.
|
|
@@ -209,7 +215,10 @@ const sdkConfig: StreamProofClientConfig = {
|
|
|
209
215
|
chain: baseSepolia,
|
|
210
216
|
transport: http("https://sepolia.base.org"),
|
|
211
217
|
account,
|
|
212
|
-
escrow: "
|
|
218
|
+
escrow: "0x0f09f36Ccc05A7c9882F438721C08De314dFd46C",
|
|
219
|
+
// Selects the checkpoint decoder. Without it the SDK reads through the legacy
|
|
220
|
+
// V1 ABI, and `claimable()`/`reclaimable()` revert against StreamEscrowV2.
|
|
221
|
+
escrowV2: "0x0f09f36Ccc05A7c9882F438721C08De314dFd46C",
|
|
213
222
|
usdc: "0x036CbD53842c5426634e7929541eC2318f3dCF7e",
|
|
214
223
|
};
|
|
215
224
|
|
|
@@ -286,11 +295,23 @@ funds exactly.
|
|
|
286
295
|
|
|
287
296
|
---
|
|
288
297
|
|
|
289
|
-
## 8.
|
|
298
|
+
## 8. Five ways to integrate
|
|
290
299
|
|
|
291
|
-
Pick the surface that matches your stack — all
|
|
300
|
+
Pick the surface that matches your stack — all five sit on the **same** mandate-gated
|
|
292
301
|
client and business logic.
|
|
293
302
|
|
|
303
|
+
**(a0) The `metrik` CLI** — no code at all, and the only surface that runs the whole
|
|
304
|
+
loop (`discover -> open -> invoke -> watch -> close -> reclaim`):
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
npx --package @absol-labs/agent metrik discover --min-tier 2
|
|
308
|
+
npx --package @absol-labs/agent metrik open --service <serviceRef> \
|
|
309
|
+
--rate 0.000001 --budget 0.27 --duration 1h --dry-run
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Testnet-only, key read from `METRIK_AGENT_PRIVATE_KEY`, `--json` for scripting. Full
|
|
313
|
+
reference: [`docs/cli.md`](./cli.md).
|
|
314
|
+
|
|
294
315
|
**(a) SDK client directly** — the path used above:
|
|
295
316
|
|
|
296
317
|
```ts
|
|
@@ -319,12 +340,18 @@ const agentKit = await createMetrikAgentKit({
|
|
|
319
340
|
**(c) MCP** — local stdio for dev, hosted HTTP for deployment:
|
|
320
341
|
|
|
321
342
|
```bash
|
|
322
|
-
|
|
343
|
+
metrik-mcp # local: one process per caller — the published executable
|
|
344
|
+
pnpm mcp:stdio # same server, from inside this repository (src/mcp/stdio.ts)
|
|
323
345
|
pnpm mcp:http # hosted: multi-tenant Streamable HTTP, per-caller bearer auth
|
|
324
346
|
```
|
|
325
347
|
|
|
326
|
-
Tools: `discover_services`, `hire_verified_service`, `
|
|
327
|
-
`list_streams` (+ `prove_https_response` when
|
|
348
|
+
Tools: `discover_services`, `hire_verified_service`, `invoke_service`,
|
|
349
|
+
`check_stream_status`, `reclaim_unspent`, `list_streams` (+ `prove_https_response` when
|
|
350
|
+
Reclaim creds are set) — full reference in [`docs/mcp-reference.md`](./mcp-reference.md).
|
|
351
|
+
`invoke_service` is the "use" half: it signs a stream-scoped capability and calls the
|
|
352
|
+
operator-signed origin, so an agent never needs an out-of-band credential. Note the meter
|
|
353
|
+
runs on verified SECONDS, not on calls — invoking more often is free, and invoking never
|
|
354
|
+
costs the same. Env is read via
|
|
328
355
|
`parseMetrikAgentEnv` (`METRIK_AGENT_RPC_URL` / `_ESCROW` / `_USDC` + wallet vars). The
|
|
329
356
|
hosted endpoint requires `Authorization: Bearer <token>` before anything runs — see
|
|
330
357
|
[`docs/mcp-hosted.md`](./mcp-hosted.md).
|
package/docs/threat-model.md
CHANGED
|
@@ -20,7 +20,8 @@ In scope:
|
|
|
20
20
|
|
|
21
21
|
- signed spend mandates in [`src/mandates/mandate.ts`](../src/mandates/mandate.ts)
|
|
22
22
|
- the mandate-gated SDK wrapper in [`src/sdk/client.ts`](../src/sdk/client.ts)
|
|
23
|
-
-
|
|
23
|
+
- Metrik `402` verified-stream opens in [`src/x402/facilitator.ts`](../src/x402/facilitator.ts)
|
|
24
|
+
(a Metrik-native challenge flow, not the x402 protocol — see [docs/x402.md](./x402.md))
|
|
24
25
|
- MCP fund-moving tools in [`src/mcp/server.ts`](../src/mcp/server.ts)
|
|
25
26
|
- zkTLS consumer delivery proofs in [`src/zktls/reclaim.ts`](../src/zktls/reclaim.ts)
|
|
26
27
|
- wallet custody in [`src/wallet/provider.ts`](../src/wallet/provider.ts)
|
|
@@ -38,7 +39,7 @@ Out of scope:
|
|
|
38
39
|
| Runaway spend | A prompt or tool call opens streams beyond the owner's intent. | Every autonomous fund-moving path calls `checkMandate()` before the SDK can write: `openVerifiedStream()`, `claimStream()`, `closeStream()`, `reclaimStream()`, MCP `hire_verified_service`, and MCP `reclaim_unspent`. Mandates cap per-stream, cumulative spend, rate, duration, and operator. Denial is a hard stop. | [`test/mandate.test.ts`](../test/mandate.test.ts), [`test/sdk-client.test.ts`](../test/sdk-client.test.ts), [`test/mcp.test.ts`](../test/mcp.test.ts), [`test/x402.int.test.ts`](../test/x402.int.test.ts) | `spentSoFarUsdc` and revocation data are resolver inputs. If an integrator provides stale values, the agent still fails closed on signature/expiry/operator checks, but cumulative-cap freshness depends on the integrator's state source. |
|
|
39
40
|
| Mandate bypass | A caller skips the mandate layer and reaches the SDK write path directly from the agent layer. | The agent wrapper no longer exposes ungated autonomous write helpers. Existing-stream actions re-read the stream and authorize against the actual operator before `claim`, `close`, or `reclaim`. MCP also prechecks before dispatch. | [`src/sdk/client.ts`](../src/sdk/client.ts), [`test/sdk-client.test.ts`](../test/sdk-client.test.ts), [`test/mcp.test.ts`](../test/mcp.test.ts) | A caller can still use `@absol-labs/sdk` directly outside this repo. That is expected; this document only claims the agent layer itself is mandate-gated. |
|
|
40
41
|
| Key exposure | The agent leaks a private key through logs, env parsing, tool args, or local persistence. | No MCP tool accepts a raw key. Wallet selection is explicit: injected viem account, CDP Server Wallet v2, or an authenticated Privy embedded EOA provider. CDP/Privy paths remote-sign and never export private keys into Metrik code. `.env.example` contains names only. | [`src/wallet/provider.ts`](../src/wallet/provider.ts), [`test/wallet.test.ts`](../test/wallet.test.ts), [`test/privy-wallet.test.ts`](../test/privy-wallet.test.ts), [`README.md`](../README.md) | Injected-key mode is still as safe as the caller's own host. Privy authentication/session revocation remains the host/provider's responsibility. |
|
|
41
|
-
| Prompt-injection-driven spend | A hostile response or tool output tries to coerce the agent into paying a different operator or budget. | Structured inputs are validated,
|
|
42
|
+
| Prompt-injection-driven spend | A hostile response or tool output tries to coerce the agent into paying a different operator or budget. | Structured inputs are validated, challenge settlement targets must match the configured chain/escrow, and any spend still must satisfy the owner's signed mandate. | [`src/x402/facilitator.ts`](../src/x402/facilitator.ts), [`test/x402.test.ts`](../test/x402.test.ts), [`test/sdk-client.test.ts`](../test/sdk-client.test.ts) | Prompt injection can still trigger tool invocation attempts. The safety claim is not "the prompt cannot be attacked"; it is "the attack cannot exceed the mandate or redirect settlement silently." |
|
|
42
43
|
| Mandate replay | A previously valid signed mandate is replayed after revocation or outside the intended lifetime. | Mandates are EIP-712 signed over `mandateId`, `owner`, `chainId`, `issuedAt`, expiry, and policy hashes. `checkMandate()` verifies signature, revocation, expiry, then policy. Integrators can revoke by `mandateId` and track cumulative spend. | [`src/mandates/mandate.ts`](../src/mandates/mandate.ts), [`test/mandate.test.ts`](../test/mandate.test.ts), [`test/mcp.test.ts`](../test/mcp.test.ts) | Replay protection is only as strong as revocation and cumulative-spend state freshness. The signed payload itself is bound to one chain and one owner, but revocation is local state today. |
|
|
43
44
|
| False or weak delivery evidence | A consumer submits a proof that is validly signed by the zkTLS system but not bound to the intended request or stream context. | The Reclaim adapter re-verifies every proof locally against the exact URL/method/body/match/redaction spec supplied by the caller, and binds the proof context to buyer/stream metadata before returning it. MCP only exposes the public-request subset so secrets do not leak through tool arguments. | [`src/zktls/reclaim.ts`](../src/zktls/reclaim.ts), [`src/x402/facilitator.ts`](../src/x402/facilitator.ts), [`src/mcp/server.ts`](../src/mcp/server.ts), [`test/reclaim.test.ts`](../test/reclaim.test.ts), [`test/x402.test.ts`](../test/x402.test.ts), [`test/mcp.test.ts`](../test/mcp.test.ts) | L2 is still consumer-supplied evidence. A malicious consumer can withhold proofs, and settlement must still treat L1/oracle evidence as authoritative on failure, ambiguity, and expiry. |
|
|
44
45
|
|
|
@@ -52,7 +53,7 @@ These are the autonomous fund-moving paths in the current agent layer:
|
|
|
52
53
|
4. `VerifiedStreamAgentClient.reclaimStream()`
|
|
53
54
|
5. MCP `hire_verified_service`
|
|
54
55
|
6. MCP `reclaim_unspent`
|
|
55
|
-
7.
|
|
56
|
+
7. Metrik `402` `open()` via `VerifiedStreamFacilitator`
|
|
56
57
|
|
|
57
58
|
All of them now pass a signed mandate check before the SDK can send a write.
|
|
58
59
|
|