Polymarket Intel
About
An MCP server and REST API that classifies Polymarket wallets as human or bot, scores their trading edge from 0–10, and streams their current open positions. Built for AI agents on copy-trading and signal-following stacks.
Details
- Author
- aemery13
- Downloads
- 176
- Categories
- Other
Jump to
- Classifies wallets as human, bot, or insufficient_data with confidence score
- Scores trading edge from 0–10 gated on net realised PnL
- Streams current open positions refreshed every 30 seconds
- Provides historical score time series via daily snapshots
- Distributed as MCP server, REST API, and hosted MCP endpoint
- Includes PnL reconstruction from raw trade and redeem activity
Setting up with Highlight
This MCP is not yet compatible with Highlight’s one-click setup. However, you can still use it with Highlight by following these steps:
- Download and install Highlight from highlightai.com/download
- Navigate to the plugins tab and select "Add Custom Plugin"
-
Configure the plugin with the settings below
Plugin Name
Polymarket IntelCommand (node, npx, python, etc.)Please refer to the README for specific instructions on how to obtain API keys or other required environment variables.
- Enable "Start Automatically" if you want the plugin to start when Highlight launches
From the repository
Install via pip install polymarket-intel-mcp then run polymarket-intel-mcp, or call the hosted REST API directly with curl https://polymarket-intel-production.up.railway.app/.... You can also clone the repo, install dependencies, and use the CLI (python scripts/analyze_wallet.py), the FastAPI REST API (uvicorn api.main:app --reload), or the MCP server (python mcp_server/server.py). The MCP server exposes four tools: score_polymarket_wallet, score_polymarket_user, get_polymarket_leaderboard, and get_open_positions.
Claude Desktop / Cursor
Paste into your MCP client config file to install this server.
{
"mcpServers": {
"polymarket intel": {
"polymarket-intel": {
"command": "python",
"args": [
"-m",
"venv",
".venv",
"&&",
"source",
".venv/bin/activate"
]
}
}
}
}
McpServers
{
"polymarket-intel": {
"command": "python",
"args": [
"-m",
"venv",
".venv",
"&&",
"source",
".venv/bin/activate"
]
}
}
Polymarket Wallet Intelligence
<!-- mcp-name: io.github.aemery13/polymarket-intel -->
An MCP server and REST API that classifies Polymarket wallets as human or bot, scores their trading edge from 0–10, and streams their current open positions. Built for AI agents on copy-trading and signal-following stacks.
# Use it from any MCP client (Claude Desktop, Cursor, etc.)
pip install polymarket-intel-mcp
polymarket-intel-mcp
Or call the hosted REST API directly
curl https://polymarket-intel-production.up.railway.app/wallet/0xf1528f12e645462c344799b62b1b421a6a4c64aa
How this fits with other Polymarket MCP servers
Status
Latest: v1.2 (May 2026) — classifier improved to distinguish active human grinders from HFT bots. See release notes and v1.3 backlog issue for what's next.
A daily snapshot job runs at 08:00 UTC and re-scores the top 50 leaderboard wallets, building a historical dataset of classification stability over time.
There are several MCP servers covering Polymarket, each at a different layer:
| Server | What it does | When to use it |
|---|---|---|
| polymarket-intel (this) | Wallet intelligence — classify human vs bot, score trading edge, read open positions | Deciding whose signals to follow |
| graph-polymarket-mcp | Market data via The Graph subgraphs (20 tools, 8 subgraphs) | Reading raw on-chain market data |
| whitmorelabs/polymarket-mcp | Slippage, liquidity, arbitrage, price feeds | Pricing your own trades |
| joinQuantish/polymarket | Self-hosted trading agent | Running an autonomous bot |
These complement each other. A copy-trading agent would use polymarket-intel to filter wallets worth following, then graph-polymarket-mcp to read the markets those wallets are betting on, then whitmorelabs/polymarket-mcp to size its own entries.
What it answers
- "Is this trader a human or a bot?" — score_polymarket_wallet(wallet_address) → returns classification ∈ {human, bot, insufficient_data} plus a confidence score and reason codes.
- "Do they actually have an edge?" — edge_score from 0–10, gated on net realised PnL so distributed-but-losing wallets don't get false positives.
- "What are they betting on right now?" — get_open_positions(wallet_address) returns live positions sorted by size, refreshed every 30s.
- "How has their edge changed over time?" — /wallet/{address}/history returns the score time series from the daily snapshots.
Why this exists
The Polymarket leaderboard is misleading. It includes unrealised PnL marked-to-current-price, so the names at the top are dominated by bots running structural arb plus a few wallets sitting on huge open positions that may never resolve in their favour. Agents that copy-trade naively from the leaderboard get burned.
This service runs every leaderboard wallet through behavioural fingerprinting (focus ratio, holding period, timing regularity, category concentration) plus PnL reconstruction from raw activity, and only surfaces traders that look like genuine humans with a real edge.
The dataset grows more valuable over time — every day the snapshot job runs, historical signals accumulate. Wallets that have been consistently above edge 7 for 90 days are a stronger signal than any single point-in-time score.
Distributed as both a REST API and an MCP server
| Surface | Use case | Setup |
|-------------|---------------------------------------------|-------------------------------------|
| MCP server | Agent that needs tool-style access | pip install polymarket-intel-mcp |
| REST API | Custom HTTP integration, dashboards | curl https://polymarket-intel-production.up.railway.app/... |
| Hosted MCP | Agent on any MCP-compatible client | Add https://polymarket-intel-production.up.railway.app/mcp to client config |
Architecture
┌──────────────────────────────────────────────┐
│ core/ │
│ client.py — Polymarket data API client │
│ signals.py — pure signal calculators │
│ scorer.py — classifier + edge score │
│ models.py — Pydantic response schemas │
├──────────────────────────────────────────────┤
│ db/ │
│ schema.sql — Postgres tables + indexes │
│ repository.py — Repository protocol + │
│ InMemoryRepository │
│ supabase_repo.py — Supabase impl │
│ converters.py — ScoreResult ↔ records │
├──────────────────────────────────────────────┤
│ api/main.py — FastAPI HTTP server │
│ mcp_server/ — MCP server (stdio) │
│ scripts/ │
│ analyze_wallet.py — CLI │
│ snapshot_job.py — daily cron entry │
│ tests/ │
└──────────────────────────────────────────────┘
Core has no idea persistence exists. The API and snapshot job depend on the Repository protocol — Supabase in production, in-memory in tests and when env vars are unset. This is what makes the suite run without a database and what lets you swap Supabase for Neon, RDS, or anything else later by adding one file.
Quickstart
git clone <repo> && cd polymarket-intel
python -m venv .venv && source .venv/bin/activate
pip install -r requirements-dev.txt
pytest # 19 tests, all green
CLI
python scripts/analyze_wallet.py phonesculptor
python scripts/analyze_wallet.py 0xf1528f12e645462c344799b62b1b421a6a4c64aa --json
REST API
uvicorn api.main:app --reload --port 8000
open http://localhost:8000/docs
The API is split into a slow tier (cached aggressively, cheap, ideal for one-off discovery) and a fast tier (short cache, ideal for live copy-trading agents). The split exists because the underlying data has different freshness needs — a wallet's classification doesn't change minute-to-minute, but their open positions do.
| Tier | Method | Path | TTL | Notes |
|------|--------|------------------------------------------|------|------------------------------------------|
| slow | GET | /wallet/{address} | 1h | Score blob — classification, edge_score, signals. No positions. Persisted to history (debounced). |
| fast | GET | /wallet/{address}/positions | 30s | Open positions only. No DB write per call. |
| — | GET | /wallet/{address}/history | DB | Score time series |
| — | GET | /wallet/{address}/positions/history | DB | Position changes over time |
| — | GET | /wallet/by-username/{username} | 1h | Convenience lookup |
| — | GET | /leaderboard?limit=50 | 30m | Raw Polymarket top traders |
| — | GET | /leaderboard/verified?min_edge=5 | 1h | Filtered to scored humans |
| — | GET | /leaderboard/historical?date=… | DB | Leaderboard at any past date |
| — | GET | /snapshots/latest | DB | When did the cron last run? |
Why 30s on positions and not faster? Polygon block time is ~2s and Polymarket's activity index lags a few seconds. Polling below 10s gets you no fresher data, just rate-limit errors. 30s is the sweet spot for cost/freshness/upstream-friendliness.
…
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.



