clause-mcp
You are about to trade a spread between two contracts that resolve differently, and nothing you own will tell you.
Polymarket lists "U.S. enacts AI safety bill before 2027?". Kalshi lists what reads as the same contract. Polymarket's resolves YES only on restrictive provisions. Kalshi's resolves YES on a federal framework "regardless of whether those provisions mandate private-sector compliance or promote voluntary guidelines."
A voluntary standards act resolves one YES and the other NO. They are not the same bet at any price. Every arbitrage screen in existence shows them as one market at a spread, and a language model reading both rules texts will agree with the screen — because the divergence is not a difference between the two documents. It is an explicit clause on one side matched by silence on the other, and silence is the one thing a comparator has to be told not to read as agreement.
This is an MCP server. It gives an agent the checks it cannot perform on its own.
The second failure: the book that isn't there
A market on a major venue reported $65,883 of order-book depth. Within a sensible band of its own mid it held $33. It had traded $122 in thirty days. Putting $200,000 into it is 49,276 days of volume — 135 years.
A book is an offer. The tape is a fact. When they disagree, believe the tape.
Install
pip install clause-mcp
Claude Code
claude mcp add --scope user clause -- clause-mcp
--scope user matters: the default registers the server for one project
directory only. The tools appear in a new session, not the one you ran the
add from.
Claude Desktop, or any stdio client
{
"mcpServers": {
"clause": { "command": "clause-mcp" }
}
}
Streamable-HTTP instead of stdio: clause-mcp --http --port 8848.
The eight tools
| Tool | Answers | Needs |
|---|---|---|
check_equivalence |
are these two contracts the same bet? | live venues |
market_liquidity |
can this market absorb size — book and tape | live venues |
preflight |
will this specific order work, with numbers | live venues |
capacity |
how much fits inside 0.5¢ / 1¢ / 2¢ / 5¢ | live venues |
resting_order |
rest or cross, and how long to fill | live venues |
venue_conventions |
how each venue's API lies to you | nothing |
find_markets |
identifiers the other tools need | an archive |
identify_market |
which contract did the user mean, in plain words | an archive |
Six of the eight work the moment you install this. They read the venues live and need no local data.
The two search tools need a Clause archive — a hash-chained daily record of every open market's terms. This package does not ship one, and it will not pretend otherwise: with no archive, both tools refuse, name the state, and say in words that nothing was searched.
{
"ok": false,
"error": "archive_unavailable",
"this_is_not_a_negative_result":
"Do NOT report this as 'no such market' or 'no results'. Nothing was
searched. The named market may exist and be trading; this install
simply has no corpus to look in."
}
That refusal is the point of the package rather than a limitation of it. The
alternative — falling back to a live search — is what the tool exists to
avoid: Polymarket's list API caps pages at 100 rows and rejects offsets past
~2,100, so a live search silently misses the quiet markets, which are exactly
the ones whose liquidity most needs checking. Point CLAUSE_DB at an archive
if you have one.
Why the tool descriptions read the way they do
They are written for the agent, not for a human browsing a catalogue. An agent does not know it has a problem, so each description leads with the failure it prevents rather than with what the tool returns. A tool called after the mistake has been made is a tool that did nothing.
The verdicts are built the same way. check_equivalence returns two of them,
because two different things can make two contracts different bets. verdict
compares thresholds and settlement sources; it can reach EQUIVALENT when
both are genuinely comparable. criteria_verdict compares the provisions —
subject, jurisdiction, actor, action breadth, voluntary conduct, logical
structure, carve-outs — and it never returns a bare EQUIVALENT:
LIKELY_EQUIVALENT is its ceiling, with the clauses to read attached. That is
the one that catches the AI bills above, and roughly half the board resolves
on provisions rather than on numbers.
An unknown on a material field returns REVIEW_REQUIRED, never a pass.
INSUFFICIENT_DATA is a distinct verdict from LIQUID and must never render
as one.
venue_conventions
Thirteen documented ways a venue API returns HTTP 200 while being wrong, each one found by losing time to it and each one pinned by a test. A sample:
- Polymarket's
/bookreturns asks descending —asks[0]is the worst price. - A YES bid at 0.10 is a NO ask at 0.90. One order, two books. Never add the ladders.
data-api /tradesignores theassetparameter and returns the full tape. A five-row sample "confirms" the filter works.- Trades are newest-first; a capped pull is recent history, so dividing by 30 days understates a busy market ~15×.
- Kalshi's orderbook is under
orderbook_fp, and both sides are resting bids — the NO ask is1 − best YES bid. - Limitless caps
limitat 25 and 400s above it, which reads as "0 markets found".
The meta-lesson, and the reason the tools refuse the way they do: a check that cannot run reads as a check that passed.
Honest status
Version 0.1.0. The verdicts are conservative by construction and the refusals are deliberate, but this is early software with no user base behind it yet. It measures and records; it does not recommend positions and it is not legal advice. Order transmission is off.
Requires Python 3.11+. Tested on 3.13.
Name collision: an unrelated PyPI package called clause (a Chinese NLP
SDK) also installs a top-level clause module. Installing both into one
environment will produce a broken hybrid. Run this server with uvx, pipx,
or its own virtualenv — which is how MCP servers are usually run anyway.
MIT licensed.
Release files for clause-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| clause_mcp-0.1.0.tar.gz | 341.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| clause_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 630.4 kB
Release files / clause_mcp-0.1.0.tar.gz
| Download URL | clause_mcp-0.1.0.tar.gz |
|---|---|
| Size | 341.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7b7c2e9dd1725bc77b9e1a5e84330b5a6a172d86b3e2ebc4d6f2577faf7489bb
|
|
BLAKE2b-256 checksum How to use checksums |
799269f1a7ca7db1bd682a4cb5287f659800c7c6f07a9a7eb6d5a3cf13baca61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / clause_mcp-0.1.0-py3-none-any.whl
| Download URL | clause_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 288.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ab3014c06ab8edb01f53573846d8cb2aba60658c7f9f720c4bf479b1041d4c58
|
|
BLAKE2b-256 checksum How to use checksums |
2153368922bc96cd207e32aa5aced937d00a9980eaceb6c425c37c3b5ba81fd9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|