> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developers.meshapi.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developers.meshapi.ai/_mcp/server.

# MCP Server

> Connect any MCP-compatible agent or client to Mesh and call models, tools, RAG, and more — authenticated with your Mesh API key.

Mesh runs a built-in **[Model Context Protocol (MCP)](https://modelcontextprotocol.io)** server, so any MCP-compatible agent or client — Claude Code, Claude Desktop, Cursor, or your own agent framework — can use Mesh's models and tools directly, without writing any Mesh-specific HTTP code.

The server exposes the Mesh API surface as MCP **tools**: an agent can run chat completions, reason with the Responses API, generate and edit images, create embeddings, moderate content, search the web, query your RAG files, manage prompt templates, and check your balance — all authenticated with your existing Mesh API key.

The MCP server is a thin layer over the same routes as the REST API. Every tool call runs the identical authentication, rate-limit, spend-cap, balance, and usage-logging pipeline as a direct API call, and is billed to the same key.

## Connection details

|                    |                                                     |
| ------------------ | --------------------------------------------------- |
| **Endpoint**       | `https://api.meshapi.ai/mcp`                        |
| **Transport**      | Streamable HTTP                                     |
| **Authentication** | `Authorization: Bearer rsk_...` (your Mesh API key) |

You connect with the **same `rsk_` API key** you use for the REST API — no separate credential or OAuth flow. Pass it in the `Authorization` header when registering the server with your client.

## Connect a client

#### Claude Code

```bash
claude mcp add --transport http mesh-api https://api.meshapi.ai/mcp \
  --header "Authorization: Bearer rsk_YOUR_KEY"
```

Then, in a session, ask Claude to use the Mesh tools (e.g. "use mesh-api to draft a reply with `openai/gpt-4o-mini`").

#### Claude Desktop / Cursor

Add Mesh to your client's MCP config (`claude_desktop_config.json` for Claude Desktop, `.cursor/mcp.json` for Cursor):

```json
{
  "mcpServers": {
    "mesh-api": {
      "type": "http",
      "url": "https://api.meshapi.ai/mcp",
      "headers": { "Authorization": "Bearer rsk_YOUR_KEY" }
    }
  }
}
```

Restart the client; the Mesh tools appear in the tool picker.

#### Python (mcp SDK)

```python
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def main():
    async with streamablehttp_client(
        "https://api.meshapi.ai/mcp",
        headers={"Authorization": "Bearer rsk_YOUR_KEY"},
    ) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Discover the available tools
            tools = await session.list_tools()
            print([t.name for t in tools.tools])

            # Call one
            result = await session.call_tool(
                "chat",
                {
                    "model": "anthropic/claude-haiku-4.5",
                    "messages": [{"role": "user", "content": "Say hi in one word."}],
                },
            )
            print(result.structuredContent)

asyncio.run(main())
```

Keep your `rsk_` key secret — it authorizes billable calls against your account. Treat an MCP client config that embeds the key like any other secret store, and rotate the key from the dashboard if it leaks.

## Available tools

Tools mirror the REST API one-to-one. Inputs are OpenAI-shaped, so anything you know from the [API reference](/api-reference) carries over directly.

### Inference

| Tool             | What it does                                                                                                              | Billed |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------- | ------ |
| `chat`           | Chat completion against any catalog model (`model`, `messages`, optional `temperature`, `max_tokens`)                     | Yes    |
| `responses`      | Responses API for reasoning models / hosted tools (`model`, `input`, `max_output_tokens`, `reasoning_effort`)             | Yes    |
| `embeddings`     | Embedding vectors for one or more texts (`model`, `input`)                                                                | Yes    |
| `moderations`    | Classify text for policy violations (`input`, optional `model`)                                                           | Yes    |
| `compare`        | Run the same messages across several models (`models`, `messages`, optional `comparison_model`)                           | Yes    |
| `router_select`  | Ask the Auto Router which model best fits (`messages`) — no completion is run                                             | No     |
| `generate_image` | Generate image(s) from a prompt (`prompt`, `model`, `n`, `size`, `response_format`)                                       | Yes    |
| `edit_image`     | Edit an image with a prompt (`model`, `prompt`, `image`, optional `mask`) — `image`/`mask` are data URLs, base64, or URLs | Yes    |

### RAG & search

| Tool          | What it does                                                                                                  | Billed |
| ------------- | ------------------------------------------------------------------------------------------------------------- | ------ |
| `web_search`  | Web search with ranked results (`query`, `max_results`, `search_depth`)                                       | Yes    |
| `file_search` | Semantic search over your uploaded files (`query`, `top_k`, optional `file_ids`)                              | Yes    |
| `upload_file` | Upload a document to RAG (`file_name`, `mime_type`, `content_base64`, `embed`); embedding runs asynchronously | No     |
| `list_files`  | List your uploaded RAG files                                                                                  | No     |
| `get_file`    | Status / metadata for one file (`file_id`) — poll until `embedding_status` is ready                           | No     |

### Catalog & account

| Tool          | What it does                                           | Billed |
| ------------- | ------------------------------------------------------ | ------ |
| `list_models` | List catalog models, optionally filtered by `provider` | No     |
| `list_voices` | List text-to-speech voices available to your key       | No     |
| `get_balance` | Current credit balance for your account                | No     |

### Prompt templates

| Tool              | What it does                                                                                   | Billed |
| ----------------- | ---------------------------------------------------------------------------------------------- | ------ |
| `list_templates`  | List prompt templates for your org                                                             | No     |
| `get_template`    | Get one template (`template_id`)                                                               | No     |
| `create_template` | Create a template (`name`, optional `system`, `messages`, `model`, `description`, `variables`) | No     |
| `update_template` | Update a template (`template_id` + fields to change)                                           | No     |
| `delete_template` | Delete a template (`template_id`)                                                              | No     |

The server also exposes a **resource**, `mesh://models`, that returns the full model catalog as JSON — useful for clients that consume MCP resources rather than calling `list_models`.

## Example: give an agent a document Q\&A tool

A typical agent flow — upload a file, wait for embeddings, then answer questions grounded in it — is three tool calls:

#### Upload the document

Call `upload_file` with the file's bytes base64-encoded. You get back a `file_id`.

```json
{
  "name": "upload_file",
  "arguments": {
    "file_name": "handbook.pdf",
    "mime_type": "application/pdf",
    "content_base64": "JVBERi0xLjc...",
    "embed": true
  }
}
```

#### Wait for embeddings

Poll `get_file` with the `file_id` until `embedding_status` is `ready`. Embedding is asynchronous, so a freshly uploaded file is not immediately searchable.

#### Search and answer

Call `file_search` with a natural-language `query`, then feed the returned passages into `chat` to get a grounded answer.

## Authentication & billing

* **Auth:** the `Authorization: Bearer rsk_...` header is validated before any tool runs. A missing or invalid key returns **401**; a suspended key returns **403**.
* **Limits & billing:** billed tool calls inherit the key's per-key rate limits, spend cap, model allow-list, and credit balance — exactly as a direct REST call. If a call would exceed a limit or your balance is insufficient, the tool returns an error carrying the Mesh message (e.g. *"Insufficient balance."*).
* **Free tools:** the catalog/account reads (`list_models`, `list_voices`, `get_balance`), the RAG file reads (`list_files`, `get_file`, `upload_file`), template management, and `router_select` are not billed. Everything under **Inference**, plus `web_search` and `file_search`, is billed.
* **Usage tracking:** every billed tool call is logged to your usage history just like a REST request, so MCP traffic shows up in the dashboard and usage reports.

## Limitations

Tool results are returned as a single payload — there is no token-by-token streaming of a `chat`/`responses` result over MCP. For streaming, use the REST API or an SDK.

The following Mesh capabilities are **not yet exposed as MCP tools** — use the [REST API](/api-reference) or an SDK for them:

* Audio: text-to-speech and speech-to-text (transcription/translation)
* Video generation and the async Batch API
* Realtime audio (bidirectional WebSocket)
* Usage-report queries

## Troubleshooting

| Symptom                                                | Likely cause / fix                                                                          |
| ------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| `401 Unauthorized` when connecting                     | Missing or malformed `Authorization` header. It must be `Bearer rsk_...`.                   |
| `403 Forbidden`                                        | The key is suspended — check it in the dashboard.                                           |
| Tool returns *"Insufficient balance."*                 | Add credits, or the call exceeded your spend cap.                                           |
| `file_search` returns nothing for a just-uploaded file | Embedding is still processing — poll `get_file` until `embedding_status` is `ready`.        |
| A model isn't callable                                 | It may be outside your key's model allow-list, or not in the catalog — check `list_models`. |