Skip to main content

Server doesn’t appear in Claude Desktop

Symptom: you added mireye-earth to claude_desktop_config.json and restarted, but the 🔌 menu shows no Mireye entry, or it’s red.
  1. Validate the config JSON. A trailing comma or unbalanced brace silently disables all MCP servers.
  2. Confirm uvx is on PATH. macOS launches GUI apps with a minimal PATH (no shell profile loaded). If which uvx prints ~/.local/bin/uvx, that path may not be visible to Claude. Use the absolute path in your config:
    Don’t have uv at all? Install it:
  3. Check the Claude logs. Logs live at ~/Library/Logs/Claude/mcp-server-mireye-earth.log. On startup you should see one line:
    If you see a Python ImportError, mireye-mcp was launched against an interpreter that doesn’t have the mcp SDK installed. With uvx, this shouldn’t happen — uvx provisions a managed environment per call. If you switched to plain pip, make sure pip show mcp returns >= 1.27.2 in the same interpreter the binary lives in.

Tools not appearing in the picker

Symptom: server is connected (green dot) but no tools show.
  • Old mcp SDK. The package pins mcp >= 1.27.2, < 2.0. If you installed an older version manually, upgrade: pip install --upgrade 'mcp>=1.27.2,<2.0'.
  • Import failure. Run uvx mireye-mcp from a terminal. It should sit silently waiting for stdio input — anything printed to stderr beyond the starting … line is a real error.

ConnectError / ReadTimeout on the first call

The hosted API keeps its machines running, but the first calls right after a backend deploy can be slow while geospatial sources warm in the background, and a handful of fields depend on slow upstream federal services at the best of times.
  • The default already covers this. MIREYE_TIMEOUT_S defaults to 120 s, above the server’s ~110 s /v1/ask deadline, so a cold start completes within it. Only raise it further (never set it below 120 — that would abandon requests the server still completes) if you still time out:
  • Pre-warm with a cheap call. Hit https://api.mireye.com/healthz before your first user-facing call (e.g. in your agent’s session-start hook).

HTTP 400 coord_out_of_bounds

Mireye is US-only in V1. The primary accepted envelope is: This covers the lower 48, Alaska, Hawaii, and US territories. A second region covers the positive-longitude Western Aleutians: lat ∈ [51, 54], lng ∈ [172, 180). Coordinates outside both regions return:
If your caller might pass non-US coordinates, validate client-side first.

HTTP 400 fields_unknown

A requested field name is not in the catalog. The response lists exactly which names failed:
Common renames (see also /api-reference/errors):
  • elevation_melevation
  • slopeslope_degrees
  • floodplainwithin_floodplain_polygon
  • power_plantnearest_power_plant_name
The canonical list lives at /v1/meta/fields.

HTTP 400 fields_too_many

You requested more than 50 fields (after preset expansion). Two paths:
  • Drop the preset and pick fields explicitly.
  • Split into multiple fetch calls (e.g. one per layer).

HTTP 502 ask_answer_incomplete

mireye_ask reached the model, but the answer came back unusable — the model ran out of output budget partway through, or omitted a required part of it. Nothing is served, because a partial answer to a due-diligence question is worse than none.
Retry it. The condition is stochastic, so the same question usually succeeds on the next attempt, and the response carries a Retry-After header. The credits are refunded (best-effort), so a retry does not cost you twice. If you see it repeatedly for one specific question, that question is likely asking for more output than the answer budget allows — narrow it, or split it into two calls.

HTTP 422 ask_question_refused

The model declined to answer. This looks similar to the error above and behaves in the opposite way:
Do not retry this one. It is deterministic for the same input — an identical retry fails identically. Rephrase the question instead. Credits are refunded here too.
Branch on retryable, not on the status code. These two are the clearest case for it: both mean “no answer”, but one is worth another attempt and the other never will be. A client that retries everything will loop forever on a refusal.

401 / 403 errors

For the local stdio adapter, 401 means the MCP server did not send a valid bearer token. Run mireye-mcp login, or set MIREYE_BEARER_TOKEN in your MCP config. 403 means the signed-in account failed backend policy, such as a non-Google provider or unverified email. Two adapter-side errors look similar but never reach the API:
  • Stored credentials bound to a different URL. Stored logins only attach to the MIREYE_BASE_URL they were created against. If you changed MIREYE_BASE_URL after logging in, tool calls behave as logged out and the error names both the stored and the active URL. Re-run mireye-mcp login against the new URL, or set MIREYE_BEARER_TOKEN.
  • insecure_base_url. Tokens are never sent over plain http:// except to loopback hosts (localhost / 127.0.0.1 / [::1]). login also refuses to run against a remote plain-http URL. Use https for any non-local deployment.
For the hosted remote endpoint (https://api.mireye.com/mcp), 401 should include a WWW-Authenticate header pointing at the OAuth protected-resource metadata. If your client does not open an OAuth browser flow after that challenge, confirm it supports remote MCP authorization over Streamable HTTP.

Unexplained 500s

These are bugs. Include the X-Request-ID when reporting (structured errors carry it; plain unhandled 500s don’t — include the timestamp and tool name instead). The MCP server logs each tool call to stderr with the request ID:
Grab that and email ansh@mireye.earth.

Server keeps restarting

Claude Desktop will respawn the MCP server if the process exits unexpectedly. If you see flapping (the server going green/red repeatedly), check stderr — most often it’s a Python crash on import. Run the binary directly:
Any traceback printed before it hangs is the real error.