{
  "name": "FreeTools API",
  "version": "3.0",
  "homepage": "https://freetools.one/",
  "description": "Free developer tools with JSON APIs. No key, no signup, no tracking.",
  "docs": "https://freetools.one/llms.txt",
  "license": "MIT",
  "rateLimit": {
    "requests": 30,
    "perMinutes": 1,
    "note": "Random endpoints allow 300/min. Exceeding returns HTTP 429."
  },
  "endpoints": [
    {
      "path": "/v1/loc",
      "method": "GET",
      "summary": "Count lines of code in a GitHub or GitLab repository",
      "params": {
        "github": "user/repo (required, or use gitlab)",
        "gitlab": "group[/subgroup]/repo (required, or use github)",
        "branch": "optional branch name (default: auto-detected)",
        "ignored": "optional comma-separated files/dirs to exclude",
        "detail": "set to 1 to also return extensions[] and files[]"
      },
      "returns": "Array of {language, files, lines, blanks, comments, linesOfCode, percent}. With detail=1: {languages, extensions, files}.",
      "example": "https://freetools.one/v1/loc?github=cli/cli",
      "exampleDetail": "https://freetools.one/v1/loc?github=cli/cli&detail=1"
    },
    {
      "path": "/v1/stars",
      "method": "GET",
      "summary": "GitHub/GitLab star history as cumulative points",
      "params": {
        "github": "user/repo",
        "gitlab": "group/repo"
      },
      "returns": "Array of {x: 'YYYY-MM-DD', y: stars}",
      "note": "GitHub history is weekly and anchored to the live star total. GitLab is per-day.",
      "example": "https://freetools.one/v1/stars?github=torvalds/linux"
    },
    {
      "path": "/v1/stars/chart",
      "method": "GET",
      "summary": "Star history as a ready-to-embed SVG image",
      "params": {
        "github": "repeatable user/repo",
        "gitlab": "repeatable group/repo",
        "theme": "light|dark"
      },
      "returns": "image/svg+xml (1200x630)",
      "example": "https://freetools.one/v1/stars/chart?github=torvalds/linux&theme=dark"
    },
    {
      "path": "/v1/headers",
      "method": "GET",
      "summary": "Inspect HTTP response headers and the redirect chain",
      "params": {
        "domain": "example.com or full URL"
      },
      "example": "https://freetools.one/v1/headers?domain=example.com"
    },
    {
      "path": "/v1/tls",
      "method": "GET",
      "summary": "TLS version, cipher and certificate details",
      "params": {
        "domain": "example.com",
        "port": "optional, default 443"
      },
      "example": "https://freetools.one/v1/tls?domain=example.com"
    },
    {
      "path": "/v1/geolocation/json",
      "method": "GET",
      "summary": "IP geolocation as JSON",
      "params": {
        "q": "IPv4, IPv6 or hostname (optional: defaults to caller IP)"
      },
      "example": "https://freetools.one/v1/geolocation/json?q=8.8.8.8"
    },
    {
      "path": "/v1/geolocation/xml",
      "method": "GET",
      "summary": "IP geolocation as XML",
      "params": {
        "q": "IPv4, IPv6 or hostname"
      },
      "example": "https://freetools.one/v1/geolocation/xml?q=8.8.8.8"
    },
    {
      "path": "/v1/weather",
      "method": "GET",
      "summary": "Current weather by city or caller IP",
      "params": {
        "city": "london",
        "format": "json|xml"
      },
      "example": "https://freetools.one/v1/weather?city=london"
    },
    {
      "path": "/v1/proxy",
      "method": "GET",
      "summary": "SSRF-guarded CORS proxy, max 5MB",
      "params": {
        "quest": "full URL"
      },
      "example": "https://freetools.one/v1/proxy?quest=https://example.com"
    },
    {
      "path": "/v1/random/integer",
      "method": "GET",
      "summary": "Random integer(s)",
      "params": {
        "min": "required",
        "max": "required",
        "times": "optional, 1-10000"
      },
      "example": "https://freetools.one/v1/random/integer?min=1&max=10"
    },
    {
      "path": "/v1/random/list",
      "method": "GET",
      "summary": "Shuffled list of 1..len",
      "params": {
        "len": "required, 2-10000"
      },
      "example": "https://freetools.one/v1/random/list?len=10"
    },
    {
      "path": "/v1/random/name",
      "method": "GET",
      "summary": "Random surname",
      "example": "https://freetools.one/v1/random/name"
    },
    {
      "path": "/v1/locbadge",
      "method": "GET",
      "summary": "Single formatted LOC number, for README badges via shields.io",
      "params": {
        "github": "user/repo",
        "gitlab": "group/repo"
      },
      "returns": "text/plain, e.g. 279.3k",
      "example": "https://freetools.one/v1/locbadge?github=cli/cli",
      "note": "Designed for shields.io endpoint badges; cached 1h."
    }
  ],
  "errors": {
    "400": "bad input",
    "403": "blocked (SSRF guard or upstream auth)",
    "404": "not found",
    "413": "payload/repo too large",
    "429": "rate limit exceeded"
  },
  "notes": [
    "All endpoints are GET and return JSON unless stated otherwise.",
    "Cacheable repository endpoints carry X-Cache: HIT | STALE | MISS; all API responses include an X-Elapsed-Ms timing header.",
    "User input is validated and all outbound fetches are SSRF-guarded."
  ],
  "mcp": {
    "endpoint": "https://freetools.one/mcp",
    "transport": "streamable-http",
    "protocolVersion": "2025-06-18",
    "tools": [
      "count_loc",
      "star_history",
      "check_tls",
      "http_headers",
      "ip_geolocation",
      "get_weather"
    ],
    "clientConfig": {
      "mcpServers": {
        "freetools": {
          "url": "https://freetools.one/mcp"
        }
      }
    }
  },
  "openapi": "https://freetools.one/openapi.json"
}