Skip to main content
Glama
YoppaV

polymarket-research

by YoppaV
README.md
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![tests](https://github.com/YoppaV/polymarket-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/YoppaV/polymarket-mcp/actions/workflows/test.yml)

# polymarket-research

Read-only MCP server that gives Claude Code investigative access to
Polymarket — wallet forensics, market metadata, and cross-wallet pattern
analysis. **No order placement, no signing, no private keys.**

All four tiers ship: 21 tools backed by Polymarket's public Gamma + Data +
CLOB APIs, a local SQLite cache, and (optionally) Polygon RPC for on-chain
enrichment.

## Architecture

```
┌──────────────┐   stdio    ┌──────────────────┐    HTTPS    ┌─────────────────────┐
│  Claude Code │ ─────────► │   MCP server     │ ──────────► │ gamma / clob / data │
│  (or any MCP │            │ (FastMCP, 21     │             │  polymarket APIs    │
│   client)    │ ◄───────── │  tools)          │ ◄────────── │  (public, no auth)  │
└──────────────┘            └──────┬───────────┘             └─────────────────────┘
                                   │
                                   ▼  (cache + cohort queries)
                            ┌─────────────┐                  ┌────────────────────┐
                            │  SQLite     │   opt-in (env)   │  Polygon RPC       │
                            │  (~/.poly…) │ ───────────────► │  (Tier-4 chain     │
                            └─────────────┘                  │   enrichment only) │
                                                             └────────────────────┘
```

Pure-read: the server never signs or moves funds. Trades are stored
append-only in SQLite by `(transaction_hash, log_index)`; profiles are TTL'd.
Polygon RPC is fully opt-in via `POLYGON_RPC_URL` — without it, Tiers 1–3 run
end-to-end on the public HTTP APIs alone.

## Tier 1 tools — wallet investigation

| Tool | What it does |
| --- | --- |
| `get_wallet_profile` | Identity + total portfolio value (cached, TTL 1h). |
| `get_wallet_positions` | Open positions, sorted by current USD value. |
| `get_wallet_trades` | Trade history, newest first; paginates Data API. |
| `get_wallet_pnl_breakdown` | Cash PnL grouped by category / month / market. |
| `get_wallet_top_trades` | Largest trades by notional USD; wins/losses filter. |
| `get_wallet_concentration` | HHI, Gini, top-5 share, biggest single market. |
| `get_wallet_first_trade` | Earliest trade — proxy for "join date". |

## Tier 2 tools — markets & events

| Tool | What it does |
| --- | --- |
| `get_market` | Single market by id / conditionId / slug. Caches payload. |
| `get_market_orderbook` | CLOB book snapshot for one outcome (mid, spread, depth). |
| `get_market_holders` | Top holders across a market's outcome tokens. |
| `get_market_price_history` | CLOB price history for one outcome (1m / 1h / 1d / …). |
| `search_markets` | Filter Gamma markets by activity, slug substring, sort. |
| `get_event` | Event + child markets by slug or id (e.g. "GTA VI" group). |

## Tier 3 tools — cross-wallet

| Tool | What it does |
| --- | --- |
| `correlate_wallets` | Jaccard + Pearson on bucketed trade timelines; common markets. |
| `find_whale_followers` | Lag percentiles for candidates that copy a leader on same market+side. |
| `find_market_cohort` | All wallets in the cache that traded a given market (with rollups). |
| `get_cache_stats` | Counters of cache contents — trades, traders, markets, etc. |

### Bulk loader (`scripts/ingest_historical.py`)

Cohort tools query the local SQLite cache, so populate it first either by
running Tier-1 tools against the wallets you care about, or by bulk-loading a
historical dataset (CSV / JSONL / JSON):

```bash
venv/bin/python scripts/ingest_historical.py \
  --file ~/data/polymarket_trades.csv --format csv \
  --col-tx-hash transactionHash --col-wallet proxyWallet \
  --col-condition-id conditionId --col-ts timestamp
```

`--dry-run`, `--since 2024-01-01`, `--limit N`, and `--db-path` are all
supported. Re-running is idempotent (PK is `(tx_hash, log_index)`).

## Tier 4 tools — forensics

| Tool | What it does |
| --- | --- |
| `find_data_source_concentrators` | Cluster active markets by resolver/source; rank by aggregate volume. |
| `compare_entry_to_consensus` | Compare a trade's entry vs CLOB consensus mid at trade time (bps deviation). |
| `get_wallet_alpha_decay` | Bucket a wallet's trades on a market into deciles of its lifetime; surfaces early-vs-late edge. |
| `get_wallet_timing_pattern` | UTC hour-of-day histogram + best-effort timezone inference. |

`compare_entry_to_consensus` accepts an optional `enrich_with_chain=True` flag
that looks up the trade's block timestamp via Polygon RPC. That path is opt-in:
set `POLYGON_RPC_URL` and install the chain extra (`pip install -e '.[chain]'`).
Without it, the tool runs purely off CLOB price history.

## Setup

```bash
git clone <this repo>
cd polymarket-mcp
uv venv venv --python python3.12
uv pip install --python venv/bin/python -e .
```

(`python3 -m venv venv` works too if you have `python3-venv` installed.)

## Environment

| Var | Default | Purpose |
| --- | --- | --- |
| `POLYMARKET_GAMMA_BASE` | `https://gamma-api.polymarket.com` | Override Gamma host. |
| `POLYMARKET_CLOB_BASE` | `https://clob.polymarket.com` | Override CLOB host (Tier 2). |
| `POLYMARKET_DATA_BASE` | `https://data-api.polymarket.com` | Override Data host. |
| `POLYGON_RPC_URL` | (unset) | Polygon RPC for Tier 4 forensics. |
| `POLYMARKET_RATE_LIMIT_RPS` | `5` | Per-host token-bucket cap. |
| `POLYMARKET_DB_PATH` | `~/.polymarket_research.db` | SQLite cache file. |
| `POLYMARKET_CACHE_MODE` | `warm` | `warm` / `bypass` / `offline`. |

## Run the server standalone

```bash
PYTHONPATH=src venv/bin/python -m polymarket_research.server
```

You should see the FastMCP banner; the process is now listening on stdio.

## Connect via Claude Code

A ready-to-go `.mcp.json` ships at the repo root. From inside Claude Code,
either start it from this directory or symlink the file. Then restart the
MCP layer (or run `/mcp restart polymarket-research`) and the seven tools
above appear under `polymarket-research:*`.

## Recipes

Investigate a wallet:

```
> Use polymarket-research:get_wallet_profile on 0x<wallet>.
> Then get_wallet_concentration and pnl_breakdown by category.
```

Spot a high-conviction position:

```
> get_wallet_top_trades 0x<wallet> by notional_usd, n=10, side=losses
> compare those trades to get_wallet_pnl_breakdown by market
```

Find a wallet's earliest activity:

```
> get_wallet_first_trade 0x<wallet>
```

Replace `<wallet>` with any Polymarket trader address — use `search_markets`
+ `get_market_holders` to discover candidates on markets that interest you.

## Cache

Trades are stored append-only by `(transaction_hash, log_index)`; wallet and
market profiles are TTL'd. Inspect manually:

```bash
sqlite3 ~/.polymarket_research.db ".schema"
sqlite3 ~/.polymarket_research.db "SELECT COUNT(*) FROM trades"
```

Reset the cache by deleting the file. The schema is recreated on next run.

## Tests

```bash
PYTHONPATH=src venv/bin/python -m pytest tests/ -v --cov=polymarket_research
```

126 tests, ~90% coverage on parsers/analytics. Heavy coverage on the pure
layer; endpoints exercise fakes for HTTP and `:memory:` SQLite for cache.

## Read-only invariant

This server never imports a private key, never signs, never places an order.
Verify with:

```bash
grep -rEn 'sign|private_key|eip712|order_place|submit_order|wallet_create' src/
```

(Any hits should be substrings inside docstrings or comments — never live code.)

## Disclaimer

This server reads only public Polymarket and Polygon on-chain data. It does
not sign, place orders, or move funds. Outputs (concentration, alpha decay,
timing patterns, cohort overlaps) are research signals — not financial
advice. Use of the tool implies acceptance that all analyzed data is public
and that the author is not affiliated with Polymarket.