Rugsight
Official# Rugsight
**See the rug before it's pulled.** Rugsight scores the rug-pull risk of any Solana SPL token from public on-chain data, and explains every flag. It is built for humans and for AI agents.
- **Live:** https://rugsight.rugsight.workers.dev
- **Free API:** `GET https://rugsight.rugsight.workers.dev/api/score/{mint}` (score, grade, verdict, flag codes)
- **Paid API for agents (x402):** `GET https://rugsight.rugsight.workers.dev/api/v1/report?mint={mint}`, **0.03 USDC per call** on Solana mainnet. No API key, no signup.
- **Remote MCP server:** `https://rugsight.rugsight.workers.dev/mcp` (streamable HTTP). Tools: `get_token_risk_score` (free) and `get_token_risk_report` (x402, 0.03 USDC).
- **Humans:** the full report on the website costs 1 USDC (or the same value in SOL), paid with Solana Pay. Payments are crypto-only.
- **Discovery:** `/.well-known/x402`, `/openapi.json`, `/llms.txt`, `/.well-known/mcp/server-card.json`
```bash
# free score for BONK
curl https://rugsight.rugsight.workers.dev/api/score/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263
```
MCP client config (any client that supports remote streamable-HTTP servers):
```json
{ "mcpServers": { "rugsight": { "url": "https://rugsight.rugsight.workers.dev/mcp" } } }
```
> **Not financial advice.** Rugsight publishes automated technical analysis of public blockchain data.
> A good score does not mean a token is safe, and a bad score does not mean it is a scam. Do your own research.
## Stack ($0 to run)
| Piece | Service | Cost |
|---|---|---|
| API + static site | Cloudflare Workers + static assets | free tier |
| Orders | Cloudflare D1 (SQLite) | free tier |
| Cache (scores 5 min, reports 7 days, SOL price 2 min) | Cloudflare KV | free tier |
| Chain data | Solana JSON-RPC: Helius free key, or any RPC | free tier |
| Market data | DexScreener public API (all pools), falling back to Jupiter token API, then a last-good KV copy (<30 min); used for our own metrics only | free |
| Payments | Solana Pay transfer requests, checked on-chain | network fee is paid by the buyer |
| Agent payments | x402 v2 (v1 compatible) through the PayAI facilitator (1,000 free credits, no key) | free |
## What it checks
Each score starts at 100. Every risk flag subtracts points. Grades: A ≥ 85, B ≥ 70, C ≥ 50, D ≥ 30, F otherwise.
| Area | Flags (points) |
|---|---|
| Authorities | `MINT_AUTHORITY_ACTIVE` (30), `FREEZE_AUTHORITY_ACTIVE` (20) |
| Token-2022 extensions | `PERMANENT_DELEGATE` (25), `NON_TRANSFERABLE` (40), `TRANSFER_HOOK` (10), `DEFAULT_FROZEN` (15), `HIGH_TRANSFER_FEE` (15) / `TRANSFER_FEE` (4), `PAUSABLE` (10) |
| Holders: wallets only, excluding pools, programs and burn addresses | `TOP10_ELEVATED` (10), `TOP10_HIGH` (20), `TOP10_EXTREME` (30), `TOP1_LARGE` (8), `TOP1_WHALE` (15), `FEW_HOLDERS` (4/8) |
| Liquidity | `NO_LIQUIDITY` (25), `LIQUIDITY_UNMEASURED` (20), `LIQUIDITY_VERY_LOW` (20), `LIQUIDITY_LOW` (10), `LIQUIDITY_MODERATE` (5), `BONDING_CURVE` (10) |
| Age | `VERY_NEW` (15), `NEW` (8), `YOUNG` (3) |
If holder data cannot be read (for example, tokens with millions of holders such as USDC, which RPCs refuse to rank), the result is marked `confidence: "partial"` and the grade is capped at B.
**Data policy:** we publish only metrics we compute ourselves: scores, flags, buckets and percentages.
We do not pass on raw third-party data. For example, liquidity and volume appear as ranges, not as DexScreener's figures.
## API
| Method | Path | Description |
|---|---|---|
| GET | `/api/score/:mint` | Free basic score: score, grade, verdict, flag codes and confidence |
| POST | `/api/orders` `{"mint","currency":"USDC"\|"SOL"}` | Creates a 1-USD order. Returns a Solana Pay URL, a QR code, and status and report URLs |
| GET | `/api/orders/:id` | Order status. Checks the chain for a payment that carries the order's reference key |
| GET | `/api/orders/:id/qr.svg` | Solana Pay QR code |
| GET | `/api/report/:id` | Full report. Returns `402` until the order is paid |
| GET | `/api/v1/report?mint=<mint>` | x402 pay-per-call full report (0.03 USDC). Also `/api/v1/report/:mint` |
| POST | `/mcp` | Remote MCP server (streamable HTTP): `get_token_risk_score` (free), `get_token_risk_report` (x402 over MCP) |
| GET | `/.well-known/x402`, `/openapi.json`, `/llms.txt`, `/.well-known/mcp/server-card.json` | Discovery documents |
| GET | `/api/health` | Shows whether payments, x402 (and whether the treasury USDC account exists) and the RPC are configured |
Example:
```bash
curl https://<your-worker>/api/score/DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263
```
### x402 pay-per-call (agents)
1. An unpaid `GET /api/v1/report?mint=…` returns `402`. The `PAYMENT-REQUIRED` header carries the base64 x402 v2 `PaymentRequired` (scheme `exact`, network `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`, 30000 base units of USDC to the treasury, fee payer = PayAI sponsor, Bazaar discovery extension). The body carries the x402 v1 form for older clients.
2. The client retries with `PAYMENT-SIGNATURE` (v2) or `X-PAYMENT` (v1).
3. The worker decodes the partially signed transaction and rejects it locally if the fee payer, the destination ATA, the mint or the amount is wrong. Then it calls the facilitator's `/verify`.
4. It builds the report. If that fails, it answers `503` and does **not** settle, so the payer is not charged.
5. It calls `/settle`, returns the report with `PAYMENT-RESPONSE`, and logs the settlement in `x402_payments`.
The treasury must own a USDC token account (`TREASURY_USDC_ATA`) before x402 transfers can land; `/api/health` reports `x402PayToReady`.
### How a Solana Pay payment is verified
1. `POST /api/orders` creates a random `reference` public key and stores the order in D1.
2. The buyer's wallet opens `solana:<TREASURY>?amount=..&spl-token=<USDC>&reference=<ref>`. The `spl-token` parameter is left out for SOL payments.
3. `GET /api/orders/:id` calls `getSignaturesForAddress(reference)` and `getTransaction`. It accepts the order only if the transaction succeeded and the treasury's USDC token balance (or SOL balance) rose by at least the quoted amount.
4. `orders.signature` is `UNIQUE`, so one transaction can pay for only one order.
A SOL quote uses the SOL/USD price from DexScreener at order time and is rounded up.
## Local development (no Cloudflare account needed)
```bash
npm install
npm run db:local # apply migrations/0001_init.sql to the local D1
npm run relay # see note below (port 8899)
npm run dev:local # http://localhost:8799
npm run typecheck
npm test # checks the payment verifier against real mainnet transactions (read-only)
npm run analyze -- <mint> # runs the scoring engine directly in Node
```
**RPC note:** the public endpoint `api.mainnet-beta.solana.com` blocks requests sent from Cloudflare Workers.
Those requests carry a `CF-Worker` header, and the endpoint answers 403.
It also rate-limits `getTokenLargestAccounts` (HTTP 429).
For local tests, `test/rpc-relay.mjs` forwards requests without that header.
**In production, set `HELIUS_API_KEY`.** A free Helius key is enough. You can also point `SOLANA_RPC_URL` at another provider.
Without a key, holder data is available only for Token-2022 tokens, such as new pump.fun launches. This comes from an account-scan fallback.
## Run locally (stdio)
`stdio/` is a small MCP server that talks over stdio. It's a thin client for the hosted API, so all analysis runs on the hosted service, and it holds no keys or wallets.
It exposes the same tools as the hosted `/mcp` endpoint:
- `get_token_risk_score`: free. Calls `GET /api/score/<mint>`.
- `get_token_risk_report`: 0.03 USDC per call via x402, settled by the hosted service. Without a payment, the tool returns the `PaymentRequired` object. To pay, retry the `tools/call` with `_meta["x402/payment"]` (an x402 v2 PaymentPayload), and the local server forwards it to the hosted `/mcp`.
```bash
cd stdio && npm ci
node index.js # speaks MCP over stdin/stdout
npm test # smoke test: initialize, tools/list, score for BONK, 402 for the report
```
Claude Desktop, Cursor, or any stdio MCP client:
```json
{ "mcpServers": { "rugsight": { "command": "node", "args": ["/path/to/rugsight/stdio/index.js"] } } }
```
Environment variables:
- `RUGSIGHT_API_URL`: base URL of the API. Defaults to `https://rugsight.rugsight.workers.dev`, and you can point it at your own deployment.
- `RUGSIGHT_TIMEOUT_MS`: request timeout. Defaults to 30000.
Docker: `docker build -t rugsight-mcp . && docker run -i --rm rugsight-mcp`. The image needs Node 18 or later. The Dockerfile uses Node 20.
## Configuration (`wrangler.toml` → `[vars]`; secrets via `wrangler secret put`)
| Var | Default | Notes |
|---|---|---|
| `TREASURY_ADDRESS` | `7Z156pFA5mf1k6hfRdwprztz3DjkXnvfMgGrD7beTqNU` | Receives every payment |
| `REPORT_PRICE_USD` | `1` | Full report price |
| `ORDER_TTL_MINUTES` | `20` | Quote validity. Payments that arrive late are still honoured |
| `SOLANA_RPC_URL` | public mainnet | Ignored when `HELIUS_API_KEY` is set |
| `HELIUS_API_KEY` (secret) | none | Needed in production |
| `PUBLIC_BASE_URL` | `http://localhost:8799` | Set this to the deployed URL |
| `X402_ENABLED` / `X402_PRICE_USDC` / `X402_FACILITATOR_URL` / `X402_NETWORK` / `TREASURY_USDC_ATA` | `true` / `0.03` / PayAI / `solana:5eykt…` / treasury USDC ATA | x402 settings; tests: `npm test` |
## Self-host (deploy your own)
Rugsight runs entirely on the Cloudflare Workers free tier. **Change `TREASURY_ADDRESS`, `TREASURY_USDC_ATA` and `PUBLIC_BASE_URL` in `wrangler.toml` to your own wallet and URL first**, otherwise payments go to the Rugsight treasury.
```bash
npx wrangler login # Cloudflare account (free)
npx wrangler kv namespace create CACHE # copy the id into wrangler.toml
npx wrangler d1 create rugsight # copy database_id into wrangler.toml
npx wrangler d1 migrations apply rugsight --remote
npx wrangler secret put HELIUS_API_KEY
# set PUBLIC_BASE_URL in wrangler.toml to https://rugsight.<subdomain>.workers.dev
npx wrangler deploy
curl https://rugsight.<subdomain>.workers.dev/api/health
```
## Schema
See `migrations/0001_init.sql` (also copied as `schema.sql`).
It has two tables: `orders` (Solana Pay orders) and `x402_payments` (a settlement log for pay-per-call).
## License
[MIT](LICENSE). Contact: yunare-qwerng+rugsight@mail.grokbot.com · X: [@rugsightapp](https://x.com/rugsightapp)
TDQS
Scored across 2 tools
Both tools assess token rug risk, so the underlying purpose overlaps, but the descriptions make the boundary clear: one is a free 0-100 score/grade snapshot, the other is a paid full report with holder and liquidity detail. An agent can reliably pick based on depth and payment willingness, though the near-identical names invite a quick double-check.
Both names follow the same get_token_risk_* snake_case verb_noun pattern with a shared prefix, making the pair read as a deliberate, predictable family. No mixing of conventions.
Two tools is on the thin side even for a narrow risk-scoring service; the surface is essentially one capability offered at two depths. It is defensible for a focused hosted API, but leaves little room for adjacent operations.
The core domain — token risk assessment — is covered at both summary and detailed levels, including flags, holders, liquidity, and pool age, so there are no dead ends for the primary workflow. Minor gaps exist: no batch/multi-token check, no historical or cached report retrieval, and no way to list or search tokens.