polymarket-mcp
by simonlokc
README.md
# polymarket-mcp
Clean, **NegRisk-resolved** Polymarket market & order-book data as an MCP server.
No API key, no database — stateless wrappers over the public Gamma and CLOB
APIs, with the messy parts (keyset pagination, NegRisk flags, token→outcome
resolution, book parsing) already handled for you.
Point any MCP client (Claude Desktop, Cowork, Cursor, …) at it and your agent
can query prediction-market data directly.
## Tools
| Tool | What it does |
|---|---|
| `polymarket_get_markets` | Top active markets by liquidity or 24h volume. Returns question, conditionId, **outcome→tokenId mapping**, negRisk flag, event, liquidity, volume, best bid/ask, spread. Filters: `limit`, `order_by`, `min_liquidity`, `contains`, `neg_risk_only`. |
| `polymarket_get_orderbook` | Live CLOB order book(s) for one or more outcome token ids. Sorted bids/asks + best bid/ask, spread, midpoint. |
| `polymarket_resolve_token` | Resolve a `token_id`, `condition_id`, or `slug` to its market and outcome mapping (which outcome the token is, its siblings). |
| `polymarket_resolve_token_onchain` | **On-chain-verified** resolution: derives `conditionId` + `outcomeIndex` from Polygon ground truth (CTF Exchange registry → ConditionalTokens position ids) instead of trusting the API. Returns block provenance + verification level (`fully_verified`, or `pair_only` for NegRisk). Requires `POLYGON_RPC_URL`. |
## Install & run
Requires **Node 18+** (uses the built-in `fetch`).
```bash
npm install
npm run build
```
Add to your MCP client config (e.g. Claude Desktop `claude_desktop_config.json`):
```json
{
"mcpServers": {
"polymarket": { "command": "node", "args": ["/absolute/path/to/polymarket-mcp/dist/server.js"] }
}
}
```
Then ask your agent things like *"what are the most active Polymarket markets
right now?"* or *"get the order book for this token id"*.
### Try it without a client
```bash
npm run build && npm run smoke # drives the server over stdio against live APIs
```
## Tests
```bash
npm test # unit tests for the ABI encoders — pure, no network
```
The encoder tests are deliberately network-free so they run anywhere. The API
and on-chain paths are verified against live endpoints by hand (see `npm run
smoke`), since CI has no route to Polymarket or a Polygon RPC.
## Config (all optional)
| Env | Default |
|---|---|
| `GAMMA_BASE_URL` | `https://gamma-api.polymarket.com` |
| `CLOB_BASE_URL` | `https://clob.polymarket.com` |
| `FETCH_TIMEOUT_MS` | `15000` |
| `POLYGON_RPC_URL` | *(unset)* — required only for `polymarket_resolve_token_onchain`. Any Polygon RPC that serves `eth_call` works; see below |
### Picking a Polygon RPC
The tool only needs `eth_blockNumber` and `eth_call`, so a free keyless endpoint
is enough. Verified working without an API key:
```bash
export POLYGON_RPC_URL="https://polygon-bor-rpc.publicnode.com"
```
`https://polygon.drpc.org` and `https://1rpc.io/matic` also answer keyless.
Note that `https://polygon-rpc.com` and `https://rpc.ankr.com/polygon` now
return **401 / Unauthorized** and require an account.
Passing the optional `block` argument reads historical state, which needs an
**archive** node — most free endpoints reject it (publicnode returns *"Archive
requests require a personal token"*). The tool surfaces that as an error rather
than pretending the token is unregistered. Omit `block` to read `latest`.
## Notes
- **Read-only.** No trading, no orders, no keys. It reads public data.
- Every fetch has a hard timeout + backstop so a stalled upstream can't hang the
server.
- This is a data-access tool, not trading advice. Prices and books are live
public data; verify before acting on them.
## License
MIT
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues