MCP tools

The MCP server's nine tools, what each takes and returns, and when it refuses.

The MCP server lives at https://binference.io/api/mcp. To connect a client, see MCP server.

Requests

  • Streamable HTTP, without sessions. It speaks MCP's 2026-07-28 revision and every 2025 revision. Each request stands alone, so every message is a POST. GET and DELETE answer 405.
  • Your key on every request, as Authorization: Bearer binf_... or x-api-key.
  • Small bodies. A request over 64 KB answers 413.
  • 60 requests a minute per key, up to 20 at once after a pause. Faster answers 429.
  • A fixed tool list. The tools never change while you're connected, so the server sends no change notifications and opens no listen streams.
  • From anywhere. Any origin may call it, like the rest of the API.

HTTP answers

Every tool answers 200, even when it refuses (see Refusals). Other statuses come before a tool runs:

StatuserrorWhen
401unauthorizedNo key was sent
401invalid_tokenThe key is wrong or revoked
405A GET or DELETE
413The body is over 64 KB
429The key is over 60 requests a minute. Retry after retry-after
503temporarily_unavailableThe key couldn't be checked. Retry after retry-after (2 s)

A 401 carries WWW-Authenticate: Bearer realm="binference". There is no OAuth sign-in: the key is the only way in.

A 429 carries retry-after in seconds and retry-after-ms exactly, and a JSON-RPC error that names the wait:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32000,
    "message": "This key is making MCP requests faster than 60 a minute. Retry in 2 seconds."
  }
}

Results

Each tool returns its answer twice: as structuredContent, which matches the tool's output schema, and as the same JSON in a text block for clients that read text only.

  • Money is US dollars as exact decimal strings, like "0.0012". Never round-trip it through a float.
  • Times are ISO 8601 in UTC. Days are UTC dates, like "2026-09-30".
  • Read tools are marked read-only, so a client may run them without asking. revoke_key is marked destructive, so a client knows to ask first.

Refusals

A tool that can't do what was asked returns isError: true and one sentence that says why. Show it to the user or act on it:

{
  "content": [
    {
      "type": "text",
      "text": "This key has a spending limit, so it can only read. Use a key without a limit to create, change or revoke keys, or manage them at https://binference.io/account/keys."
    }
  ],
  "isError": true
}
The message starts withWhy
This key has a spending limitOnly a key without a limit can create, change or revoke
No key 12 belongs to this agentThe key id is another agent's, or doesn't exist
This agent already has 10 active keysRevoke one first
This agent made 20 keys over MCPIt can make 20 in any 24 hours. Try later, or create one on the keys page
This agent is not activeA suspended agent can't get new keys
label: or spending_limit.usd:That input is wrong. The rest of the sentence says how
Input validation errorAn input is missing, of the wrong type or out of range
bInference could not finish this right nowNothing on your side is wrong. Retry in a moment

get_balance

What the key can spend. No inputs. It returns the same body as Get balance.

{
  "object": "balance",
  "agent": {
    "id": 42,
    "name": "Nova",
    "token": "0x9f3c7e2b8a41d05c6e1f9a8b7c2d3e4f50617777",
    "status": "active"
  },
  "spendable_usd": "18.40211",
  "balance_usd": "18.42211",
  "reserved_usd": "0.02",
  "running_calls": 1,
  "expiring": [
    { "at": "2026-10-02T00:00:00.000Z", "usd": "2.1084" },
    { "at": "2026-10-03T00:00:00.000Z", "usd": "4.92" }
  ],
  "key_limit": null
}
  • spendable_usd is what new calls can reserve right now: the balance less what running calls hold.
  • expiring is what is left of each day's credit and when it expires, soonest first. Credit lasts 7 days.
  • key_limit is this key's spending limit, or null. It has the same fields as spending_limit below.
  • agent.token is null for an account.

get_limits

The limits on this key and its agent. No inputs.

{
  "key": {
    "id": 12,
    "label": "prod-server",
    "prefix": "binf_7Hq2xYv9aB",
    "can_manage_keys": false,
    "spending_limit": {
      "limit_usd": "5",
      "reset": "daily",
      "spent_usd": "1.2",
      "reserved_usd": "0.02",
      "remaining_usd": "3.78",
      "resets_at": "2026-10-01T00:00:00.000Z"
    }
  },
  "agent": {
    "calls_per_minute": 600,
    "burst": 60,
    "max_running_calls": 8,
    "running_calls": 1,
    "max_active_keys": 10,
    "active_keys": 3
  },
  "request": { "max_body_mb": 4, "max_stream_minutes": 30, "max_call_minutes": 13 },
  "mcp": { "requests_per_minute": 60, "burst": 20, "keys_per_day": 20 },
  "images": {
    "uploads_per_day": 200,
    "max_upload_mb": 20,
    "upload_link_hours": 24,
    "result_link_days": 7,
    "max_results_gb": 5
  }
}
  • can_manage_keys is true when the key has no spending limit.
  • spending_limit.remaining_usd is what the key may still start this period: the limit less what it spent and what its running calls hold.
  • The agent limits are shared by all of the agent's keys. See Rate limits.
  • mcp is this server's own limits: requests per key, and keys the agent may make here in 24 hours.
  • images is what image storage allows the agent.

get_usage

What the agent spent, by day and by model. It counts every key of the agent.

InputTypeDefaultWhat it is
daysinteger7How many UTC days back, today included: 1 to 90. 1 is today only
{
  "from": "2026-09-24",
  "to": "2026-09-30",
  "total": { "usd": "3.4102", "calls": 212, "tokens": 1840210 },
  "days": [
    { "day": "2026-09-29", "usd": "1.9", "calls": 130, "tokens": 1102400 },
    { "day": "2026-09-30", "usd": "1.5102", "calls": 82, "tokens": 737810 }
  ],
  "models": [
    {
      "model": "anthropic/claude-sonnet-5.5",
      "name": "Claude Sonnet 5.5",
      "usd": "3.1",
      "calls": 120,
      "tokens": 1400000
    },
    {
      "model": "google/gemini-3.8-flash",
      "name": "Gemini 3.8 Flash",
      "usd": "0.3102",
      "calls": 92,
      "tokens": 440210
    }
  ]
}

Days without calls are left out. Models are listed by spend, highest first. A call counts once its cost is known, usually within a minute.

list_calls

The agent's calls, newest first.

InputTypeDefaultWhat it is
key_idintegerOnly this key's calls
limitinteger20Calls per page, 1 to 50
beforestringThe next value of the page before, for older calls
{
  "calls": [
    {
      "id": 88412,
      "started_at": "2026-09-30T11:02:41.118Z",
      "duration_ms": 2840,
      "key": { "id": 12, "label": "prod-server", "prefix": "binf_7Hq2xYv9aB" },
      "model": "anthropic/claude-sonnet-5.5",
      "model_name": "Claude Sonnet 5.5",
      "endpoint": "messages",
      "stream": true,
      "outcome": "ok",
      "http_status": 200,
      "error_code": null,
      "tokens": {
        "prompt": 8120,
        "completion": 412,
        "reasoning": null,
        "cached": 6400
      },
      "reserved_usd": "0.1",
      "charge_usd": "0.0142"
    }
  ],
  "next": "88412"
}
  • outcome is running, pending (finished, its cost not known yet), ok, stopped (your side hung up) or failed. A failed call has its http_status and error_code, which Errors explains.
  • reserved_usd is what the call set aside when it started. charge_usd is what it cost, 0 until it's priced.
  • next is null on the last page.

list_keys

The agent's active keys, oldest first. No inputs. A key's secret is never shown.

{
  "keys": [
    {
      "id": 12,
      "label": "prod-server",
      "prefix": "binf_7Hq2xYv9aB",
      "created_at": "2026-09-20T09:12:03.000Z",
      "last_used_at": "2026-09-30T11:02:41.000Z",
      "month_usd": "24.8",
      "spending_limit": null,
      "this_key": true,
      "created_by_key_id": null
    }
  ],
  "max_active": 10
}
  • this_key is true for the key this connection uses.
  • created_by_key_id is the key that made it over MCP, or null for a key made on the keys page.
  • month_usd is what the key spent this calendar month (UTC).
  • spending_limit has the same fields as in get_limits, or is null.

create_key

A new key for the agent. Needs a key without a spending limit.

InputTypeWhat it is
labelstring, requiredA name to recognise it by, one line of up to 60 characters
spending_limitobjectLeave it out for a key without a limit
spending_limit.usdstring or numberThe most it may spend each period, from 0.01 to 1000000, like "5"
spending_limit.resetstringdaily, weekly or monthly. Periods start at 00:00 UTC, weeks on Monday
{
  "key": "binf_...",
  "id": 15,
  "label": "worker-2",
  "prefix": "binf_Qp4mZt81Rw",
  "created_at": "2026-09-30T12:00:00.000Z",
  "spending_limit": {
    "limit_usd": "5",
    "reset": "daily",
    "spent_usd": "0",
    "reserved_usd": "0",
    "remaining_usd": "5",
    "resets_at": "2026-10-01T00:00:00.000Z"
  }
}

key is shown this once and never again. Store it before doing anything else. An agent may have 10 active keys, and make 20 over MCP in any 24 hours. The new key is recorded as made by the key you're connected with.

update_key

Rename one of the agent's keys, or set, change or remove its spending limit. Needs a key without a spending limit.

InputTypeWhat it is
key_idinteger, requiredThe key's id, from list_keys
labelstringThe new name
spending_limitobject or nullThe new limit, as in create_key, or null to remove it

Pass label, spending_limit or both. It returns the key as list_keys shows it. A limit set mid-period counts what the key already spent in that period.

revoke_key

Revoke one of the agent's keys. Needs a key without a spending limit.

InputTypeWhat it is
key_idinteger, requiredThe key's id, from list_keys
{ "key_id": 15, "revoked": true, "this_key": false }

The key stops on its next call; calls already running finish. Revoking a key twice answers the same. If this_key is true, the connection you're using stops working too.

create_upload

A link to upload one image to, so a model can read a large or local image by link. Any key may use it, for an agent with credit.

InputTypeWhat it is
content_typestring, requiredimage/png, image/jpeg, image/webp or image/gif
sizeinteger, requiredThe image's exact size in bytes, up to 20 MB (20,971,520)

It returns what POST /uploads does:

{
  "object": "upload",
  "id": "upl_BTSNzIeW9d7D_ShZQ8fJEQ",
  "upload_url": "https://...r2.cloudflarestorage.com/binference-images/uploads/42/BTSNzIeW9d7D_ShZQ8fJEQ.png?X-Amz-...",
  "upload_method": "PUT",
  "upload_headers": { "Content-Type": "image/png" },
  "upload_expires_at": "2026-10-01T12:10:00.000Z",
  "url": "https://...r2.cloudflarestorage.com/binference-images/uploads/42/BTSNzIeW9d7D_ShZQ8fJEQ.png?X-Amz-...",
  "expires_at": "2026-10-02T12:00:00.000Z",
  "content_type": "image/png",
  "size": 3400000
}

PUT the image's bytes to upload_url with upload_headers before upload_expires_at, then send url as the image in any model call until expires_at. The PUT must carry exactly size bytes of that type, or storage refuses it. An agent may start 200 uploads in any 24 hours.

On this page