> ## Documentation Index
> Fetch the complete documentation index at: https://getanyapi.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Connect AI agents to every AnyAPI through one Model Context Protocol endpoint, one key, and a USD wallet.

AnyAPI ships a [Model Context Protocol](https://modelcontextprotocol.io) server so agents
can discover and run any API in the catalog without bespoke integrations. Point your MCP
client at one endpoint, authenticate with your AnyAPI key, and your agent gets a
registry-driven tool surface that covers the entire catalog — no tool-per-API sprawl.

|               |                                                                 |
| ------------- | --------------------------------------------------------------- |
| **Endpoint**  | `https://api.getanyapi.com/mcp`                                 |
| **Transport** | Streamable HTTP                                                 |
| **Auth**      | AnyAPI key as a Bearer token                                    |
| **Tools**     | `list_apis`, `search_apis`, `get_api`, `run_api`, `get_balance` |

## Prerequisites

* An AnyAPI key. Create one in the [dashboard](https://getanyapi.com/dashboard) under **API keys**.
* A funded USD wallet. `run_api` bills your wallet per successful request; discovery is free.
* An MCP-capable client (Claude Code, Claude Desktop, Cursor, Codex, or any client that
  speaks Streamable HTTP).

<Note>
  The MCP surface is **API-key only** — session tokens are not accepted. Send your key as
  `Authorization: Bearer <your-key>`. Discovery (`list_apis`, `search_apis`, `get_api`) works
  **without a key**, so an agent can browse the catalog and read schemas before credentials are
  set up; `run_api` and `get_balance` require authentication.
</Note>

## Connect

<Tabs>
  <Tab title="Claude Code">
    Add the server with the CLI:

    ```bash theme={"dark"}
    claude mcp add anyapi \
      --transport http \
      https://api.getanyapi.com/mcp \
      --header "Authorization: Bearer YOUR_ANYAPI_KEY"
    ```

    Confirm it registered:

    ```bash theme={"dark"}
    claude mcp list
    ```
  </Tab>

  <Tab title="Claude Desktop">
    Open **Settings → Developer → Edit Config** and add AnyAPI to `mcpServers`:

    ```json theme={"dark"}
    {
      "mcpServers": {
        "anyapi": {
          "type": "http",
          "url": "https://api.getanyapi.com/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_ANYAPI_KEY"
          }
        }
      }
    }
    ```

    Restart Claude Desktop. The AnyAPI tools appear in the tools menu.
  </Tab>

  <Tab title="Cursor">
    Add AnyAPI to `~/.cursor/mcp.json` (or your project's `.cursor/mcp.json`):

    ```json theme={"dark"}
    {
      "mcpServers": {
        "anyapi": {
          "url": "https://api.getanyapi.com/mcp",
          "headers": {
            "Authorization": "Bearer YOUR_ANYAPI_KEY"
          }
        }
      }
    }
    ```

    Enable the server in **Settings → MCP**.
  </Tab>

  <Tab title="Codex">
    Add the server with the Codex CLI:

    ```bash theme={"dark"}
    codex mcp add anyapi \
      --url https://api.getanyapi.com/mcp \
      --header "Authorization: Bearer YOUR_ANYAPI_KEY"
    ```

    Or add it to `~/.codex/config.toml`:

    ```toml theme={"dark"}
    [mcp_servers.anyapi]
    url = "https://api.getanyapi.com/mcp"
    http_headers = { "Authorization" = "Bearer YOUR_ANYAPI_KEY" }
    ```
  </Tab>

  <Tab title="Any MCP client">
    Configure a remote Streamable HTTP server with these values:

    * **URL:** `https://api.getanyapi.com/mcp`
    * **Header:** `Authorization: Bearer YOUR_ANYAPI_KEY`

    Most clients accept the same JSON shape:

    ```json theme={"dark"}
    {
      "mcpServers": {
        "anyapi": {
          "url": "https://api.getanyapi.com/mcp",
          "headers": { "Authorization": "Bearer YOUR_ANYAPI_KEY" }
        }
      }
    }
    ```
  </Tab>
</Tabs>

## Tools

The server exposes five generic tools. Discovery (`list_apis`, `search_apis`, `get_api`) is
free; only `run_api` touches your wallet. `get_balance` reports what's left in it.

The MCP tools are a lightweight transport and projection over the same AnyAPI gateway
used by REST. The gateway owns input validation, provider selection, routing, failover,
pricing, health semantics, response normalization, and billing. Discovery tools return
those gateway-published facts and tolerate safe additions to the underlying catalog;
they do not recalculate relationships between prices, lanes, or failover.

<AccordionGroup>
  <Accordion title="list_apis — browse the catalog" icon="list">
    Browse APIs as lightweight summaries, optionally filtered by category. Summaries carry
    the SKU, name, category, provider, nested USD pricing, and failover status, but
    **no descriptions or schemas**, so listing the whole catalog stays token-cheap.
    To find an API by keyword (with descriptions), use
    `search_apis`; for one API's schemas, use `get_api`.

    **Input**

    | Field      | Type   | Required | Description                |
    | ---------- | ------ | -------- | -------------------------- |
    | `category` | string | no       | Category slug to filter by |

    **Returns** `scrapers`, an array containing `id`, `slug`, `name`, `category`,
    `provider`, nested `pricing`, `failover`, and optional `heavy` and
    `excludesCallerDelay`. `failover` reports whether AnyAPI currently has an alternate
    route. Descriptions, lanes, health, schemas, eligibility, and relevance are omitted.
    Use `search_apis` for every ranked free-text query.
  </Accordion>

  <Accordion title="search_apis — find an API by intent" icon="magnifying-glass">
    Search APIs by meaning and keyword across name, slug, and description, returning matches **with
    their descriptions** (schemas omitted). This is the targeted lookup: use it to find the
    right SKU before reading its schema with `get_api`.

    **Input**

    | Field      | Type    | Required | Description                                       |
    | ---------- | ------- | -------- | ------------------------------------------------- |
    | `query`    | string  | yes      | Free-text search over name, slug, and description |
    | `category` | string  | no       | Category slug to narrow the search                |
    | `platform` | string  | no       | Platform slug to narrow the search                |
    | `limit`    | integer | no       | Cap on matches returned (default 25)              |

    **Returns** `results` with the list fields, including `failover`, plus `description`
    and response-relative `relevance`, `total` before the limit, and `ranking`
    (`semantic` or `keyword`). Lanes, health, schemas, and eligibility are omitted.
  </Accordion>

  <Accordion title="get_api — inspect input and output schemas" icon="file-lines">
    Get the full definition of one API by SKU, including its normalized input and output
    JSON schemas.

    **Input**

    | Field    | Type   | Required | Description                  |
    | -------- | ------ | -------- | ---------------------------- |
    | `sku_id` | string | yes      | The API SKU slug to describe |

    **Returns** the list fields, including `failover`, plus `description`, anonymous lane
    pricing, input/output JSON schemas, and optional `tryEligible`. Lane health is
    omitted. Use the input schema to build a valid payload for `run_api`.
  </Accordion>

  <Accordion title="run_api — execute an API" icon="bolt">
    Execute an API by SKU with a normalized input payload. Requires a valid AnyAPI key.
    Billed to your USD wallet on success only.

    **Input**

    | Field       | Type    | Required | Description                                                                                                                     |
    | ----------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------- |
    | `sku_id`    | string  | yes      | The API SKU slug to execute                                                                                                     |
    | `input`     | object  | yes      | Normalized payload matching the API's input schema                                                                              |
    | `fields`    | string  | no       | Comma-separated keys (dotted paths like `author.name`) to keep on each result item. Trims the response, not the charge.         |
    | `max_items` | integer | no       | Cap the number of result rows returned; a `_truncated` note reports how many were withheld. Trims the response, not the charge. |
    | `summary`   | boolean | no       | Return only a structural outline (top-level keys and item counts) instead of the full data. Trims the response, not the charge. |

    The last three are **opt-in response-budget controls** — they keep a large result
    from flooding your context window. They change only what is returned to you, never
    what you are billed (`costUsd` reflects the full result the API produced).

    **Returns** the normalized `output`, the serving `provider` (always **AnyAPI**),
    `costUsd`, `items` (the number of results charged for), and `replayed`. Most APIs
    are priced per result — `baseUsd + perUnitUsd × items` — so cap results (and cost)
    with `limit` in your input; simple lookups are flat per request. Invalid input,
    insufficient funds, and total upstream failure are **not** charged.

    **Duplicate calls are not charged twice.** MCP clients re-issue a tool call on
    their own judgment: the model reads a result as truncated, the user re-runs the
    turn, a conversation branch is replayed. AnyAPI derives a duplicate-protection
    key automatically, with no argument for you to pass.

    Once AnyAPI admits that keyed run, it can continue synchronously in-process if
    the MCP client disconnects, bounded by the normal execution deadline. The
    disconnected request does not receive the eventual result. Repeat the same
    `sku_id` and `input` (compared by meaning, so key order and formatting do not
    matter):

    * `duplicate_call_in_progress` means the original run is still working. Nothing
      has been charged yet; wait a few seconds and repeat the same call.
    * A completed replay returns the original `output`, `costUsd`, and `items` with
      `replayed: true`, without another provider run or charge.

    Completed results remain replayable for about five minutes. A continued run that
    produces a replayable result charges normally exactly once even if the original
    MCP request disconnected. Past the replay window, or with any change to the
    input, the call runs fresh and is billed normally.
  </Accordion>

  <Accordion title="get_balance — check your wallet" icon="wallet">
    Get the remaining wallet balance for the API key you authenticate with. Requires a
    valid AnyAPI key; never charges.

    **Input** — none.

    **Returns** `balanceUsd`, the remaining wallet balance in USD. Use it to confirm
    there are funds before a `run_api` call, or to surface the balance to a user.
  </Accordion>
</AccordionGroup>

## How an agent uses it

A typical flow chains the tools - discover, inspect, run:

<Steps>
  <Step title="Discover">
    The agent calls `search_apis` with a query (for example, "instagram") to find a matching
    SKU and read its description. (Use `list_apis` instead to browse the whole catalog as
    lightweight summaries.)
  </Step>

  <Step title="Inspect">
    It calls `get_api` with that `sku_id` to read the input schema and build a valid
    payload.
  </Step>

  <Step title="Run">
    It calls `run_api` with the `sku_id` and `input`. AnyAPI routes to a provider,
    normalizes the response, falls back automatically on error, and returns the result.
  </Step>
</Steps>

Because every API shares the same tools and one normalized schema convention, an
agent that learns this flow once can use the entire catalog.

### Worked example

Discover Reddit APIs, inspect one, and run it. Tool results carry both a JSON text block
and `structuredContent` with these shapes:

```json theme={"dark"}
// search_apis {"query": "reddit"} → structuredContent
{
  "results": [
    {
      "id": "reddit.search",
      "slug": "reddit.search",
      "category": "social",
      "name": "Reddit Search",
      "description": "Search Reddit posts across all subreddits by query, normalized across providers with transparent failover.",
      "provider": "AnyAPI",
      "pricing": {
        "from": {
          "model": "flat",
          "unit": "request",
          "maxUsd": 0.003
        },
        "failoverMaxUsd": 0.003
      },
      "failover": true,
      "relevance": 1
    }
  ],
  "total": 1,
  "ranking": "semantic"
}
```

`list_apis` returns the same identity and pricing fields without `description` or
`relevance` (and wrapped in `scrapers`). Neither tool returns lanes, health, or schemas,
so browsing and searching stay token-cheap. Reach for `list_apis` when you want to
enumerate rather than search.

This API's `pricing.from.model` is `flat`, so its maximum is per request. `failover`
is the gateway's authoritative routing fact; do not infer it from lanes. A linear
offer instead carries `unit`, `baseUsd`, `perUnitUsd`, and `maxUsd`. For example,
an API billed per result reports `unit: "result"`; the actual successful charge is
the base plus the per-unit amount, capped at `maxUsd`.

```json theme={"dark"}
// get_api {"sku_id": "reddit.search"} → structuredContent (schemas abridged)
{
  "scraper": {
    "id": "reddit.search",
    "slug": "reddit.search",
    "category": "social",
    "name": "Reddit Search",
    "provider": "AnyAPI",
    "pricing": {
      "from": {
        "model": "flat",
        "unit": "request",
        "maxUsd": 0.003
      },
      "failoverMaxUsd": 0.003
    },
    "failover": true,
    "description": "Search Reddit posts across all subreddits by query.",
    "lanes": [
      {
        "pricing": {
          "model": "flat",
          "unit": "request",
          "maxUsd": 0.003
        }
      }
    ],
    "inputSchema": {
      "type": "object",
      "required": ["query"],
      "properties": {
        "query":     { "type": "string" },
        "sort":      { "type": "string" },
        "timeframe": { "type": "string" },
        "after":     { "type": "string" }
      }
    },
    "outputSchema": { "type": "object" }
  }
}
```

```json theme={"dark"}
// run_api {"sku_id": "reddit.search", "input": {"query": "golang"}} → structuredContent
{
  "output":   { "posts": [ { "title": "…", "url": "…", "score": 123 } ] },
  "provider": "AnyAPI",
  "costUsd":  0.003,
  "items":    25,
  "replayed": false
}
```

## Errors

Tool failures come back as MCP tool errors with a short machine-readable prefix:

| Prefix                             | Meaning                                                                                           | Billed                                                                                           |
| ---------------------------------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `unauthorized`                     | Missing or invalid AnyAPI key                                                                     | No                                                                                               |
| `sku_not_found`                    | The requested SKU does not exist                                                                  | No                                                                                               |
| `invalid_input`                    | Payload did not match the API's input schema                                                      | No                                                                                               |
| `insufficient_credits`             | Wallet balance too low — top up to run                                                            | No                                                                                               |
| `key_cap_exceeded`                 | The API key reached its configured spend cap                                                      | No                                                                                               |
| `grant_cap_exceeded`               | The authorization reached the spending limit its owner approved                                   | No                                                                                               |
| `trial_cap_reached`                | The autonomous trial reached its cap                                                              | No                                                                                               |
| `duplicate_call_in_progress`       | An identical call is still running; wait a few seconds and repeat the same call to get its result | No                                                                                               |
| `duplicate_needs_review`           | An identical earlier call is being reconciled; retrying will not clear it                         | No                                                                                               |
| `duplicate_call_conflict`          | An earlier call holds this call's duplicate-protection slot                                       | No                                                                                               |
| `duplicate_protection_unavailable` | AnyAPI could not check for a duplicate, so nothing ran; safe to retry                             | No                                                                                               |
| `provider_rejected_request`        | The upstream rejected this request; adjust it before retrying                                     | No                                                                                               |
| `provider_rate_limited`            | The upstream rate-limited the request; retry later                                                | No                                                                                               |
| `provider_timeout`                 | Every available route ended in an upstream timeout                                                | No (released)                                                                                    |
| `provider_transport_error`         | Every available route ended in a network failure                                                  | No (released)                                                                                    |
| `provider_failure`                 | Every available route ended in an upstream service failure                                        | No (released)                                                                                    |
| `malformed_upstream_response`      | The upstream response could not be safely normalized                                              | No (released)                                                                                    |
| `unclassified_upstream_response`   | The upstream response is not recognized yet                                                       | No (released)                                                                                    |
| `all_providers_failed`             | Every provider for this API failed                                                                | No (released)                                                                                    |
| `no_providers`                     | The API has no enabled providers                                                                  | No                                                                                               |
| `scrape_failed`                    | The run ended without a confirmed outcome                                                         | Unknown - check `get_balance`; repeating the same call within a few minutes cannot double charge |

A completed lookup that returns a normalized empty result such as `found: false` is not a
tool error. It is a successful, billable answer: the lookup ran and no matching entity was
found.

<Tip>
  Pair the MCP server with the official [agent skill](/docs/agent-skills) — the skill teaches
  your agent the discover → inspect → run workflow and cost discipline; MCP provides the
  live tools. Need help? Reach out at
  [support@getanyapi.com](mailto:support@getanyapi.com).
</Tip>
