Honeypot and rug-pull check API for AI agents

One call before your agent buys a token: a sell simulation, the taxes, liquidity depth, pair age and same-ticker impersonation, rolled into low, medium, high or unknown with every signal behind it. Remote MCP server and plain HTTP. Free, no account, no API key.

Connect over MCP

Streamable HTTP at https://vetagent.dev/mcp. Any MCP client that accepts a remote server URL works; for one that reads a JSON config:

{
  "mcpServers": {
    "vetagent": { "type": "http", "url": "https://vetagent.dev/mcp" }
  }
}

Three tools: assess_token_risk (the verdict), get_token_liquidity (price and depth only) and find_new_hot_pools (discovery, never an endorsement).

Or call it over HTTP

# the address in the body, which keeps it out of URLs and logs along the way
curl -X POST https://vetagent.dev/assess \
  -H 'content-type: application/json' \
  -d '{"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "chain_hint": "base"}'

# convenient, but the address travels in the URL
curl "https://vetagent.dev/assess/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913?chain_hint=base"

What comes back

A shortened real answer for USDC on Base (evidence trimmed):

{
  "risk_level": "low",
  "risk_score": 0,
  "confidence": "high",
  "driver": null,
  "signals": [
    {"severity": "ok", "name": "Liquidity is adequate", "category": "liquidity"},
    {"severity": "ok", "name": "Buys and sells normally", "category": "honeypot"}
  ],
  "recommendation": "Low risk: sellable and liquid when checked, no fatal signal. ...",
  "checked_at": "2026-09-15T05:17:23Z",
  "evidence_max_age_seconds": 0
}
FieldHow an agent should read it
risk_levellow means no fatal signal in the checks that ran — the exit was open when we looked, not that nobody can close it. medium: real signals, none fatal; surface them. high: do not proceed unreviewed. unknown: a critical check could not run — never a green light.
driverThe one signal that decided the verdict, by name and category. null when nothing above ok fired.
confidenceHow complete the input data was, not how safe the token is. An answer that leaned on cached data is at most medium.
unknown_kind, next_actionOnly on unknown: whether to retry (our upstream failed) or abstain (nothing can see the token).
checked_at, evidence_max_age_secondsWhen the answer was made, and how old its oldest evidence is.

What it checks, and where

CheckChains
Buy/sell simulation (honeypot), buy/sell/transfer taxEthereum, BSC, Base
Mint and freeze authority, top-10 holder concentrationSolana
Liquidity depth — counted only for reserves held in independently priced assets, so a pool priced in its creator's own token cannot buy a lowEthereum, BSC, Base, Arbitrum, Optimism, Polygon, Avalanche, Solana; elsewhere the depth a pool states is used as stated
Pair age, 24h turnover across the token's poolsEvery chain
Same-ticker impersonation, within one chainEvery chain
Owner powers in the bytecode (blacklist, tax change, pause, mint) — disclosed, never scoredEthereum, BSC, Base

On a chain the sell simulator does not cover, the answer says so and comes back unknown rather than pretending the check ran. Pass chain_hint (ethereum, bsc, base, arbitrum, polygon, optimism, avalanche, solana): the same address can exist on several chains, and without a hint an answer covers the one holding the most depth and names it.

Limits

About 60 tool calls a minute per caller, then HTTP 429 with Retry-After. At most 10 messages in one JSON-RPC batch. The token address you look up is not logged. How accurate it is, including the numbers that make it look worst, is on the method page.