Agent quickstart

Copy-paste curl, Python, MCP config and Claude or ChatGPT tool config for finding and downloading a model.

Four steps: search, read the model record, download the file, check the SHA-256. Reads need no key. The machine-readable contract is /api/openapi.json (OpenAPI 3.1).

curl

# 1. Find a model (no key needed)
curl -s 'https://huggingbay.xyz/api/v1/search?q=qwen&limit=5'

# 2. Read the model record; howToRun has runtime, command, file, sha256, sizeBytes, minimumRamGb, downloadUrl
curl -s 'https://huggingbay.xyz/api/v1/artifacts/hf-model-qwen-qwen3-0-6b' | jq .howToRun

# 3. Download the file (the URL redirects to a signed link that lasts at most 300 seconds) and check its hash
curl -fL -o model.safetensors 'https://huggingbay.xyz/api/downloads/hf-model-qwen-qwen3-0-6b/model.safetensors'
shasum -a 256 model.safetensors

Python

Standard library only.

import hashlib, json, urllib.error, urllib.request

BASE = "https://huggingbay.xyz"

def get(path):
    with urllib.request.urlopen(BASE + path) as r:
        return json.load(r)

rows = get("/api/v1/search?q=qwen&limit=5")["rows"]
model = get("/api/v1/artifacts/" + rows[0]["id"])
run = model["howToRun"]
print(run["runtime"], run["command"], run["minimumRamGb"], "GB")

if run["available"]:
    name = run["file"]["path"].split("/")[-1]
    urllib.request.urlretrieve(run["downloadUrl"], name)
    with open(name, "rb") as f:
        digest = hashlib.file_digest(f, "sha256").hexdigest()
    assert digest == run["file"]["sha256"], "hash mismatch"
    print("saved", name)

# Errors are JSON with code, message, hint and next.
try:
    get("/api/v1/artifacts/not-a-real-id")
except urllib.error.HTTPError as e:
    print(json.load(e)["hint"])

The howToRun block

The model record (GET /api/v1/artifacts/{id}) has howToRun: runtime, command, file (path, sha256, sizeBytes), minimumRamGb, downloadUrl, downloadCommand and verifyCommand. available is true only when the hosted file with a recorded hash can be downloaded now. minimumRamGb is an estimate from the file size. tested is true only when the record carries run evidence; a hash checks bytes, not a run.

MCP

Claude Code:

claude mcp add --transport http hugging-bay https://huggingbay.xyz/api/mcp

Claude Desktop, Cursor and other clients that read an mcpServers file:

{
  "mcpServers": {
    "hugging-bay": {
      "type": "http",
      "url": "https://huggingbay.xyz/api/mcp"
    }
  }
}

Claude tools

Use the MCP connector in the Messages API:

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: mcp-client-2025-11-20" \
  -H "content-type: application/json" \
  -d '{
  "model": "claude-opus-5-5",
  "max_tokens": 4096,
  "mcp_servers": [
    {
      "type": "url",
      "url": "https://huggingbay.xyz/api/mcp",
      "name": "hugging-bay"
    }
  ],
  "tools": [
    {
      "type": "mcp_toolset",
      "mcp_server_name": "hugging-bay"
    }
  ],
  "messages": [
    {
      "role": "user",
      "content": "Find a small chat model that fits in 8 GB and give me its download URL and SHA-256."
    }
  ]
}'

Or define your own tools and call the REST API from your code:

[
  {
    "name": "search_models",
    "description": "Search open models on Hugging Bay. Calls GET https://huggingbay.xyz/api/v1/search. Returns rows with id, repo, task, formats and defaultDownloadBytes.",
    "input_schema": {
      "type": "object",
      "properties": {
        "q": {
          "type": "string",
          "description": "Model name or task, for example qwen or speech recognition"
        },
        "limit": {
          "type": "integer",
          "minimum": 1,
          "maximum": 50
        }
      },
      "required": [
        "q"
      ]
    }
  },
  {
    "name": "get_model",
    "description": "Read one model by id. Calls GET https://huggingbay.xyz/api/v1/artifacts/{id}. The howToRun field has runtime, command, file, sha256, sizeBytes, minimumRamGb and downloadUrl.",
    "input_schema": {
      "type": "object",
      "properties": {
        "id": {
          "type": "string",
          "description": "Model id from search_models, for example hf-model-qwen-qwen3-0-6b"
        }
      },
      "required": [
        "id"
      ]
    }
  }
]

ChatGPT

Custom GPT action:

In the GPT editor: Configure, Actions, Create new action, Import from URL:
https://huggingbay.xyz/api/openapi.json
Authentication: None. Privacy policy: https://huggingbay.xyz/privacy

OpenAI function tool (Responses API):

{
  "type": "function",
  "name": "search_models",
  "description": "Search open models on Hugging Bay (GET https://huggingbay.xyz/api/v1/search).",
  "parameters": {
    "type": "object",
    "properties": {
      "q": {
        "type": "string"
      },
      "limit": {
        "type": "integer"
      }
    },
    "required": [
      "q"
    ],
    "additionalProperties": false
  }
}

Errors

Every error is JSON with code, message, hint (one line: how to fix it), next (label, action, command, href) and request_id. On 429 or 503, wait retry_after_s seconds and try again.

Updated .

Page sources

Page-copy source revision 8871bab84e1cf80aea1686a944ec335078a6c036 · Source files: apps/web/server.mjs, apps/web/lib/aeo-page.mjs, apps/web/lib/api-status-contract.mjs, apps/web/lib/agent-readable.mjs, apps/web/lib/docs-hub-model.mjs, apps/web/lib/compare-pages.mjs · Full revision record