NegativeEV bet checker

Grade any bet against thousands of play-by-play game simulations — true win probability, implied odds, and edge for every leg.

Documentation

NegativeEV auth.md

NegativeEV (https://negativeev.com) is a bet checker. Anonymous visitors get 10 free checks a day; signing in makes checks unlimited (paced by a per-hour cap). There is no separate agent API — agents use the same HTTP endpoints as the web app, under the same quotas and rate limits. The MCP server is the one exception: it is metered on its own counter, more generously (see below).

How auth works

What the authorization server supports

Read from Supabase's own discovery document, which is the authority; this list is a convenience, not a second source of truth.

  • Grants: authorization_code and refresh_token. There is no client_credentials grant — see the next section for what that means.
  • PKCE is supported with S256. Use it: an agent driving a browser has no place to keep a client secret.
  • Scopes: openid, profile, email, phone, offline_access. This origin needs only openid profile email to identify the caller behind a check; ask for offline_access only if you genuinely need to refresh unattended.
  • Tokens are RS256/HS256/ES256 JWTs, sent to this origin as Authorization: Bearer. A protected endpoint refuses an invalid or expired one with 401 and a WWW-Authenticate: Bearer header naming the resource metadata above — re-authenticate rather than retrying anonymously.

What this means for agents

  • An agent acts ON BEHALF OF a signed-in user, always. There is no client_credentials grant: nothing here issues a token to a program acting as itself. The one credential a program can hold is an agent key a member minted for it (next section), and that key carries the member's own entitlements, not a separate identity.
  • Dynamic client registration (RFC 7591) is supported, so an MCP host can register itself without anyone creating a client by hand. Registration alone grants nothing — every authorization is decided by the signed-in user on https://negativeev.com/oauth/consent, which names the client and the scopes it asked for. The registration_endpoint is in the authorization server metadata linked above.
  • The simpler path still works and needs no registration: send a signed-in user's Supabase access token as Authorization: Bearer on requests (including MCP tool calls), or drive the site in the user's browser session.
  • Anonymous access also works; the free daily quota is metered per device.

Agent keys (optional, members only)

A signed-in member can mint a key that carries the same entitlements as their web session — the same hourly allowance, the same sims-explorer access — so an agent, a script or an MCP client can act as them without holding a Supabase session. Anonymous access stays keyless; a key is never required.

  • Mint: POST https://negativeev.com/keys with a Supabase access token as Authorization: Bearer and the body {"name": "<a label>"}. Answers {"id", "name", "prefix", "key", "created_at"}. The key (nev_ followed by 43 characters) is shown exactly once; only its SHA-256 is stored.
  • Use: send it as Authorization: Bearer nev_… on any request this document covers, MCP tool calls included. Once revoked it authenticates nothing: the metered routes treat the call as anonymous, the MCP endpoint refuses it with 401, and the member-only routes answer 401.
  • List: GET https://negativeev.com/keys — ids, names, prefixes and dates, never a plaintext or a hash.
  • Revoke: POST https://negativeev.com/keys/revoke with {"id": "<key id>"}.
  • A key cannot mint, list or revoke keys: those three routes take a Supabase access token only, and answer 403 to a key.

MCP server

A stateless MCP server (Streamable HTTP transport) is available at POST https://negativeev.com/mcp — server card at https://negativeev.com/.well-known/mcp/server-card.json

Tools: check_bet (grade a bet from text — spends one of the caller's checks when it fully grades), get_slate (is there a checkable slate right now — free), get_usage (checks remaining — free). Anonymous tool calls get their own per-device allowance of 100 checks a day — a separate counter from the web app's 10, so agent traffic never eats a browser's free checks. Send a Supabase access token as Authorization: Bearer on the POST for unlimited checks (paced at 1000 an hour).

Example prompts

Prompts a user can give any MCP-connected assistant to exercise the tools:

  • "Is Shohei Ohtani over 1.5 total bases at -120 a good bet tonight?" — check_bet grades it against thousands of simulated games and returns the true probability, the implied probability from the price, and the edge.
  • "Is there a checkable MLB slate tonight?" — get_slate answers per live sport, free, before any check is spent.
  • "How many bet checks do I have left today?" — get_usage reports the remaining quota and when the next check frees up.
  • "Here's my parlay: Ohtani over 0.5 home runs +280 and Dodgers moneyline -150. Worth it?" — check_bet prices each leg and the combined parlay.

Endpoints agents may call

Same-origin JSON, quota- and rate-limited, not yet documented as a stable public API (shapes can change without notice):

  • GET /slate — is there a checkable slate right now?
  • POST /extract — parse a bet from text: {"text": "<bet text>"}
  • POST /check — grade the parsed legs (send the fields /extract returned)
  • GET /usage — checks remaining for the caller

A refused request (quota, rate limit, started game) returns an explanatory JSON error. Discovery: /.well-known/api-catalog, /sitemap.xml, and the agent-skills index at /.well-known/agent-skills/index.json