Rate limits and retries

Authenticated GitHub accounts get 5000 requests per hour. That sounds like a lot, but one inspector run can burn dozens of requests, and a misbehaving MCP client can loop. You need to read the rate limit headers and back off cleanly when you get close to the ceiling.

github_client.py
python
import time
from github import Github, GithubException, RateLimitExceededException


def _wait_for_rate_limit(gh: Github, min_remaining: int = 50) -> None:
    """Pause when we are about to hit the hourly quota."""
    core = gh.get_rate_limit().core
    if core.remaining <= min_remaining:
        wait_seconds = max(0, core.reset.timestamp() - time.time()) + 1
        time.sleep(wait_seconds)


def get_pr_diff_safe(owner: str, repo: str, number: int):
    gh = _client()
    for attempt in range(3):
        try:
            _wait_for_rate_limit(gh)
            return get_pr_diff(owner, repo, number)
        except RateLimitExceededException:
            _wait_for_rate_limit(gh, min_remaining=0)
        except GithubException as exc:
            if exc.status >= 500 and attempt < 2:
                time.sleep(2 ** attempt)
                continue
            raise

The pre-check sleeps when the remaining budget is low. The retry loop catches transient 5xx errors with exponential backoff. You never loop forever, because three attempts is enough to clear a hiccup without punishing a real outage.

Rate limit handling flow

How the client decides between calling, waiting, and retrying.

Flashcards: Flashcards

Loading practice…

Quiz: Quiz

Loading practice…