---
title: MCP
url: https://runapi.ai/docs/guides/mcp.md
canonical: https://runapi.ai/docs/guides/mcp
locale: en
---

# MCP

Connect Claude Desktop, Cursor, VS Code, or Windsurf to Hosted MCP with
OAuth, authenticate with an API key when configuring credentials
directly, or run Local MCP over stdio when you need a local process.

## Connect with OAuth

Add this Streamable HTTP endpoint as a remote MCP server:

```text
https://mcp.runapi.ai/mcp
```

OAuth is the preferred authentication method for all four supported
desktop clients:

| Client | Setup | Successful connection |
|----------
| Claude Desktop | Add a custom remote connector with the endpoint above. | RunAPI appears as connected and its tools are available in a conversation. |
| Cursor | Add a remote MCP server with the endpoint above. | The server status is connected and the tool list loads. |
| VS Code | Add an HTTP MCP server with the endpoint above. | The MCP server starts without an authentication error and exposes its tools. |
| Windsurf | Add a remote MCP server with the endpoint above. | RunAPI is connected and its tools are available to the assistant. |

The client discovers RunAPI OAuth from the Hosted MCP endpoint. Your
browser then opens the RunAPI authorization flow:

1.  Sign in or create a RunAPI account.
2.  Select the Account the client may use.
3.  Approve access and return to the client.

The client stores and refreshes its OAuth credential. It never receives
your RunAPI API key. Review or revoke access from [Authorized
apps](/settings#oauth-connections).

OAuth discovery uses these resources:

* Hosted MCP resource: `https://mcp.runapi.ai`
* Protected Resource Metadata:
  `https://runapi.ai/.well-known/oauth-protected-resource`
* Authorization Server Metadata:
  `https://runapi.ai/.well-known/oauth-authorization-server`

The resource is the Hosted MCP origin, while the transport endpoint
includes `/mcp`. Do not use `https://mcp.runapi.ai/mcp` as the OAuth
resource value.

## Use an API key

A standard API key is a separate, manual authentication method for
clients and unattended hosts that accept bearer-token configuration.

Create a dedicated standard key from the [API Keys page](/api_keys).
Keep the key in a client secret input, environment variable, or mode
`600` file; never paste it directly into committed JSON.

### Cursor

```json
{
  "mcpServers": {
    "runapi": {
      "url": "https://mcp.runapi.ai/mcp",
      "headers": {
        "Authorization": "Bearer ${env:RUNAPI_API_KEY}"
      }
    }
  }
}
```

For a macOS GUI session, set the variable before opening Cursor and
fully restart the app:

```shell
launchctl setenv RUNAPI_API_KEY "YOUR_API_KEY"
```

Remove it with `launchctl unsetenv RUNAPI_API_KEY`. Use a dedicated
revocable key because GUI applications opened later in the same login
session can read the variable.

### Windsurf

```json
{
  "mcpServers": {
    "runapi": {
      "serverUrl": "https://mcp.runapi.ai/mcp",
      "headers": {
        "Authorization": "Bearer ${file:~/.config/runapi/mcp_api_key}"
      }
    }
  }
}
```

Create the referenced file without placing the key in shell history:

```shell
install -d -m 700 ~/.config/runapi
umask 077
printf 'RunAPI API key: ' >&2
read -r -s RUNAPI_API_KEY
printf '\n' >&2
printf '%s' "$RUNAPI_API_KEY" > ~/.config/runapi/mcp_api_key
unset RUNAPI_API_KEY
chmod 600 ~/.config/runapi/mcp_api_key
```

### VS Code

```json
{
  "inputs": [
    {
      "type": "promptString",
      "id": "runapi-api-key",
      "description": "RunAPI API key",
      "password": true
    }
  ],
  "servers": {
    "runapi": {
      "type": "http",
      "url": "https://mcp.runapi.ai/mcp",
      "headers": {
        "Authorization": "Bearer ${input:runapi-api-key}"
      }
    }
  }
}
```

The password input keeps the key out of the configuration file. Revoke
the key from the [API Keys page](/api_keys) when a host is retired or a
key may have been exposed.

## Run Local MCP

Local MCP runs `@runapi.ai/mcp` as a stdio process and requires Node.js.
Configure an MCP host to run:

```json
{
  "mcpServers": {
    "runapi": {
      "command": "npx",
      "args": ["-y", "@runapi.ai/mcp"]
    }
  }
}
```

For interactive use, install the [RunAPI CLI](/docs/resources/cli), sign
in, and then start the MCP process. The MCP `login` tool uses the same
saved local configuration.

```shell
runapi login
npx -y @runapi.ai/mcp
```

For a headless host or CI, inject a dedicated key at runtime:

```shell
RUNAPI_API_KEY="YOUR_API_KEY" npx -y @runapi.ai/mcp
```

Store the value in the platform's secret manager, keep it out of logs
and command history, and revoke it when the workload is removed.

## Available tools

Hosted MCP exposes eight tools:

| Tool | Purpose |
|----------
| `list_models` | List models, optionally filtered by modality, service, or action. |
| `get_model_info` | Inspect one model's operations, inputs, constraints, and pricing. |
| `list_actions` | Group available actions by modality. |
| `check_pricing` | Read current pricing for a service, action, and model. |
| `search_prompts` | Search reusable prompt examples. |
| `check_balance` | Read the authenticated Account balance and spending metrics. |
| `create_task` | Create a media Task with an idempotency key. |
| `get_task` | Read the current status and result of a Task. |

Local MCP also provides `login` for browser-based local authentication.

## Verify the connection

Your MCP client performs the protocol exchange. Use its server log or
MCP Inspector to confirm these three operations in order.

First, `initialize` must return RunAPI server information and protocol
capabilities:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {},
    "clientInfo": {"name": "connection-check", "version": "1.0.0"}
  }
}
```

After the client sends `notifications/initialized`, `tools/list` must
return the eight Hosted MCP tool names:

```json
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
```

Finally, call `list_models({})`. A successful result contains model
entries and proves that tool dispatch works:

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {"name": "list_models", "arguments": {}}
}
```

## Troubleshoot

* `401 Unauthorized`: restart the OAuth connection and confirm the
  authorization completed, or verify the configured API key has not been
  revoked.
* `403 Forbidden`: reconnect and select an Account where you still have
  access. For API keys, confirm the key belongs to the intended Account.
* `429 Too Many Requests`: wait for the `Retry-After` interval before
  retrying. Hosted MCP limits requests per client IP and authenticated
  principal.
* Connection opens but tools do not appear: remove and re-add the exact
  `https://mcp.runapi.ai/mcp` endpoint, then repeat `initialize` and
  `tools/list`.
* `list_models({})` fails after the tool list succeeds: retry once, then
  check the client log for the JSON-RPC error and RunAPI request
  identifier.
* A browser or browser extension reports CORS: direct browser calls are
  not supported. Connect through an MCP client or a server-side/headless
  MCP host.
* Local MCP cannot authenticate: run `runapi auth status`, then `runapi
  login` again, or confirm `RUNAPI_API_KEY` is available to the process
  that starts `npx`.

For transient `5xx` responses, retry with backoff. Do not loop on `401`
or `403`; correct the credential or Account selection first.
