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

# Setting up an MCP surface

An MCP (Model Context Protocol) Surface exposes your [Product](/user-guide/products-surfaces/what-are-products)'s Capabilities as tools that AI assistants can discover and use. After you connect an MCP client, it can call your [Flows](/user-guide/flows/what-are-flows) and [Agents](/user-guide/agents/what-are-agents) from its chat interface.

## What is MCP?

MCP is an open protocol that lets AI assistants interact with external tools and services. When you create an MCP Surface, Runtype publishes your Product's Capabilities as tools for MCP clients to discover and call.

You can use an MCP Surface for workflows such as:

* Claude Desktop calls your data-retrieval Flow during analysis.
* Cursor calls your code-generation Agent during a coding session.
* VS Code calls your custom tools through the Cline extension or GitHub Copilot.

## Before you begin

Add at least one Capability to your Product. The MCP setup shows an empty tool list when your Product has no Capabilities. For more information, see [Adding capabilities to a product](/user-guide/products-surfaces/adding-capabilities-to-a-product).

## Create an MCP Surface

To add an MCP Surface to a Product, follow these steps:

1. Open your Product.
2. In the Product editor, click **Add Surface**.
3. Select **MCP Server**. The editor opens a Surface panel.
4. Click **Save** in the Product editor. The Surface panel shows the **Connect to AI Assistants** setup, starting at the **Configure Tools** step.

The setup has two steps: **Configure Tools** and **Ship**. After you finish the setup, **Ship** is also available as a tab in the Surface panel.

## Configure tools

Use the **Configure Tools** step to choose which Capabilities the MCP Surface exposes as tools. Each Capability attached to your Product has an enable or disable toggle.

Use **Enable All** or **Disable All** to update every Capability at the same time. From the setup completion screen, click **View Full Config** to manage tools and connection settings.

Runtype derives each tool's input schema from the Capability. For a Flow, the schema comes from the Flow's input variables. A Capability without a schema accepts one string argument named `input`. Runtype passes the tool arguments to the Flow as inputs and also sends them to the Capability as a user message. For more information, see [Flow variables and templates](/user-guide/flows/flow-variables-and-templates).

By default, each tool uses its Capability's name and description. To give a Capability a different name or description on this Surface only, set `exposedName` (up to 100 characters) and `exposedDescription` on the Surface item with the `PUT /v1/products/{id}/surfaces/{surfaceId}/items/{itemId}` endpoint. The dashboard has no control for these overrides.

An Agent can't finish over MCP if it pauses for a tool approval, asks the user for input, or calls a tool that runs on the client. The tool call returns an error instead. Expose these Agents on a Chat or AG-UI Surface, or turn off **Tool approval** in the Agent's tool settings. For more information, see [Agent tools](/user-guide/agents/agent-tools).

## Connect an MCP client

In the **Ship** step, select an authentication mode from the **Connect with** menu:

* **OAuth**: Use OAuth with clients that support MCP OAuth discovery, including Claude Desktop and Cursor.
* **API Key**: Use a `Bearer` token with clients that don't support OAuth, or when you want key-based access.
* **Public**: Allow unauthenticated access. Use this mode only for public tools or testing.

New MCP Surfaces use **API Key** mode. In **API Key** mode, the **Ship** step creates a test key and includes it in the configuration.

Copy the connection URL or JSON configuration from the **Ship** step into your MCP client. Claude Desktop doesn't load remote servers from the `claude_desktop_config.json` file that the **Ship** step names. Add the server URL in Claude Desktop under **Settings > Connectors** instead. Connectors don't send API keys, so use **OAuth** or **Public** mode for Claude Desktop.

For client-specific instructions for Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, JetBrains, and other MCP clients, see [Connecting to MCP clients](/user-guide/products-surfaces/connecting-to-mcp-clients).

## Activate the Surface

New Surfaces start in **Draft** status. The MCP endpoint rejects every request until the Surface status is **Active**.

To activate the Surface, follow these steps:

1. On the setup completion screen, click **View Full Config**.
2. On the **Overview** tab, click the status menu and select **Active**. The banner shows "This surface is live and accepting requests".

To stop traffic without deleting the Surface, select **Paused** or **Draft**. For more information, see [Product versioning and status](/user-guide/products-surfaces/product-versioning-and-status).

## Manage your Surface

Use the following tabs to inspect your Surface, manage its endpoint and keys, and copy its connection details.

### Overview

The **Overview** tab shows your Surface name, status, and key details. Use it to change the Surface status.

### Endpoints

The **Endpoints** tab shows your MCP endpoint URL and MCP manifest URL, with a copy button for each:

* **MCP Endpoint**: `https://api.runtype.com/v1/products/YOUR_PRODUCT_ID/surfaces/YOUR_SURFACE_ID/mcp`
* **MCP Manifest**: `https://api.runtype.com/v1/products/YOUR_PRODUCT_ID/surfaces/YOUR_SURFACE_ID/mcp/.well-known/mcp.json`

Replace `YOUR_PRODUCT_ID` and `YOUR_SURFACE_ID` with the IDs from your Product and Surface.

### Keys

MCP Surfaces use API keys in **API Key** mode, and as a fallback in **OAuth** mode for clients that don't support OAuth. Create and manage keys in the **Keys** tab.

The **Keys** tab also has an **Authentication Mode** menu with different labels for the same three modes. **Keys Only** is **API Key**, **OAuth + Keys** is **OAuth**, and **Public (No Auth)** is **Public**. For more information, see [MCP authentication](/user-guide/products-surfaces/mcp-authentication).

To create an API key, follow these steps:

1. Open the **Keys** tab.
2. Click **Generate Key**.
3. In **Name (optional)**, enter a name for the key.
4. In **Key Type**, select **Test** or **Production**.
5. Click **Generate Key**.
6. Copy the key and store it securely.

Production keys are stored as hashes and can't be revealed after creation. Test keys can be revealed again from the **Keys** tab.

The key dialog also shows a daily cap for test keys and a **Rate Limit (requests/minute)** field. An MCP Surface doesn't apply either limit. MCP tool calls count only toward your plan's daily execution limit. To limit what a client can call, use a [scoped key](/user-guide/products-surfaces/scoping-api-keys-to-capabilities).

Store API keys securely. Don't commit them to version control. Rotate a key immediately if someone exposes it.

### Ship

The **Ship** tab shows the same connection URL or JSON configuration as the **Ship** setup step. Use it to change the authentication mode with the **Connect with** menu and to copy the configuration again.

## Call tools with JSON-RPC

Most clients use an MCP library that performs the `initialize` handshake and tool discovery. To integrate directly, send JSON-RPC 2.0 requests to the MCP endpoint.

The MCP endpoint accepts JSON-RPC 2.0 requests over HTTP `POST` at this URL:

**`MCP endpoint`**

```plaintext title="MCP endpoint"
POST https://api.runtype.com/v1/products/YOUR_PRODUCT_ID/surfaces/YOUR_SURFACE_ID/mcp
```

Replace `YOUR_PRODUCT_ID` and `YOUR_SURFACE_ID` with the IDs from your Product and Surface.

For a protected Surface, send an API key in an `Authorization` header. The endpoint also accepts the `X-API-Key` header:

**`Authorization header`**

```plaintext title="Authorization header"
Authorization: Bearer mcp_YOUR_API_KEY
Content-Type: application/json
```

Replace `YOUR_API_KEY` with the key value. The full key includes the `mcp_` prefix.

Protected Surfaces require authentication for `initialize`, `tools/list`, and `tools/call`. Public Surfaces accept these methods without authentication.

To list the tools available to your API key, send this JSON-RPC request:

**`List tools request`**

```json title="List tools request"
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/list",
  "params": {}
}
```

The response includes each Capability available to the request as a tool and its JSON Schema:

**`List tools response`**

```json title="List tools response"
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {
        "name": "answer_questions",
        "description": "Answer questions about products and services",
        "inputSchema": {
          "type": "object",
          "properties": {
            "question": { "type": "string" }
          },
          "required": ["question"]
        }
      }
    ],
    "ttlMs": 300000,
    "cacheScope": "private"
  }
}
```

The `ttlMs` field (300000, five minutes) says how long a client can cache the tool list. The `cacheScope` value `private` means that the list applies only to this credential. Clients can ignore both fields.

Tool names contain only letters, digits, underscores, and hyphens, up to 64 characters. Runtype replaces other characters with underscores, so a Capability named `Answer Questions` becomes the tool `Answer_Questions`. When two tools get the same name, Runtype adds a suffix such as `_2`. Use the `name` from `tools/list` in `tools/call`.

To call a tool, send its name and arguments in a `tools/call` request:

**`Call tool request`**

```json title="Call tool request"
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "answer_questions",
    "arguments": { "question": "What are your shipping options?" }
  }
}
```

The response returns a `content` array that contains text:

**`Call tool response`**

```json title="Call tool response"
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{ "type": "text", "text": "We offer standard, express, and overnight shipping." }]
  }
}
```

When the call starts a Runtype run, the result also carries the run's ID in `_meta`, under the `com.runtype/executionId` key:

**`Call tool response with run ID`**

```json title="Call tool response with run ID"
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{ "type": "text", "text": "We offer standard, express, and overnight shipping." }],
    "_meta": { "com.runtype/executionId": "exec_YOUR_EXECUTION_ID" }
  }
}
```

A call that fails after its run starts carries the same key. A call refused before a run starts, such as an unknown tool or a reached limit, carries no `_meta`. Use the ID to correlate logs, quote it in a support request, or open the run with `GET /v1/runs/{executionId}` and an API key from your Runtype account.

A failed tool call still returns a JSON-RPC `result`, not an `error`. The result has `"isError": true`, and the `content` text describes the failure:

**`Failed tool call response`**

```json title="Failed tool call response"
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{ "type": "text", "text": "Error: Tool not found: answer_question" }],
    "isError": true
  }
}
```

A tool call returns `isError` for an unknown tool name, a key that is scoped away from the tool, a reached daily execution limit, or a failure in the Flow or Agent.

### Long-running tool calls

A `tools/call` request can run for up to five minutes. To receive MCP progress notifications while the call runs, include `params._meta.progressToken` in the request. The endpoint then streams the response as server-sent events. Requests without a progress token get a plain JSON response.

If an Agent is still running when the call returns, the result text includes the execution ID and an API path for following its progress.

### Server metadata and errors

To retrieve public server metadata without authentication, send a `GET` request to `https://api.runtype.com/v1/products/YOUR_PRODUCT_ID/surfaces/YOUR_SURFACE_ID/mcp/.well-known/mcp.json`.

Replace `YOUR_PRODUCT_ID` and `YOUR_SURFACE_ID` with the IDs from your Product and Surface. Protected manifests omit tool details until you authenticate.

The endpoint returns these JSON-RPC error codes:

| Code     | Meaning                | When it appears                                                |
| -------- | ---------------------- | -------------------------------------------------------------- |
| `-32700` | Parse error            | The request body contains invalid JSON.                        |
| `-32600` | Invalid request        | The JSON-RPC request envelope is invalid.                      |
| `-32601` | Method not found       | The request uses an unsupported method.                        |
| `-32602` | Invalid params         | The method parameters are invalid.                             |
| `-32603` | Internal error         | The server encounters an internal error.                       |
| `-32001` | Authorization required | An OAuth-enabled Surface receives no credentials.              |
| `-32002` | API key required       | A protected Surface receives no API key or an invalid API key. |

If the Surface doesn't exist or isn't **Active**, the endpoint returns HTTP `404` with a plain JSON body, such as `{"error":"MCP surface is not active"}`, instead of a JSON-RPC error.

## Verify your setup

To confirm that your tools work before you configure a client, send a `tools/list` request and a `tools/call` request to the MCP endpoint, as described in [Call tools with JSON-RPC](#call-tools-with-json-rpc).

After you connect an MCP client, confirm that the client lists your Capabilities as tools. [Connecting to MCP clients](/user-guide/products-surfaces/connecting-to-mcp-clients) shows where each client lists its tools. Then ask the AI assistant to call one of your Capabilities by name.

## Troubleshooting

The following sections cover the most common setup failures.

### Tools don't appear

If tools don't appear, check these conditions:

* Confirm that the Surface status is **Active**. An inactive Surface returns HTTP `404` with the message `MCP surface is not active`.
* Confirm that at least one Capability is enabled for the Surface.
* Reload the client after you add or change the configuration.

### Authentication fails

If authentication fails, check these conditions:

* Confirm that the API key starts with `mcp_` and belongs to this Surface.
* Send the key in an `Authorization: Bearer` header or an `X-API-Key` header.
* Confirm that the key hasn't expired. An expired key returns `API key has expired`.
* For OAuth, confirm that your client supports MCP OAuth discovery or use an API key.

## Next steps

Continue with one of these guides:

* [Connecting to MCP clients](/user-guide/products-surfaces/connecting-to-mcp-clients): configure Claude Desktop, Cursor, and other clients.
* [MCP authentication](/user-guide/products-surfaces/mcp-authentication): choose and manage authentication modes.
* [Scoping API keys to capabilities](/user-guide/products-surfaces/scoping-api-keys-to-capabilities): restrict a key to selected Capabilities.
* [Product versioning and status](/user-guide/products-surfaces/product-versioning-and-status): understand the **Active**, **Paused**, and **Draft** statuses.
* [Quickstart: build a social media post generator as a REST API](/user-guide/getting-started/quickstart-social-media-post-generator): build a Product and expose a Capability through a Surface.