chainhint-mcp 1.3.0 → 1.3.1

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 CHANGED
@@ -86,6 +86,8 @@ Add an Agency key to the server entry (any client):
86
86
  Free tier: 2 of 3 checks left today — set CHAINHINT_API_KEY (Agency plan, https://chainhint.com/pricing) for 10,000/day.
87
87
  ```
88
88
 
89
+ When the address is in ChainHint's agent-infrastructure registry (agent-token launchpads, deployer factories, routers, payment facilitators, known agent wallets), the report adds an `🤖` line, e.g. *Known agent infrastructure: Virtuals launchpad* — a registry fact you can verify at its source, not a behavioural classification and not part of the risk score.
90
+
89
91
  ## Development (no build step)
90
92
 
91
93
  ```bash
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ const API_KEY = process.env.CHAINHINT_API_KEY;
22
22
  const BASE_URL = process.env.CHAINHINT_API_URL ?? "https://kjiwfwymnuzxriokhcjk.supabase.co/functions/v1";
23
23
  const SUPABASE_URL = process.env.CHAINHINT_SUPABASE_URL ?? "https://kjiwfwymnuzxriokhcjk.supabase.co";
24
24
  const SUPABASE_ANON_KEY = process.env.CHAINHINT_SUPABASE_ANON_KEY ?? "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImtqaXdmd3ltbnV6eHJpb2toY2prIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzI3MzkxODgsImV4cCI6MjA4ODMxNTE4OH0.VqzzF_jI8zF072cbjWEDbYo3PnMDlIPy621iWkXEqyo";
25
- const VERSION = "1.1.0";
25
+ const VERSION = "1.3.1";
26
26
  const USER_AGENT = `chainhint-mcp/${VERSION}`;
27
27
  const FREE_CHECKS_PER_DAY = 3;
28
28
  const UPGRADE_HINT = "set CHAINHINT_API_KEY (Agency plan, https://chainhint.com/pricing) for 10,000/day";
@@ -196,11 +196,29 @@ function formatExposure(label, buckets) {
196
196
  }),
197
197
  ];
198
198
  }
199
+ /**
200
+ * Same rule as chainhint.com (src/lib/attackerAttribution.ts): an address is
201
+ * "the attacker" only when the attribution was checked against the exploit
202
+ * transaction (attacker_address_source = analyst_verified). Everything else is
203
+ * a report — shown as one, and never as a HIGH-risk verdict.
204
+ */
205
+ function attackerAttribution(inc) {
206
+ if (!inc.attacker_address)
207
+ return { verified: false, label: "Attacker not identified" };
208
+ if (inc.attacker_address_source === "analyst_verified")
209
+ return { verified: true, label: "Attacker" };
210
+ return {
211
+ verified: false,
212
+ label: inc.source === "defillama"
213
+ ? "Reported attacker (DeFiLlama), unverified"
214
+ : "Reported attacker (user-provided), unverified",
215
+ };
216
+ }
199
217
  /** Public incident whose attacker_address matches, or null (errors swallowed — best effort). */
200
218
  async function findPublicIncidentByAttacker(address) {
201
219
  try {
202
220
  const rows = await supabaseGet("public_incidents_view", {
203
- select: "id,title,chain,amount_usd,estimated_loss_usd,risk_score",
221
+ select: "id,title,chain,amount_usd,estimated_loss_usd,risk_score,source,attacker_address_source",
204
222
  attacker_address: `eq.${normalizeAddr(address)}`,
205
223
  limit: "1",
206
224
  });
@@ -241,7 +259,11 @@ server.tool("check_wallet_risk", "Fast risk check for a crypto wallet address ag
241
259
  lines.push(`**Risk:** âšĒ NO DATA — address is not in ChainHint's labeled database. This is not evidence it is clean.`);
242
260
  const inc = await findPublicIncidentByAttacker(d.address);
243
261
  if (inc) {
244
- lines.push(`âš ī¸ **Known attacker in a public hack incident:** ${inc.title ?? "Unnamed incident"} (${inc.chain}, loss ${usd(inc.amount_usd ?? inc.estimated_loss_usd)}${inc.risk_score != null ? `, incident risk ${inc.risk_score}/100` : ""}). Treat as HIGH risk.`, `🔗 https://chainhint.com/incident/${inc.id}`);
262
+ const attribution = attackerAttribution({ attacker_address: d.address, ...inc });
263
+ const where = `${inc.title ?? "Unnamed incident"} (${inc.chain}, loss ${usd(inc.amount_usd ?? inc.estimated_loss_usd)}${inc.risk_score != null ? `, incident risk ${inc.risk_score}/100` : ""})`;
264
+ lines.push(attribution.verified
265
+ ? `âš ī¸ **Verified attacker in a public hack incident:** ${where}. The attribution was checked against the exploit transaction. Treat as HIGH risk.`
266
+ : `â„šī¸ **${attribution.label}, in a public hack incident:** ${where}. This attribution has not been verified against the exploit transaction — treat it as a lead to check, not as a risk verdict.`, `🔗 https://chainhint.com/incident/${inc.id}`);
245
267
  }
246
268
  lines.push(`Use lookup_address for an on-chain assessment (risk factors, GoPlus flags, counterparty exposure).`);
247
269
  }
@@ -375,7 +397,7 @@ server.tool("get_trace_status", "Fund-trace summary for a publicly tracked crypt
375
397
  // public_incidents_view is the canonical anonymous read path (SECURITY DEFINER,
376
398
  // exposes only is_public rows and only public-safe columns).
377
399
  const queryParams = {
378
- select: "id,title,status,chain,attacker_address,amount_usd,estimated_loss_usd,risk_score,incident_type,hack_date,display_date,created_at,updated_at,source,endpoints,flow_graph,counterparty_exposure",
400
+ select: "id,title,status,chain,attacker_address,attacker_address_source,amount_usd,estimated_loss_usd,risk_score,incident_type,hack_date,display_date,created_at,updated_at,source,endpoints,flow_graph,counterparty_exposure",
379
401
  limit: "1",
380
402
  order: "created_at.desc",
381
403
  };
@@ -406,7 +428,7 @@ server.tool("get_trace_status", "Fund-trace summary for a publicly tracked crypt
406
428
  `**Incident ID:** ${inc.id}`,
407
429
  `**Chain:** ${inc.chain}`,
408
430
  `**Status:** ${status.toUpperCase()}`,
409
- `**Attacker:** ${inc.attacker_address}`,
431
+ `**${attackerAttribution(inc).label}:** ${inc.attacker_address ?? "—"}`,
410
432
  `**Loss:** ${usd(lossUsd)}`,
411
433
  `**Date:** ${date.slice(0, 10)}`,
412
434
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chainhint-mcp",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "ChainHint MCP server — crypto risk intelligence tools for Claude Desktop and Cursor",
5
5
  "license": "MIT",
6
6
  "repository": {