oddsrail 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oddsrail-0.3.0/.gitignore +5 -0
- oddsrail-0.3.0/LICENSE +21 -0
- oddsrail-0.3.0/PKG-INFO +261 -0
- oddsrail-0.3.0/README.md +214 -0
- oddsrail-0.3.0/llms.txt +54 -0
- oddsrail-0.3.0/oddsrail/__init__.py +0 -0
- oddsrail-0.3.0/oddsrail/kalshi.py +299 -0
- oddsrail-0.3.0/oddsrail/polymarket.py +170 -0
- oddsrail-0.3.0/oddsrail/server.py +234 -0
- oddsrail-0.3.0/oddsrail/signals.py +202 -0
- oddsrail-0.3.0/oddsrail/trading.py +125 -0
- oddsrail-0.3.0/pyproject.toml +47 -0
- oddsrail-0.3.0/server.json +24 -0
oddsrail-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 oddsrail
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
oddsrail-0.3.0/PKG-INFO
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: oddsrail
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: MCP server giving AI trading agents access to prediction markets (Polymarket, Kalshi) with on-chain builder-code attribution and trading signals.
|
|
5
|
+
Project-URL: Homepage, https://github.com/hmesutozsoy/oddsrail
|
|
6
|
+
Project-URL: Repository, https://github.com/hmesutozsoy/oddsrail
|
|
7
|
+
Project-URL: Issues, https://github.com/hmesutozsoy/oddsrail/issues
|
|
8
|
+
Author: oddsrail
|
|
9
|
+
License: MIT License
|
|
10
|
+
|
|
11
|
+
Copyright (c) 2026 oddsrail
|
|
12
|
+
|
|
13
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
14
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
15
|
+
in the Software without restriction, including without limitation the rights
|
|
16
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
17
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
18
|
+
furnished to do so, subject to the following conditions:
|
|
19
|
+
|
|
20
|
+
The above copyright notice and this permission notice shall be included in all
|
|
21
|
+
copies or substantial portions of the Software.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Keywords: ai-agents,kalshi,llm,mcp,model-context-protocol,polymarket,prediction-markets,trading
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Intended Audience :: Developers
|
|
34
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
40
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
41
|
+
Requires-Python: >=3.11
|
|
42
|
+
Requires-Dist: cryptography>=42.0
|
|
43
|
+
Requires-Dist: httpx>=0.28
|
|
44
|
+
Requires-Dist: mcp[cli]>=2.0.0
|
|
45
|
+
Requires-Dist: polymarket-client>=0.6.0
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
|
|
48
|
+
# oddsrail
|
|
49
|
+
|
|
50
|
+
<!-- mcp-name: io.github.hmesutozsoy/oddsrail -->
|
|
51
|
+
|
|
52
|
+
**The rail AI agents use to trade prediction markets.**
|
|
53
|
+
|
|
54
|
+
An MCP server that gives any agent (Claude Code, Claude Desktop, or anything
|
|
55
|
+
MCP-compatible) prediction-market access across **Polymarket and Kalshi**:
|
|
56
|
+
market search, orderbooks, price history, positions, and order routing — with
|
|
57
|
+
**on-chain builder-code attribution** on Polymarket — plus two premium signal
|
|
58
|
+
tools (in-play overshoot/fade detection, resolution dispute-risk).
|
|
59
|
+
|
|
60
|
+
**Free to use, and free of fees.** oddsrail ships with a project builder code
|
|
61
|
+
registered at **0 bps**, so orders routed through it are attributed without
|
|
62
|
+
adding a single basis point to anyone's trade. The project's income is a share
|
|
63
|
+
of Polymarket's weekly builder reward pool — paid by Polymarket's own program,
|
|
64
|
+
not by you. Running your own builder profile instead is one environment
|
|
65
|
+
variable (`ODDSRAIL_BUILDER_CODE`), and `server_info` always tells you which
|
|
66
|
+
code is in use. No fee tiers, no paywalled tools, no account required.
|
|
67
|
+
|
|
68
|
+
## Why this and not Parsec
|
|
69
|
+
|
|
70
|
+
The closest competitor (parsecapi.com) is a closed-source hosted service:
|
|
71
|
+
it stores your exchange keys (or holds a managed wallet that signs for you),
|
|
72
|
+
and its Builder Program keeps **55–85% of the fees builders collect**.
|
|
73
|
+
oddsrail is the opposite on every axis: **self-hosted, non-custodial (keys
|
|
74
|
+
never leave your machine), open source, and you keep 100% of your Polymarket
|
|
75
|
+
builder fees** because attribution uses Polymarket's native mechanism, not a
|
|
76
|
+
middleman escrow. Parsec also ships zero signal/analytics tools and nothing
|
|
77
|
+
on resolution risk — that's our paid layer.
|
|
78
|
+
|
|
79
|
+
## Quickstart
|
|
80
|
+
|
|
81
|
+
Python 3.11+ required.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install oddsrail
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
claude mcp add --transport stdio oddsrail -- oddsrail
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or from a clone, without installing:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
claude mcp add --transport stdio oddsrail -- /abs/path/to/oddsrail/.venv/bin/python -m oddsrail.server
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then ask the agent: *"search markets about the World Cup final and run the
|
|
102
|
+
overshoot signal on the favorite"*.
|
|
103
|
+
|
|
104
|
+
## How attribution works (CLOB V2, verified Aug 2026)
|
|
105
|
+
|
|
106
|
+
1. Get your **builder code** (a bytes32) at polymarket.com → **Settings →
|
|
107
|
+
Builders**. Set your fee rates there: taker up to 100 bps, maker up to
|
|
108
|
+
50 bps — additive on top of platform fees, settled to your builder wallet.
|
|
109
|
+
2. `export ODDSRAIL_BUILDER_CODE=0x...` where the server runs.
|
|
110
|
+
3. Every order any agent routes through `place_order` has the code placed in
|
|
111
|
+
the V2 order struct's `builder` field **before signing** — attribution is
|
|
112
|
+
on-chain, visible in every `OrderFilled` event on CTF Exchange V2.
|
|
113
|
+
4. Verify with the `builder_stats` tool (public builder-trades endpoint +
|
|
114
|
+
leaderboard).
|
|
115
|
+
|
|
116
|
+
If you skip this, orders carry the bundled oddsrail code at 0 bps — costing
|
|
117
|
+
you nothing and funding the project. If you set your own, yours wins; the
|
|
118
|
+
default is a default, not a lock-in.
|
|
119
|
+
|
|
120
|
+
## Environment variables
|
|
121
|
+
|
|
122
|
+
| Variable | Default | Meaning |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| `ODDSRAIL_DRY_RUN` | `1` | `1` = orders are simulated and returned, never posted. Set `0` to trade. |
|
|
125
|
+
| `ODDSRAIL_BUILDER_CODE` | project default | Your bytes32 builder code. Overrides the bundled project default so attribution (and any reward-pool share) accrues to you instead. |
|
|
126
|
+
| `POLYMARKET_PRIVATE_KEY` | unset | Operator wallet key; required only for real trading. Never leaves this machine. |
|
|
127
|
+
| `POLYMARKET_WALLET_ADDRESS` | unset | Proxy/deposit wallet address, if the account uses one. |
|
|
128
|
+
|
|
129
|
+
## Status — live-verified 2026-08-23
|
|
130
|
+
|
|
131
|
+
All 10 callable tools were driven end-to-end through a real MCP client
|
|
132
|
+
session against live Polymarket, from the Finland VPS (`/opt/oddsrail`).
|
|
133
|
+
Verified working: search, market lookup, orderbook (9/65 levels), price
|
|
134
|
+
history (361 pts), overshoot signal, dispute-risk, builder leaderboard,
|
|
135
|
+
dry-run order, open orders, server info.
|
|
136
|
+
|
|
137
|
+
Field mappings were corrected against the real API during that run — the
|
|
138
|
+
docs-guessed shapes were wrong in three places (`outcomes` is a dict keyed
|
|
139
|
+
`yes`/`no`, `search()` nests markets inside events, and book/volume/
|
|
140
|
+
resolution data live in `prices`/`metrics`/`state`/`resolution`
|
|
141
|
+
sub-objects).
|
|
142
|
+
|
|
143
|
+
## ⚠️ Network note
|
|
144
|
+
|
|
145
|
+
Polymarket API domains are **blocked on Turkish networks (BTK)** — local
|
|
146
|
+
testing fails TLS with a block page. Run the server where Polymarket is
|
|
147
|
+
reachable (the Finland VPS at `/opt/oddsrail`, a VPN, or any unblocked
|
|
148
|
+
network). The signal logic and MCP layer are fully testable offline.
|
|
149
|
+
|
|
150
|
+
## Kalshi (venue #2)
|
|
151
|
+
|
|
152
|
+
Kalshi is **bring-your-own-key and single-tenant by design**: the operator
|
|
153
|
+
supplies their own API key, trades their own account, and this server caches
|
|
154
|
+
nothing. That is deliberate — Kalshi's Developer Agreement limits API use to a
|
|
155
|
+
member's own trading (§3), bars facilitating other members' trading (§3.2) and
|
|
156
|
+
sublicensing the API (§3.7), and restricts storing/sharing API data (§3.1). A
|
|
157
|
+
hosted multi-tenant Kalshi service would not be compliant; a self-hosted one is.
|
|
158
|
+
|
|
159
|
+
**Attribution does not exist here.** Kalshi Builder Codes are a
|
|
160
|
+
Solana/DFlow/Jupiter integration — there is no builder or affiliate field
|
|
161
|
+
anywhere on the REST API, so Kalshi order flow cannot be attributed or
|
|
162
|
+
monetised the way Polymarket's can. Kalshi is in oddsrail for coverage and
|
|
163
|
+
signal reach, not for routing revenue.
|
|
164
|
+
|
|
165
|
+
Two shapes on this API are easy to get wrong, so oddsrail normalises both:
|
|
166
|
+
|
|
167
|
+
- **Prices are dollar strings, not cents** (`"0.5600"`), sizes are fixed-point
|
|
168
|
+
strings (`"10.00"`); the legacy integer-cent fields were removed in March
|
|
169
|
+
2026. All arithmetic uses `Decimal`.
|
|
170
|
+
- **The orderbook is bids-only on both sides.** `yes_dollars` and `no_dollars`
|
|
171
|
+
are both bid ladders, ascending — so the best bid is the *last* element, and
|
|
172
|
+
a NO bid at $0.99 *is* a YES ask at $0.01. `kalshi_get_orderbook` returns a
|
|
173
|
+
conventional best-first bid/ask view of the YES book plus the raw ladders.
|
|
174
|
+
|
|
175
|
+
Order placement speaks natural terms — `outcome` (yes/no), `action`
|
|
176
|
+
(buy/sell), `price` = probability of that outcome — and translates to Kalshi's
|
|
177
|
+
YES-book `bid`/`ask` internally (buy NO @ 0.25 becomes ask @ 0.75). That
|
|
178
|
+
translation is unit-tested, since it is the obvious place to ship an
|
|
179
|
+
inverted-position bug.
|
|
180
|
+
|
|
181
|
+
Credentials: `KALSHI_KEY_ID` plus `KALSHI_PRIVATE_KEY_PATH` (PKCS#8 PEM) or
|
|
182
|
+
`KALSHI_PRIVATE_KEY`. Set `KALSHI_DEMO=1` to hit the demo environment. Read
|
|
183
|
+
tools need no key at all.
|
|
184
|
+
|
|
185
|
+
## Tools (21)
|
|
186
|
+
|
|
187
|
+
- `search_markets`, `get_market`, `get_orderbook`, `price_history`,
|
|
188
|
+
`get_positions` — read-only, no keys
|
|
189
|
+
- `overshoot_signal` — premium: fresh panic-jump detection + this market's
|
|
190
|
+
historical reversion tendency (ported from the polymarket-wc analyzer)
|
|
191
|
+
- `dispute_risk` — premium: transparent 0–100 heuristic for contested
|
|
192
|
+
(UMA-dispute-prone) resolutions
|
|
193
|
+
- `place_order`, `cancel_order`, `open_orders` — trading, dry-run by default
|
|
194
|
+
- `builder_stats` — attribution verification + public builder leaderboard
|
|
195
|
+
- `server_info` — config status, per-venue
|
|
196
|
+
|
|
197
|
+
Kalshi: `kalshi_search_markets`, `kalshi_get_market`, `kalshi_get_orderbook`,
|
|
198
|
+
`kalshi_get_trades`, `kalshi_balance`, `kalshi_positions`,
|
|
199
|
+
`kalshi_open_orders`, `kalshi_place_order`, `kalshi_cancel_order`.
|
|
200
|
+
|
|
201
|
+
## Stack notes
|
|
202
|
+
|
|
203
|
+
- Official unified SDK `polymarket-client` (0.6.x): `AsyncPublicClient` for
|
|
204
|
+
data, `AsyncSecureClient.place_limit_order(..., builder_code=...)` for
|
|
205
|
+
attributed orders. The legacy `py-clob-client` is archived and cannot
|
|
206
|
+
attach builder codes — do not use it.
|
|
207
|
+
- MCP SDK 2.0: `MCPServer` from `mcp.server.mcpserver` (the old
|
|
208
|
+
`mcp.server.fastmcp.FastMCP` import is gone in 2.x).
|
|
209
|
+
- Kalshi is on plain `httpx` + `cryptography`, not the official SDK:
|
|
210
|
+
`kalshi-python-sync` requires Python >=3.13 and re-releases weekly in
|
|
211
|
+
lockstep with the spec version. Auth is RSA-PSS(SHA256, salt=digest length)
|
|
212
|
+
over `str(unix_ms) + METHOD + path`, where the path includes `/trade-api/v2`
|
|
213
|
+
and excludes the query string. Base URL is now
|
|
214
|
+
`external-api.kalshi.com`.
|
|
215
|
+
- x402 (planned): the official `x402` PyPI package (v2.20+) can wrap MCP
|
|
216
|
+
tools directly (`x402.mcp`, payment rides in tool-call `_meta`), but its
|
|
217
|
+
MCP helpers currently target mcp 1.x — integrating means pinning
|
|
218
|
+
`mcp>=1.28,<2` or waiting for the 2.x-compatible release. Mainnet
|
|
219
|
+
settlement needs a facilitator (Coinbase CDP: 1,000 free settlements/mo,
|
|
220
|
+
then $0.001). Keep free tiers of both signals so registries can index the
|
|
221
|
+
server.
|
|
222
|
+
|
|
223
|
+
## What the builder economy looks like (live, 2026-08-23)
|
|
224
|
+
|
|
225
|
+
Pulled from the public leaderboard via `builder_stats`:
|
|
226
|
+
|
|
227
|
+
| | weekly | all-time |
|
|
228
|
+
|---|---|---|
|
|
229
|
+
| #1 (betmoar) | $2.31M | $2.10B |
|
|
230
|
+
| median of top 25 | $127K | $88.2M |
|
|
231
|
+
| **entry to top 25** | **$42K** | $36.8M |
|
|
232
|
+
|
|
233
|
+
The instructive rows are the small-user ones: MagicMarkets routes $354K/week
|
|
234
|
+
with **1 active user**, Gate $1.11M/week with 2, PolymarketScan $277K with 3.
|
|
235
|
+
Those are bot operators routing their own flow — oddsrail's exact target
|
|
236
|
+
customer — and they show a single serious agent trader is worth real volume.
|
|
237
|
+
Wallets (MetaMask, 37K users) dominate on user count, not on volume per user.
|
|
238
|
+
|
|
239
|
+
## Roadmap
|
|
240
|
+
|
|
241
|
+
1. ~~Live smoke test from an unblocked network~~ — done 2026-08-23, all tools pass
|
|
242
|
+
2. Register builder code (polymarket.com → Settings → Builders), set fees to
|
|
243
|
+
0 bps at launch, export `ODDSRAIL_BUILDER_CODE`; first attributed order on
|
|
244
|
+
a tiny size
|
|
245
|
+
3. ~~Kalshi as venue #2~~ — done 2026-08-23, 9 tools, verified live
|
|
246
|
+
4. x402 paid wrapping for the two signals once the mcp-2.x conflict clears
|
|
247
|
+
5. Registry listings: official MCP registry (`mcp-publisher`, PyPI
|
|
248
|
+
`mcp-name:` marker), Smithery (needs public streamable-HTTP + a free
|
|
249
|
+
tool for their scanner), Glama (`glama.json`)
|
|
250
|
+
|
|
251
|
+
## Listing / distribution
|
|
252
|
+
|
|
253
|
+
- **GitHub**: https://github.com/hmesutozsoy/oddsrail (public, MIT)
|
|
254
|
+
- **Glama**: auto-crawls GitHub; `glama.json` in the repo root claims
|
|
255
|
+
maintainership.
|
|
256
|
+
- **Official MCP registry**: `server.json` is ready. Publishing needs the
|
|
257
|
+
package on PyPI first (the registry verifies ownership via an
|
|
258
|
+
`mcp-name: io.github.hmesutozsoy/oddsrail` marker in the PyPI README),
|
|
259
|
+
then `mcp-publisher login github && mcp-publisher publish`.
|
|
260
|
+
- **Smithery**: requires a public HTTPS streamable-HTTP endpoint — available
|
|
261
|
+
once oddsrail is hosted rather than run locally over stdio.
|
oddsrail-0.3.0/README.md
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# oddsrail
|
|
2
|
+
|
|
3
|
+
<!-- mcp-name: io.github.hmesutozsoy/oddsrail -->
|
|
4
|
+
|
|
5
|
+
**The rail AI agents use to trade prediction markets.**
|
|
6
|
+
|
|
7
|
+
An MCP server that gives any agent (Claude Code, Claude Desktop, or anything
|
|
8
|
+
MCP-compatible) prediction-market access across **Polymarket and Kalshi**:
|
|
9
|
+
market search, orderbooks, price history, positions, and order routing — with
|
|
10
|
+
**on-chain builder-code attribution** on Polymarket — plus two premium signal
|
|
11
|
+
tools (in-play overshoot/fade detection, resolution dispute-risk).
|
|
12
|
+
|
|
13
|
+
**Free to use, and free of fees.** oddsrail ships with a project builder code
|
|
14
|
+
registered at **0 bps**, so orders routed through it are attributed without
|
|
15
|
+
adding a single basis point to anyone's trade. The project's income is a share
|
|
16
|
+
of Polymarket's weekly builder reward pool — paid by Polymarket's own program,
|
|
17
|
+
not by you. Running your own builder profile instead is one environment
|
|
18
|
+
variable (`ODDSRAIL_BUILDER_CODE`), and `server_info` always tells you which
|
|
19
|
+
code is in use. No fee tiers, no paywalled tools, no account required.
|
|
20
|
+
|
|
21
|
+
## Why this and not Parsec
|
|
22
|
+
|
|
23
|
+
The closest competitor (parsecapi.com) is a closed-source hosted service:
|
|
24
|
+
it stores your exchange keys (or holds a managed wallet that signs for you),
|
|
25
|
+
and its Builder Program keeps **55–85% of the fees builders collect**.
|
|
26
|
+
oddsrail is the opposite on every axis: **self-hosted, non-custodial (keys
|
|
27
|
+
never leave your machine), open source, and you keep 100% of your Polymarket
|
|
28
|
+
builder fees** because attribution uses Polymarket's native mechanism, not a
|
|
29
|
+
middleman escrow. Parsec also ships zero signal/analytics tools and nothing
|
|
30
|
+
on resolution risk — that's our paid layer.
|
|
31
|
+
|
|
32
|
+
## Quickstart
|
|
33
|
+
|
|
34
|
+
Python 3.11+ required.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install oddsrail
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
claude mcp add --transport stdio oddsrail -- oddsrail
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Or from a clone, without installing:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
claude mcp add --transport stdio oddsrail -- /abs/path/to/oddsrail/.venv/bin/python -m oddsrail.server
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Then ask the agent: *"search markets about the World Cup final and run the
|
|
55
|
+
overshoot signal on the favorite"*.
|
|
56
|
+
|
|
57
|
+
## How attribution works (CLOB V2, verified Aug 2026)
|
|
58
|
+
|
|
59
|
+
1. Get your **builder code** (a bytes32) at polymarket.com → **Settings →
|
|
60
|
+
Builders**. Set your fee rates there: taker up to 100 bps, maker up to
|
|
61
|
+
50 bps — additive on top of platform fees, settled to your builder wallet.
|
|
62
|
+
2. `export ODDSRAIL_BUILDER_CODE=0x...` where the server runs.
|
|
63
|
+
3. Every order any agent routes through `place_order` has the code placed in
|
|
64
|
+
the V2 order struct's `builder` field **before signing** — attribution is
|
|
65
|
+
on-chain, visible in every `OrderFilled` event on CTF Exchange V2.
|
|
66
|
+
4. Verify with the `builder_stats` tool (public builder-trades endpoint +
|
|
67
|
+
leaderboard).
|
|
68
|
+
|
|
69
|
+
If you skip this, orders carry the bundled oddsrail code at 0 bps — costing
|
|
70
|
+
you nothing and funding the project. If you set your own, yours wins; the
|
|
71
|
+
default is a default, not a lock-in.
|
|
72
|
+
|
|
73
|
+
## Environment variables
|
|
74
|
+
|
|
75
|
+
| Variable | Default | Meaning |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| `ODDSRAIL_DRY_RUN` | `1` | `1` = orders are simulated and returned, never posted. Set `0` to trade. |
|
|
78
|
+
| `ODDSRAIL_BUILDER_CODE` | project default | Your bytes32 builder code. Overrides the bundled project default so attribution (and any reward-pool share) accrues to you instead. |
|
|
79
|
+
| `POLYMARKET_PRIVATE_KEY` | unset | Operator wallet key; required only for real trading. Never leaves this machine. |
|
|
80
|
+
| `POLYMARKET_WALLET_ADDRESS` | unset | Proxy/deposit wallet address, if the account uses one. |
|
|
81
|
+
|
|
82
|
+
## Status — live-verified 2026-08-23
|
|
83
|
+
|
|
84
|
+
All 10 callable tools were driven end-to-end through a real MCP client
|
|
85
|
+
session against live Polymarket, from the Finland VPS (`/opt/oddsrail`).
|
|
86
|
+
Verified working: search, market lookup, orderbook (9/65 levels), price
|
|
87
|
+
history (361 pts), overshoot signal, dispute-risk, builder leaderboard,
|
|
88
|
+
dry-run order, open orders, server info.
|
|
89
|
+
|
|
90
|
+
Field mappings were corrected against the real API during that run — the
|
|
91
|
+
docs-guessed shapes were wrong in three places (`outcomes` is a dict keyed
|
|
92
|
+
`yes`/`no`, `search()` nests markets inside events, and book/volume/
|
|
93
|
+
resolution data live in `prices`/`metrics`/`state`/`resolution`
|
|
94
|
+
sub-objects).
|
|
95
|
+
|
|
96
|
+
## ⚠️ Network note
|
|
97
|
+
|
|
98
|
+
Polymarket API domains are **blocked on Turkish networks (BTK)** — local
|
|
99
|
+
testing fails TLS with a block page. Run the server where Polymarket is
|
|
100
|
+
reachable (the Finland VPS at `/opt/oddsrail`, a VPN, or any unblocked
|
|
101
|
+
network). The signal logic and MCP layer are fully testable offline.
|
|
102
|
+
|
|
103
|
+
## Kalshi (venue #2)
|
|
104
|
+
|
|
105
|
+
Kalshi is **bring-your-own-key and single-tenant by design**: the operator
|
|
106
|
+
supplies their own API key, trades their own account, and this server caches
|
|
107
|
+
nothing. That is deliberate — Kalshi's Developer Agreement limits API use to a
|
|
108
|
+
member's own trading (§3), bars facilitating other members' trading (§3.2) and
|
|
109
|
+
sublicensing the API (§3.7), and restricts storing/sharing API data (§3.1). A
|
|
110
|
+
hosted multi-tenant Kalshi service would not be compliant; a self-hosted one is.
|
|
111
|
+
|
|
112
|
+
**Attribution does not exist here.** Kalshi Builder Codes are a
|
|
113
|
+
Solana/DFlow/Jupiter integration — there is no builder or affiliate field
|
|
114
|
+
anywhere on the REST API, so Kalshi order flow cannot be attributed or
|
|
115
|
+
monetised the way Polymarket's can. Kalshi is in oddsrail for coverage and
|
|
116
|
+
signal reach, not for routing revenue.
|
|
117
|
+
|
|
118
|
+
Two shapes on this API are easy to get wrong, so oddsrail normalises both:
|
|
119
|
+
|
|
120
|
+
- **Prices are dollar strings, not cents** (`"0.5600"`), sizes are fixed-point
|
|
121
|
+
strings (`"10.00"`); the legacy integer-cent fields were removed in March
|
|
122
|
+
2026. All arithmetic uses `Decimal`.
|
|
123
|
+
- **The orderbook is bids-only on both sides.** `yes_dollars` and `no_dollars`
|
|
124
|
+
are both bid ladders, ascending — so the best bid is the *last* element, and
|
|
125
|
+
a NO bid at $0.99 *is* a YES ask at $0.01. `kalshi_get_orderbook` returns a
|
|
126
|
+
conventional best-first bid/ask view of the YES book plus the raw ladders.
|
|
127
|
+
|
|
128
|
+
Order placement speaks natural terms — `outcome` (yes/no), `action`
|
|
129
|
+
(buy/sell), `price` = probability of that outcome — and translates to Kalshi's
|
|
130
|
+
YES-book `bid`/`ask` internally (buy NO @ 0.25 becomes ask @ 0.75). That
|
|
131
|
+
translation is unit-tested, since it is the obvious place to ship an
|
|
132
|
+
inverted-position bug.
|
|
133
|
+
|
|
134
|
+
Credentials: `KALSHI_KEY_ID` plus `KALSHI_PRIVATE_KEY_PATH` (PKCS#8 PEM) or
|
|
135
|
+
`KALSHI_PRIVATE_KEY`. Set `KALSHI_DEMO=1` to hit the demo environment. Read
|
|
136
|
+
tools need no key at all.
|
|
137
|
+
|
|
138
|
+
## Tools (21)
|
|
139
|
+
|
|
140
|
+
- `search_markets`, `get_market`, `get_orderbook`, `price_history`,
|
|
141
|
+
`get_positions` — read-only, no keys
|
|
142
|
+
- `overshoot_signal` — premium: fresh panic-jump detection + this market's
|
|
143
|
+
historical reversion tendency (ported from the polymarket-wc analyzer)
|
|
144
|
+
- `dispute_risk` — premium: transparent 0–100 heuristic for contested
|
|
145
|
+
(UMA-dispute-prone) resolutions
|
|
146
|
+
- `place_order`, `cancel_order`, `open_orders` — trading, dry-run by default
|
|
147
|
+
- `builder_stats` — attribution verification + public builder leaderboard
|
|
148
|
+
- `server_info` — config status, per-venue
|
|
149
|
+
|
|
150
|
+
Kalshi: `kalshi_search_markets`, `kalshi_get_market`, `kalshi_get_orderbook`,
|
|
151
|
+
`kalshi_get_trades`, `kalshi_balance`, `kalshi_positions`,
|
|
152
|
+
`kalshi_open_orders`, `kalshi_place_order`, `kalshi_cancel_order`.
|
|
153
|
+
|
|
154
|
+
## Stack notes
|
|
155
|
+
|
|
156
|
+
- Official unified SDK `polymarket-client` (0.6.x): `AsyncPublicClient` for
|
|
157
|
+
data, `AsyncSecureClient.place_limit_order(..., builder_code=...)` for
|
|
158
|
+
attributed orders. The legacy `py-clob-client` is archived and cannot
|
|
159
|
+
attach builder codes — do not use it.
|
|
160
|
+
- MCP SDK 2.0: `MCPServer` from `mcp.server.mcpserver` (the old
|
|
161
|
+
`mcp.server.fastmcp.FastMCP` import is gone in 2.x).
|
|
162
|
+
- Kalshi is on plain `httpx` + `cryptography`, not the official SDK:
|
|
163
|
+
`kalshi-python-sync` requires Python >=3.13 and re-releases weekly in
|
|
164
|
+
lockstep with the spec version. Auth is RSA-PSS(SHA256, salt=digest length)
|
|
165
|
+
over `str(unix_ms) + METHOD + path`, where the path includes `/trade-api/v2`
|
|
166
|
+
and excludes the query string. Base URL is now
|
|
167
|
+
`external-api.kalshi.com`.
|
|
168
|
+
- x402 (planned): the official `x402` PyPI package (v2.20+) can wrap MCP
|
|
169
|
+
tools directly (`x402.mcp`, payment rides in tool-call `_meta`), but its
|
|
170
|
+
MCP helpers currently target mcp 1.x — integrating means pinning
|
|
171
|
+
`mcp>=1.28,<2` or waiting for the 2.x-compatible release. Mainnet
|
|
172
|
+
settlement needs a facilitator (Coinbase CDP: 1,000 free settlements/mo,
|
|
173
|
+
then $0.001). Keep free tiers of both signals so registries can index the
|
|
174
|
+
server.
|
|
175
|
+
|
|
176
|
+
## What the builder economy looks like (live, 2026-08-23)
|
|
177
|
+
|
|
178
|
+
Pulled from the public leaderboard via `builder_stats`:
|
|
179
|
+
|
|
180
|
+
| | weekly | all-time |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| #1 (betmoar) | $2.31M | $2.10B |
|
|
183
|
+
| median of top 25 | $127K | $88.2M |
|
|
184
|
+
| **entry to top 25** | **$42K** | $36.8M |
|
|
185
|
+
|
|
186
|
+
The instructive rows are the small-user ones: MagicMarkets routes $354K/week
|
|
187
|
+
with **1 active user**, Gate $1.11M/week with 2, PolymarketScan $277K with 3.
|
|
188
|
+
Those are bot operators routing their own flow — oddsrail's exact target
|
|
189
|
+
customer — and they show a single serious agent trader is worth real volume.
|
|
190
|
+
Wallets (MetaMask, 37K users) dominate on user count, not on volume per user.
|
|
191
|
+
|
|
192
|
+
## Roadmap
|
|
193
|
+
|
|
194
|
+
1. ~~Live smoke test from an unblocked network~~ — done 2026-08-23, all tools pass
|
|
195
|
+
2. Register builder code (polymarket.com → Settings → Builders), set fees to
|
|
196
|
+
0 bps at launch, export `ODDSRAIL_BUILDER_CODE`; first attributed order on
|
|
197
|
+
a tiny size
|
|
198
|
+
3. ~~Kalshi as venue #2~~ — done 2026-08-23, 9 tools, verified live
|
|
199
|
+
4. x402 paid wrapping for the two signals once the mcp-2.x conflict clears
|
|
200
|
+
5. Registry listings: official MCP registry (`mcp-publisher`, PyPI
|
|
201
|
+
`mcp-name:` marker), Smithery (needs public streamable-HTTP + a free
|
|
202
|
+
tool for their scanner), Glama (`glama.json`)
|
|
203
|
+
|
|
204
|
+
## Listing / distribution
|
|
205
|
+
|
|
206
|
+
- **GitHub**: https://github.com/hmesutozsoy/oddsrail (public, MIT)
|
|
207
|
+
- **Glama**: auto-crawls GitHub; `glama.json` in the repo root claims
|
|
208
|
+
maintainership.
|
|
209
|
+
- **Official MCP registry**: `server.json` is ready. Publishing needs the
|
|
210
|
+
package on PyPI first (the registry verifies ownership via an
|
|
211
|
+
`mcp-name: io.github.hmesutozsoy/oddsrail` marker in the PyPI README),
|
|
212
|
+
then `mcp-publisher login github && mcp-publisher publish`.
|
|
213
|
+
- **Smithery**: requires a public HTTPS streamable-HTTP endpoint — available
|
|
214
|
+
once oddsrail is hosted rather than run locally over stdio.
|
oddsrail-0.3.0/llms.txt
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# oddsrail
|
|
2
|
+
|
|
3
|
+
> An MCP server that gives AI trading agents access to prediction markets
|
|
4
|
+
> across Polymarket and Kalshi, with on-chain builder-code attribution on
|
|
5
|
+
> routed Polymarket orders and premium signal tools.
|
|
6
|
+
|
|
7
|
+
Self-hosted and non-custodial: the operator runs the server themselves and
|
|
8
|
+
private keys never leave their machine. Orders are dry-run by default.
|
|
9
|
+
|
|
10
|
+
## What an agent can do with it
|
|
11
|
+
|
|
12
|
+
- `search_markets(query, limit)` — find markets by text; returns token ids,
|
|
13
|
+
best bid/ask, spread, 24h volume, liquidity, end date, resolution status
|
|
14
|
+
- `get_market(id_or_slug)` — one market's details
|
|
15
|
+
- `get_orderbook(token_id)` — live bids/asks
|
|
16
|
+
- `price_history(token_id, hours, fidelity_minutes)` — recent price series
|
|
17
|
+
- `get_positions(address)` — a wallet's current positions
|
|
18
|
+
- `overshoot_signal(token_id, hours, threshold)` — detects fresh price jumps
|
|
19
|
+
(panic moves) and reports whether a fade setup is active, plus that
|
|
20
|
+
market's historical reversion tendency
|
|
21
|
+
- `dispute_risk(id_or_slug)` — 0-100 score for how likely a market's
|
|
22
|
+
resolution gets contested (UMA dispute risk), with transparent reasons
|
|
23
|
+
- `place_order(token_id, side, price, size)` — limit order; price is an
|
|
24
|
+
implied probability in (0,1); dry-run unless the operator enables trading
|
|
25
|
+
- `cancel_order(order_id)`, `open_orders()`
|
|
26
|
+
- `builder_stats(time_period)` — public builder leaderboard and this
|
|
27
|
+
operator's attributed trades
|
|
28
|
+
|
|
29
|
+
## Kalshi tools
|
|
30
|
+
|
|
31
|
+
- `kalshi_search_markets(query, limit, min_volume)`, `kalshi_get_market(ticker)`,
|
|
32
|
+
`kalshi_get_orderbook(ticker, depth)`, `kalshi_get_trades(ticker, limit)`
|
|
33
|
+
- `kalshi_balance()`, `kalshi_positions()`, `kalshi_open_orders()`
|
|
34
|
+
- `kalshi_place_order(ticker, outcome, action, price, count)` — outcome yes|no,
|
|
35
|
+
action buy|sell, price is the probability of THAT outcome in (0,1)
|
|
36
|
+
- `kalshi_cancel_order(order_id)`
|
|
37
|
+
|
|
38
|
+
Kalshi notes: prices are dollar strings not cents; the raw orderbook is
|
|
39
|
+
bids-only on both sides (a NO bid at 0.99 is a YES ask at 0.01) but
|
|
40
|
+
`kalshi_get_orderbook` returns a normal best-first bid/ask view. Kalshi needs
|
|
41
|
+
the operator's own API key for private endpoints; read tools do not.
|
|
42
|
+
|
|
43
|
+
## Install
|
|
44
|
+
|
|
45
|
+
python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
|
|
46
|
+
claude mcp add --transport stdio oddsrail -- /abs/path/oddsrail/.venv/bin/python -m oddsrail.server
|
|
47
|
+
|
|
48
|
+
## Notes for agents
|
|
49
|
+
|
|
50
|
+
- Prices are implied probabilities in (0,1), not cents.
|
|
51
|
+
- `place_order` returns `{"dry_run": true, ...}` unless the operator has set
|
|
52
|
+
ODDSRAIL_DRY_RUN=0 — check this before assuming an order was placed.
|
|
53
|
+
- Polymarket API domains are blocked on some networks (e.g. Turkey); run the
|
|
54
|
+
server where they resolve.
|
|
File without changes
|