Built with Chang Kai Zhe, Apr 2026

DeFi pool health scoring

Pool health scoring over MCP

Capability

No move yet

No move yet

Result and evidence

  • Pool health scoring over MCPCapabilityClassifier scores are from a labelled training set, not measured on live pools.

The case

Problem
A new liquidity pool can be drained within hours of launch. Someone about to trade it, or an agent about to recommend it, needs a risk read in the first hour, not after the fact.
Decision
Split ingestion from judgement. An async Python worker polls GeckoTerminal, drops pools it has already seen with a Bloom filter, and queues the rest in Redis. Rails 8 scores each pool, keeps its history in PostgreSQL, pushes it to the dashboard over Turbo Streams, and answers agents through an MCP server.
Constraint
Only what a pool shows in its first hour can feed the score.
Example
Input: a pool address and network. Output: a 0-100 health score, SAFE, WARNING or DANGER, a recommendation such as DO_NOT_TRADE, and flags such as critical_low_liquidity or wash_trading_suspected.
Considered and rejected
A single-page frontend: the dashboard is server-rendered Hotwire, so a new scan reaches the page without a client app.

Architecture

  1. GeckoTerminalnew pools
  2. Python workerBloom filter
  3. Redisqueue
  4. Rails 8score

Beside the path

  1. Hotwirelive dashboard
  2. MCP serveragent tools

Around it

  1. PostgreSQLscan history

What was built

  1. An asyncio ingestion worker with a scalable Bloom filter for duplicates and back-off on GeckoTerminal rate limits.
  2. A risk calculator that scores with an XGBoost classifier on five first-hour features, and falls back to liquidity, wash-trading and pool-age rules when the model is unavailable.
  3. A live Hotwire dashboard, with the N+1 query on the pool list removed by tracking each pool's latest scan.
  4. An MCP server with tools to analyse a token, get a pool's status, list tracked tokens and check the backend, with a static fallback when Rails is unreachable.
  5. Dockerfiles for running the Rails app and the worker as separate ECS Fargate tasks.
Limitations
The classifier's near-perfect test scores come from the training pipeline's labelled set, which it can generate synthetically; they are not a measurement on live pools, so none is quoted here. The 500-user MCP load test is written but has no recorded run.
What I would change now
Label real pools that were drained, measure the classifier against them, and run the load test.

Built with Chang Kai Zhe; both of us committed to the repository.

Python · asyncio · Redis · Rails 8 · Hotwire · PostgreSQL · XGBoost · MCP

Next, 1…Nf6Financial Risk Predictor