Troubleshooting
Fixes for the problems people hit most: refused tokens, missing write access, rate limits, apps that do not load Unitley, and missing data.
Start with the exact message you see. Unitley's messages say what went wrong, and most of them say what to do next. Over MCP, a tool that fails still answers: your app shows the message as the tool's result, so ask it what the tool said.
Token refused (401)
Unitley answers 401 invalid_token with one of two messages:
- Send a Unitley access token as Authorization: Bearer unt_... (create one on the Connect page). No usable token arrived. The header is missing, it does not start with
Bearerand a space, or what follows is not a whole Unitley token. - This access token is unknown, revoked or expired. Create a new one on the Connect page. The token is well formed but does not work.
Check, in this order:
- The header. It must read
Authorization: Bearerfollowed by the token. A token pasted withoutBearerin front is refused. - The whole token. A Unitley token is
unt_followed by 43 letters, digits,-or_. A token cut short, or with a stray quote or space inside it, is refused. - The token's status. On the Connect page, find it by its prefix. If it says Expired or Revoked, it cannot be brought back. Sign out everywhere revokes every token at once.
- A lost token. Unitley cannot show a token again. Create a new one, put it in the app, and revoke the old one.
See Tokens and security for how tokens work, and Errors for the REST API's error format.
Read-only token (403)
Calling log_bet, settle_bet and save_recommendation with a read-only token returns insufficient_scope. Over the REST API it is a 403:
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="unitley", error="insufficient_scope", scope="write"
Content-Type: application/json
{
"error": {
"code": "insufficient_scope",
"message": "log_bet saves to your account, and this access token is read-only. Create a token with write access on the Connect page to use it.",
"issues": []
}
}Over MCP, the same message comes back as the tool's result. The write tools still appear in a read-only token's tool list, so an app can try to call them.
A token's access cannot be changed after it is created. Create a new token with Let it log bets, settle them and save picks ticked, replace the old one in your app, and revoke the old one.
Too many requests
Limits come back with how long to wait. Over the REST API it is a 429 rate_limited error with a Retry-After header and retryAfterSeconds in the body. Over MCP, the per-address limit is a 429 with Retry-After, and a tool-call limit comes back as the tool's result, with rate_limited and retryAfterSeconds.
Each message ends with how long to wait, such as "Try again in 4 minutes."
- Too many tool calls. Tool calls are limited to 60 a minute per token and 120 a minute per account. Giving each app its own token does not raise the account limit.
- Too many requests. Every request from one address counts, before the token is checked: 300 a minute for the MCP server and 300 a minute for the REST API.
- Too many new tokens in a short time. Creating tokens is limited too. Wait, then create the token.
- Too many key tests in a short time. Testing AI provider keys in Settings is limited. Wait, then test again.
An agent that loops on the same call can reach the tool-call limit quickly. Ask it to slow down, or to reuse what it has already fetched. See Rate limits for every budget.
Unitley missing in Claude Code
- Run
/mcp. Ifunitleyshows as failed with a 401, the token is wrong, expired or revoked. See Token refused. - Check the project. By default,
claude mcp addadds Unitley only to the project you ran it in. Start Claude Code in that folder, or add it again with--scope userto use it everywhere. See Claude Code. - Check it was saved. Run
claude mcp list. Ifunitleyis not there, run the add command again.
Claude Desktop does not load Unitley
- Node.js. Run
node --versionin a terminal. You need Node.js 20.18.1 or later (the current LTS is fine), because the config starts the mcp-remote bridge withnpx. - The JSON. The file must be valid JSON with one
mcpServerssection. If you already had other servers, theunitleyentry goes inside the samemcpServers, with a comma between entries. - A full restart. Quit Claude Desktop completely, not just its window, then open it again.
- The token. It goes in
env, asAUTH_HEADER, withBearerand a space in front. See why the token goes in env. - The logs.
mcp-server-unitley.logandmcp.log, in~/Library/Logs/Claudeon macOS or%APPDATA%\Claude\logson Windows, show why the bridge did not connect.
Hermes does not load Unitley
- Test it. Run
hermes mcp test unitley. It reports what Unitley answered. - The variable. If Hermes says
${UNITLEY_TOKEN}is not set in this profile's .env, check that~/.hermes/.envhas the lineUNITLEY_TOKEN=followed by the whole token, spelled exactly as inconfig.yaml. A 401 instead means Unitley refused the token itself: it is mistyped, expired or revoked. - The YAML. The
unitleyentry goes undermcp_servers, indented as in the Hermes guide. Keep the quotes around theAuthorizationvalue. - Reload. In a running session, type
/reload-mcpafter any change.
Odds missing or out of date
Unitley's odds come only from The Odds API, and the line shown for each game is FanDuel's moneyline, spread and total.
- Every price has an age. Each price comes with when it was fetched, such as "Updated 5h ago". Main lines are fetched about 90 minutes before each group of kickoffs, on Tuesday morning for the opening lines, and on Saturday morning after the injury reports. Between those times, prices can be hours old.
- The last prices stay. If Unitley has used up its odds requests for the moment, it keeps showing the last prices it fetched, each with its age. Check the price at your own book before betting.
- Games far out. Each fetch covers the games in the next 8 days, so a game further out may have no line yet.
- No FanDuel line. If FanDuel has not posted a market for a game, Unitley has no line to show for it.
No player props
get_player_props says why when it has nothing new:
- Player props are fetched in the 24 hours before kickoff. Check back closer to the game. Props are fetched only in the last 24 hours before a game starts.
- This game has started, so props are no longer refreshed.
- The odds provider has not listed this game yet, so its props cannot be fetched.
- Odds requests are being saved for the main lines right now, so props were not refreshed. Any props already fetched are still shown, with their age.
- Props for this game are being fetched right now. Try again in a moment. Another request is already fetching this game's props. Ask again shortly.
- These are the latest props for this game. They were already fetched, and the note says when they are next refreshed: once in the 24 hours before kickoff and once more in the last 3 hours.
- The latest props fetch for this game found none to show. Props were fetched for this game, but none came back to show. If that fetch came before the last 3 hours, it is tried once more then.
- The last props fetch for this game found none or failed. It is tried again an hour later.
- The odds provider did not deliver props for this game. Unitley has stopped asking for them to save the shared odds quota.
A props call that has to fetch them, or wait for another request fetching them, can take most of a minute. If your app gives up sooner, give it a tool-call timeout of at least 60 seconds.
No weather
- No forecast yet: forecasts are kept for games up to 7 days out and refreshed every 3 hours. A game more than 7 days away has no forecast. Ask again closer to the game.
- A closed roof. For an indoor venue, Unitley says the weather does not reach the field rather than showing a forecast.
- A retractable roof. The team decides on game day, about 90 minutes before kickoff, whether the roof is open. Unitley shows the forecast and says so.
Analyst key rejected
These are for the web analyst, which runs on your own AI provider key. They do not affect Claude or agents connected with a token.
- (Provider) did not accept this key. Check you copied all of it, or create a new one. The provider refused the key when you tested it. A new key that fails this way is not saved. Copy the whole key again, or create a new one with the provider.
- (Provider) did not accept your API key. Replace it in Settings. The provider refused a saved key during a chat, and Unitley marked it Key rejected. Paste a new key in Settings.
- (Provider) accepted the key but it lacks permission. Use a key with full access to models.
- Your (provider) account is out of credit or over its limit. The key works, but the provider will not run it. Add credit with the provider. Test connection spends nothing, so it may not catch this before you chat.
- There is no usable saved key. Paste your key again. Save the key again in Settings.