Skip to main content
Stobo MCP uses a structured error handling system with specific error types for different failure scenarios.

Error types

All errors are handled by the _call wrapper function in server.py:86-120, which catches exceptions from the Stobo client and returns structured JSON responses.

AuthError

Raised when authentication fails due to missing, invalid, or expired API keys. Status codes: 401, 403 Common scenarios:
When STOBO_API_KEY is not set and a paid tool is called:
{
  "error": "No API key configured. Get your free API key at https://trystobo.com — then add STOBO_API_KEY to your MCP server config.",
  "status_code": 401
}
Resolution:
  1. Sign up at trystobo.com
  2. Generate an API key from Settings > API Keys
  3. Add to your MCP config’s env section
  4. Restart your editor
When an API key is configured but invalid:
{
  "error": "Your API key is invalid or expired. Log in at https://trystobo.com to get a new one, then update STOBO_API_KEY in your MCP server config.",
  "status_code": 401
}
Resolution:
  1. Log in to trystobo.com
  2. Revoke the old key
  3. Generate a new API key
  4. Update your MCP config
  5. Restart your editor
Implementation:
except AuthError as e:
    has_key = bool(os.environ.get("STOBO_API_KEY", ""))
    if not has_key:
        msg = (
            "No API key configured. "
            "Get your free API key at https://trystobo.com — "
            "then add STOBO_API_KEY to your MCP server config."
        )
    else:
        msg = (
            "Your API key is invalid or expired. "
            "Log in at https://trystobo.com to get a new one, "
            "then update STOBO_API_KEY in your MCP server config."
        )
    return json.dumps({"error": msg, "status_code": e.status_code})

RateLimitError

Raised when you exceed the API rate limits. Status code: 429 Response format:
{
  "error": "Rate limit reached. Please wait a moment and try again.",
  "status_code": 429
}
Handling: Rate limits reset quickly. Simply wait a moment and retry the request. Normal conversational use stays well within limits. Implementation:
except RateLimitError as e:
    return json.dumps({
        "error": "Rate limit reached. Please wait a moment and try again.",
        "status_code": e.status_code,
    })
Rate limiting is applied per API key. Free tools without authentication have separate, more generous limits.

StoboAPIError

Generic API error for various failure scenarios. Status codes: Various (most commonly 402, 400, 404, 500)
When you’ve exhausted your credit balance:
{
  "error": "You've run out of credits. Top up at https://trystobo.com to continue using premium tools.",
  "status_code": 402
}
Affected tools:
  • generate_llms_txt (500 credits)
  • extract_tone (500 credits)
  • rewrite_article (1,000 credits)
Resolution:
  • Top up credits at trystobo.com
  • Free tools continue working without credits
  • Use get_credits to check your balance
For all other API errors (validation, not found, server errors):
{
  "error": "<error detail from API>",
  "status_code": 400
}
The error field contains the specific error message from the Stobo API’s detail field.
Implementation:
except StoboAPIError as e:
    if e.status_code == 402:
        msg = (
            "You've run out of credits. "
            "Top up at https://trystobo.com to continue using premium tools."
        )
        return json.dumps({"error": msg, "status_code": 402})
    return json.dumps({"error": e.detail, "status_code": e.status_code})

Generic exceptions

Catches any unexpected errors not covered by specific error types. Response format:
{
  "error": "<exception message>"
}
Implementation:
except Exception as e:
    return json.dumps({"error": str(e)})
Generic exceptions typically indicate unexpected failures (network issues, malformed responses, etc.). If you encounter these frequently, please report them to Stobo support.

Error handling patterns

In tool implementations

All tools use the _call wrapper to ensure consistent error handling:
@mcp.tool(annotations=READ_ONLY)
def audit_site(url: str) -> str:
    """Analyze a website's SEO performance and AI visibility."""
    client = _get_client()
    return _call(client.audit_site, url)
The _call function:
  1. Executes the client method
  2. Serializes the result to JSON
  3. Catches and transforms exceptions into user-friendly error messages
  4. Returns structured JSON with error details and status codes

Connection diagnostics

The check_connection tool provides detailed diagnostics for connectivity issues:
try:
    resp = httpx.get(f"{base_url}/api/v1/health", timeout=10)
    result["status"] = "ok" if resp.status_code == 200 else "error"
    result["http_code"] = resp.status_code
except httpx.ConnectError as e:
    result["status"] = "connection_refused"
    result["error"] = str(e)
    result["fix"] = "The API server is unreachable. Check your network or try again later."
except httpx.TimeoutException:
    result["status"] = "timeout"
    result["error"] = "Request timed out after 10 seconds"
    result["fix"] = "The API server is slow or unreachable. Check your network."
Response fields:
  • base_url — The API endpoint being used
  • has_api_key — Whether an API key is configured
  • status — Connection status (ok, error, connection_refused, timeout)
  • http_code — HTTP status code (if connection succeeded)
  • error — Error message (if any)
  • fix — Suggested resolution (for known issues)

Best practices

  1. Check connection first — Use check_connection to diagnose setup issues before running audits
  2. Monitor credits — Call get_credits periodically to avoid unexpected 402 errors
  3. Handle rate limits gracefully — Implement retry logic with exponential backoff for 429 errors
  4. Validate API keys — Test with a free tool first, then verify paid tools work
  5. Parse error responses — All errors return structured JSON with error and status_code fields

Debugging

To debug issues:
  1. Run check_connection to verify basic connectivity
  2. Check the status_code field to identify the error type:
    • 401/403 → Authentication issue
    • 429 → Rate limiting
    • 402 → Out of credits
    • 400 → Invalid request
    • 404 → Resource not found
    • 500 → Server error
  3. Review the error message for specific details
  4. Verify environment variables are set correctly
  5. Ensure you’re using the latest version of stobo-mcp
For persistent issues, check the troubleshooting guide or contact Stobo support.