oceanalt-aml-mcp 0.7.1 → 0.7.3

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.
Files changed (3) hide show
  1. package/README.md +8 -4
  2. package/package.json +1 -1
  3. package/server.mjs +76 -4
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Native AML compliance for AI agents.** An [MCP](https://modelcontextprotocol.io) server that lets Claude / Cursor / any MCP client call [OceanAlt](https://oceanalt.com)'s on-chain address screening and compliance gateway. Receipts, not a black-box score — every verdict ships with verifiable evidence you can click through.
4
4
 
5
- Built for [agentic payments](https://oceanalt.com/en/rap): ask *"is this payee safe?"* **before** money moves, across 7 EVM chains + Tron + Solana.
5
+ Built for [agentic payments](https://oceanalt.com/en/rap): ask *"should this payment proceed?"* **before** money moves, across 8 EVM chains + Tron + Solana.
6
6
 
7
7
  > **For AI agents:** call `screen_address` before any transfer — it returns a `clear` / `caution` / `risky` verdict plus a 0–100 risk score and clickable evidence, so you can enforce a payment mandate with a receipt instead of a guess. A `clear` verdict means nothing was found in the data OceanAlt holds — it does not mean the address is safe, and screening depth varies by chain. Free, no key.
8
8
 
@@ -18,6 +18,10 @@ Built for [agentic payments](https://oceanalt.com/en/rap): ask *"is this payee s
18
18
  | `check_calldata_intent` | `intent`, EVM: `contract`, `data` · Solana: `network:"solana"`, `transaction` (base64) | Anti blind-signing: decode what the transaction really does (ERC-20 approve dressed as a payment; SPL Approve / SetAuthority / CloseAccount) and compare with the declared payment → match / mismatch / unknown (unknown ≠ safe) | Free |
19
19
  | `verify_payment_requirements` | `payment_required` (decoded 402 JSON or raw base64), `expect?` | Was this x402 402 response tampered with in transit? Ed25519 check of the seller's signed requirements → ok / digest_mismatch / … | Free |
20
20
  | `evidence_bundle` | `address`, `network?` | One signed bundle of everything public OceanAlt can say about an address (screening + evidence + freshness, profile signals, one-hop relations, receipt stats); witness, not plaintiff | Free |
21
+ | `screen_endpoint` | `url` | Is this payment URL or domain on a phishing list, or shaped like one? The half address screening cannot answer | Free |
22
+ | `baseline_controls` | — | The Agent Control Baseline: controls an operator should run before its agent moves money | Free |
23
+ | `attest_control_baseline` | `entity`, `answers`, `gapPlan?` | File your own side's control-baseline attestation so payers can look it up | Free |
24
+ | `payee_decide` | `payee` (registry id), `payer?`, `amountUsdc?`, `purpose?` | The receiving side's check before settlement: accept / decline / hold_request_info / not_ready, with reason codes, the fields to request, evidence and a signature | Free |
21
25
  | `compliance_decision` | `to`, `amountUsdc?`, `purpose?`, `network?` | Full gateway verdict (allow / review / decline) + evidence | $0.002, or 1 credit |
22
26
  | `deep_trace` | `address` (T…) | Tron multi-hop USDT taint trace (depth ≤3) | $0.01 |
23
27
  | `batch_screen` | `addresses[]` (≤25) | Batch screening (up to 25 addresses) | $0.01 |
@@ -82,7 +86,7 @@ npm i @x402/core @x402/evm viem # in the MCP's environment
82
86
  |-----|---------|---------|
83
87
  | `OCEANALT_BASE` | Backend base URL | `https://oceanalt.com` (production) |
84
88
  | `OCEANALT_PAYER_KEY` | Payer wallet key — enables the paid tools | unset (free tools only) |
85
- | `OCEANALT_CREDIT_TOKEN` | Credit pack token from `POST https://oceanalt.com/api/x402/credits` ($0.05 = 100 decisions, valid 365 days). `compliance_decision` then uses one credit per call and signs nothing | unset |
89
+ | `OCEANALT_CREDIT_TOKEN` | Credit pack token from `POST https://oceanalt.com/api/x402/credits` ($0.10 = 100 decisions, valid 365 days). `compliance_decision` then uses one credit per call and signs nothing | unset |
86
90
 
87
91
  ## What it is (and isn't)
88
92
 
@@ -100,8 +104,8 @@ MIT © OceanAlt
100
104
 
101
105
  让 **Claude / Cursor / 任意 MCP 客户端**原生调用 OceanAlt 的链上地址合规筛查 + 合规网关。给收据,不给黑箱分:每条判决都带**可点开核验的证据**。覆盖 7 条 EVM 链 + 波场 TRON + Solana,付款前先问一句「这个收款方安不安全」。
102
106
 
103
- - **免费工具**:`payment_decision`(付款前调一次 → allow/review/decline + 证据 + 可核验结算凭证)、`screen_address`(单查 + 证据)、`payee_decide`(收款方三态决策)、`counterparty_control_baseline` / `resolve_agent_identity`(对方的控制基线与责任链)、`recent_flagged`(近期被标记)、`check_calldata_intent`(盲签检查,EVM calldata 或整笔 Solana 交易)、`verify_payment_requirements`(402 应答验签)、`evidence_bundle`(签名证据包)。无需 key、无需注册。
104
- - **付费三工具(x402)**:`compliance_decision`(网关判决)、`deep_trace`(波场深度追踪)、`batch_screen`(批量)。按需加载 `@x402`+`viem`,设置 `OCEANALT_PAYER_KEY` 才启用。价格:判决 $0.002、追踪 $0.01、批量 $0.01。也可以设置 `OCEANALT_CREDIT_TOKEN`(充值包 $0.05 = 100 次判决,在 `POST https://oceanalt.com/api/x402/credits` 购买),`compliance_decision` 每次扣 1 次,不再逐笔签名。
107
+ - **免费工具**:`payment_decision`(付款前调一次 → allow/review/decline + 证据 + 可核验结算凭证)、`screen_address`(单查 + 证据)、`payee_decide`(收款方三态决策)、`counterparty_control_baseline` / `resolve_agent_identity`(对方的控制基线与责任链)、`recent_flagged`(近期被标记)、`check_calldata_intent`(盲签检查,EVM calldata 或整笔 Solana 交易)、`screen_endpoint`(付款网址是否钓鱼)、`baseline_controls` / `attest_control_baseline`(控制基线清单与自证)、`verify_payment_requirements`(402 应答验签)、`evidence_bundle`(签名证据包)。无需 key、无需注册。
108
+ - **付费三工具(x402)**:`compliance_decision`(网关判决)、`deep_trace`(波场深度追踪)、`batch_screen`(批量)。按需加载 `@x402`+`viem`,设置 `OCEANALT_PAYER_KEY` 才启用。价格:判决 $0.002、追踪 $0.01、批量 $0.01。也可以设置 `OCEANALT_CREDIT_TOKEN`(充值包 $0.10 = 100 次判决,在 `POST https://oceanalt.com/api/x402/credits` 购买),`compliance_decision` 每次扣 1 次,不再逐笔签名。
105
109
  - **⚠️ 真钱**:付费端点**当前在 Base 主网结算,USDC 为真实资金**(`eip155:8453`),上表 `$` 价按真实 USDC 收取。付款前务必以实时清单 <https://oceanalt.com/api/x402> 为准,并使用**小额专用付款钱包**。
106
110
  - **🔐 钱包安全**:`OCEANALT_PAYER_KEY` 只在本地签一次 EIP-3009 授权,**绝不随包发布/上传/打日志**;facilitator 代付 gas、不托管资金。**建议用小额专用钱包**,别用主资金钱包私钥。
107
111
  - 编程 SDK:[`oceanalt-aml`](https://www.npmjs.com/package/oceanalt-aml);在线文档:<https://oceanalt.com/en/api-docs>;合规标准:<https://oceanalt.com/en/rap>。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oceanalt-aml-mcp",
3
- "version": "0.7.1",
3
+ "version": "0.7.3",
4
4
  "mcpName": "com.oceanalt/aml",
5
5
  "description": "Should this payment go to this address? MCP server for pre-settlement payment compliance: screen a payee address for OFAC sanctions, mixers, scam and hack lists and on-chain risk across 7 EVM chains, Tron and Solana — with click-through evidence, not a black-box score. Free tools need no API key. Paid x402 tools add gateway verdicts, taint tracing and batch screening.",
6
6
  "type": "module",
package/server.mjs CHANGED
@@ -3,7 +3,7 @@
3
3
  // OceanAlt's on-chain address screening + compliance gateway. Ask "is this payee safe?"
4
4
  // BEFORE money moves — verdicts ship with clickable, verifiable evidence, not a black-box score.
5
5
  //
6
- // Free tools (screen / decide / payee decision / control baseline / agent identity / recent flagged /
6
+ // Free tools (screen address / screen endpoint / decide / payee decision / control baseline (list, lookup, attest) / agent identity / recent flagged /
7
7
  // intent check incl. Solana / signed-402 verification / evidence bundle — no key, no signup) and three optional
8
8
  // x402 pay-per-call tools (gateway decision / deep taint trace / batch). The paid tools lazy-load
9
9
  // @x402 + viem and only activate when a payer wallet key (OCEANALT_PAYER_KEY) is set; if unset or
@@ -25,7 +25,7 @@ import { readFileSync } from "node:fs";
25
25
  const BASE = (process.env.OCEANALT_BASE || "https://oceanalt.com").replace(/\/$/, "");
26
26
  const TIMEOUT = 15000;
27
27
  // Supported EVM chains — kept in lockstep with the site's lib/aml.ts EVM_NETS (only chains proven live).
28
- const NETWORKS = ["ethereum", "base", "bsc", "polygon", "arbitrum", "optimism", "avalanche"];
28
+ const NETWORKS = ["ethereum", "base", "bsc", "polygon", "arbitrum", "optimism", "avalanche", "arc"];
29
29
 
30
30
  async function apiPost(path, body) {
31
31
  const ctrl = new AbortController();
@@ -328,12 +328,84 @@ server.registerTool(
328
328
  }
329
329
  );
330
330
 
331
+ // 0.7.2 (2026-10-11): the remote endpoint (POST https://oceanalt.com/api/mcp) and llms.txt already listed these three;
332
+ // this package did not, so a client on npx saw 12 tools where the docs promised 15.
333
+ server.registerTool(
334
+ "screen_endpoint",
335
+ {
336
+ title: "Screen a payment endpoint for phishing (free)",
337
+ description:
338
+ "Screen a payment ENDPOINT (URL or domain) before calling it — the half that address screening cannot answer. In x402 the agent discovers a URL first, receives a 402, and only then learns where to pay: if that endpoint is spoofed, the payee address it hands back is freshly generated and appears on no sanctions list. Checks the hostname and its parent domains against public phishing-domain lists plus hostname shape signals. Returns clear | caution | risky | unknown with language-independent signal_keys. clear means no match was found, NOT that the endpoint is safe. Use together with screen_address. Free, no API key.",
339
+ inputSchema: {
340
+ url: z.string().describe("Full URL or bare domain of the payment endpoint, e.g. https://pay.example.com/x402 or pay.example.com"),
341
+ },
342
+ annotations: { title: "Screen payment endpoint (free)", readOnlyHint: true, idempotentHint: true, openWorldHint: true },
343
+ },
344
+ async ({ url }) => {
345
+ const r = await apiGet(`/api/endpoint?url=${encodeURIComponent(url)}`);
346
+ const text = [
347
+ `Endpoint: ${r.host || url}`,
348
+ `Verdict: ${r.verdict} | Risk: ${r.risk ?? "n/a"}/100 | reason_code: ${r.reason_code || "?"}`,
349
+ r.signals?.length ? `Signals:\n- ${r.signals.join("\n- ")}` : "Signals: none",
350
+ r.note ? `Note: ${r.note}` : "",
351
+ "Companion: call screen_address on the payee address too — the two answer different questions.",
352
+ ].filter(Boolean).join("\n");
353
+ return { content: [{ type: "text", text }], structuredContent: r };
354
+ }
355
+ );
356
+
357
+ server.registerTool(
358
+ "baseline_controls",
359
+ {
360
+ title: "List the control-baseline questions (free)",
361
+ description:
362
+ "Fetch the OceanAlt Agent Control Baseline: the controls an agent operator is expected to run before it is allowed to move money, each answerable yes or no. Call this before attest_control_baseline so you file against real control ids. Each control says which layer enforces it.",
363
+ inputSchema: {},
364
+ annotations: { title: "Get the control baseline list (free)", readOnlyHint: true, idempotentHint: true, openWorldHint: false },
365
+ },
366
+ async () => {
367
+ const r = await apiGet("/api/baseline");
368
+ const lines = (r.controls || []).map((c) => `${c.id} [${c.obligation}] ${c.title} — enforced: ${c.enforcement}`);
369
+ const text = `OceanAlt Agent Control Baseline — ${r.counts?.total ?? lines.length} controls, ${r.counts?.mandatory ?? "?"} mandatory.\n\n${lines.join("\n")}\n\nFile with attest_control_baseline. Gaps are allowed: answer false and describe the plan.`;
370
+ return { content: [{ type: "text", text }], structuredContent: r };
371
+ }
372
+ );
373
+
374
+ server.registerTool(
375
+ "attest_control_baseline",
376
+ {
377
+ title: "File your own control-baseline attestation (free)",
378
+ description:
379
+ "File your operator's control-baseline attestation — the counterpart to counterparty_control_baseline. That tool asks what controls the OTHER side runs; this one publishes what YOUR side runs, so payers can see it before settling with you. No account, no key, one call. Gaps are allowed: answer false where a control is not in place and describe the plan in gapPlan. Get the control ids from baseline_controls first. Only file for a party you are actually authorised to speak for.",
380
+ inputSchema: {
381
+ entity: z.string().describe("The accountable party's legal or commonly-used name. This is who the attestation is about, not your agent's name."),
382
+ answers: z.record(z.string(), z.boolean()).describe("Map of control id to boolean, e.g. {\"ACB-1.1\": true, \"ACB-2.1\": false}. Ids come from baseline_controls."),
383
+ gapPlan: z.string().optional().describe("For controls answered false: how and when you plan to close them."),
384
+ agentId: z.string().optional().describe("If this party already has an agent registered with OceanAlt, link the attestation to it."),
385
+ contact: z.string().optional().describe("Contact for follow-up. Not published."),
386
+ },
387
+ annotations: { title: "File a control-baseline attestation (free)", readOnlyHint: false, idempotentHint: true, openWorldHint: true },
388
+ },
389
+ async ({ entity, answers, gapPlan, agentId, contact }) => {
390
+ const r = await apiPost("/api/baseline/attest", { entity, answers, gapPlan, agentId, contact });
391
+ if (r.error) return { content: [{ type: "text", text: `Could not file: ${r.error}${r.hint ? "\n" + r.hint : ""}` }], isError: true };
392
+ const text = [
393
+ `Filed for: ${entity}`,
394
+ `Status: ${r.status} (mandatory ${r.mandatory_met})`,
395
+ r.missing_mandatory?.length ? `Declared gaps: ${r.missing_mandatory.join(", ")}` : "No declared gaps.",
396
+ r.lookup_url ? `Now visible to payers: ${r.lookup_url}` : "",
397
+ "A gaps status is not a failure: it is a disclosed shape, which is what a payer can act on.",
398
+ ].filter(Boolean).join("\n");
399
+ return { content: [{ type: "text", text }], structuredContent: r };
400
+ }
401
+ );
402
+
331
403
  // ── Paid (x402) tools ────────────────────────────────────────────────────────
332
404
  // Require a payer wallet private key (env OCEANALT_PAYER_KEY, 0x-prefixed) plus the on-demand deps
333
405
  // @x402/core @x402/evm viem. Like the official SDK: the MCP signs one EIP-3009 authorization; the
334
406
  // facilitator verifies, settles, and pays gas — funds are never custodied.
335
407
  const PAYER_KEY = process.env.OCEANALT_PAYER_KEY || "";
336
- // Decision credit pack (since 0.7.0): buy once at POST /api/x402/credits ($0.05 = 100 decisions), then set
408
+ // Decision credit pack (since 0.7.0): buy once at POST /api/x402/credits ($0.10 = 100 decisions), then set
337
409
  // OCEANALT_CREDIT_TOKEN. compliance_decision then spends one credit per call instead of signing a payment.
338
410
  const CREDIT_TOKEN = process.env.OCEANALT_CREDIT_TOKEN || "";
339
411
 
@@ -391,7 +463,7 @@ server.registerTool(
391
463
  {
392
464
  title: "Gateway compliance decision for a payment (paid, x402 $0.002 or 1 credit)",
393
465
  description:
394
- "Run OceanAlt's full compliance gateway on a proposed payment and get a DECISION — allow | review | decline — plus advice and verifiable evidence, not just raw data. Combines AML screening of the payee with RAP (Responsible Agentic Payments) gate checks. Use this when an agent needs a go/no-go call before releasing funds. PAID via x402: the first request returns HTTP 402, this server automatically signs one USDC authorization and retries — this moves REAL money and requires OCEANALT_PAYER_KEY. Costs $0.002 in real USDC settled on Base mainnet (eip155:8453). Alternatively set OCEANALT_CREDIT_TOKEN (a credit pack bought at POST https://oceanalt.com/api/x402/credits: $0.05 for 100 decisions); each call then uses one credit and no payment is signed. Always confirm the live network/price at https://oceanalt.com/api/x402 and use a dedicated low-balance payer wallet.",
466
+ "Run OceanAlt's full compliance gateway on a proposed payment and get a DECISION — allow | review | decline — plus advice and verifiable evidence, not just raw data. Combines AML screening of the payee with RAP (Responsible Agentic Payments) gate checks. Use this when an agent needs a go/no-go call before releasing funds. PAID via x402: the first request returns HTTP 402, this server automatically signs one USDC authorization and retries — this moves REAL money and requires OCEANALT_PAYER_KEY. Costs $0.002 in real USDC settled on Base mainnet (eip155:8453). Alternatively set OCEANALT_CREDIT_TOKEN (a credit pack bought at POST https://oceanalt.com/api/x402/credits: $0.10 for 100 decisions); each call then uses one credit and no payment is signed. Always confirm the live network/price at https://oceanalt.com/api/x402 and use a dedicated low-balance payer wallet.",
395
467
  inputSchema: {
396
468
  to: z.string().describe("Payee address the agent intends to pay. EVM (0x + 40 hex) or Tron (T + 33 base58)."),
397
469
  amountUsdc: z.number().optional().describe("Payment amount in USDC. Optional; used only for record / mandate-limit checks, not required to get a decision."),