# API Setup



Every connection on this page needs your **Surface API key**, which scopes
each tool call to one environment. Claude can connect without one, over OAuth:
see [Claude OAuth Setup](/mcp-server/claude-oauth-setup).

<Warning>
  Don't have an API key yet? Create one in **Settings > API Keys** in your [Surface dashboard](https://app.withsurface.com). The key is only shown once, so save it securely.
</Warning>

<Info>
  A new connection loads the default **forms and vault bundles** (45 of 128 tools). To load a different set, add `?tools=` to the server URL in any of the configs below, e.g. `https://app.withsurface.com/mcp?tools=all`. See [Tool Bundles](/mcp-server/tool-bundles).
</Info>

## Claude Desktop [#claude-desktop]

<Steps>
  <Step title="Open MCP config">
    In Claude Desktop, go to **Settings > Developer > Edit Config** to open your `claude_desktop_config.json`.
  </Step>

  <Step title="Add the server">
    Add the following to your config file, replacing `<your-api-key>` with your actual API key:

    ```json
    {
      "mcpServers": {
        "surface-forms": {
          "url": "https://app.withsurface.com/mcp",
          "headers": { "Authorization": "Bearer <your-api-key>" }
        }
      }
    }
    ```
  </Step>

  <Step title="Verify connection">
    Restart Claude Desktop and look for the MCP icon in the chat input to confirm the server is connected.
  </Step>
</Steps>

## Cursor [#cursor]

<Tabs>
  <Tab title="Settings UI">
    <Steps>
      <Step title="Open MCP settings">
        Go to **Cursor Settings > MCP** and click **Add new MCP server**.
      </Step>

      <Step title="Configure the server">
        * **Type:** `HTTP`
        * **Name:** `surface-forms`
        * **URL:** `https://app.withsurface.com/mcp`
        * **Headers:** `Authorization: Bearer <your-api-key>`
      </Step>
    </Steps>
  </Tab>

  <Tab title="Config file">
    Add the following to your project's `.cursor/mcp.json`:

    ```json
    {
      "mcpServers": {
        "surface-forms": {
          "url": "https://app.withsurface.com/mcp",
          "headers": { "Authorization": "Bearer <your-api-key>" }
        }
      }
    }
    ```
  </Tab>
</Tabs>

## Claude Code [#claude-code]

Run the following command in your terminal:

```bash
claude mcp add --transport http surface-forms https://app.withsurface.com/mcp \
  --header "Authorization: Bearer <your-api-key>"
```

Verify the server is configured:

```bash
claude mcp list
```

## Windsurf [#windsurf]

<Steps>
  <Step title="Open MCP config">
    Go to &#x2A;*Windsurf Settings > Cascade > Model Context Protocol (MCP)** and click **Add Server** or edit your `~/.codeium/windsurf/mcp_config.json`.
  </Step>

  <Step title="Add the server">
    ```json
    {
      "mcpServers": {
        "surface-forms": {
          "serverUrl": "https://app.withsurface.com/mcp",
          "headers": { "Authorization": "Bearer <your-api-key>" }
        }
      }
    }
    ```
  </Step>

  <Step title="Verify connection">
    Refresh the MCP panel and check that `surface-forms` shows as connected.
  </Step>
</Steps>

## Other Editors [#other-editors]

Any editor that supports [Streamable HTTP](https://modelcontextprotocol.io/docs/concepts/transports#streamable-http) can connect to the Surface MCP server. Use this configuration:

```json
{
  "mcpServers": {
    "surface-forms": {
      "url": "https://app.withsurface.com/mcp",
      "headers": { "Authorization": "Bearer <your-api-key>" }
    }
  }
}
```

<Info>
  The Surface MCP server uses the **Streamable HTTP** transport, so there is no local process or Docker container to run.
</Info>

## Read-only Connections [#read-only-connections]

API keys are full-access, so the connection can create, edit, and publish. To hand a key to an agent that should only read, add `?readonly=1` to the URL:

```
https://app.withsurface.com/mcp?readonly=1
```

This drops every write and admin tool from the connection, whatever the credential allows. It combines with `?tools=`; see [Tool Bundles](/mcp-server/tool-bundles#read-only-connections).

## Troubleshooting [#troubleshooting]

<AccordionGroup>
  <Accordion title="Server not connecting">
    * Double-check that your API key is correct and hasn't been revoked.
    * Make sure the `Authorization` header uses the `Bearer` prefix.
    * Confirm your editor supports the Streamable HTTP transport.
  </Accordion>

  <Accordion title="A tool I expected is missing">
    * The default connection loads the forms and vault bundles. Add `?tools=all` (or the [bundle or family](/mcp-server/tool-bundles) you need) to the server URL.
    * On a `?readonly=1` connection, write tools are deliberately absent.
    * A `?tools=` selection containing a typo falls back to every tool rather than silently narrowing the set.
  </Accordion>

  <Accordion title="Tools not returning data">
    * Your API key is scoped to a specific environment. Make sure the environment has forms, responses, or leads to query.
    * Form edits save a draft. Visitors only see them after `publish_form` promotes the draft to live.
  </Accordion>

  <Accordion title="Rate limiting or timeouts">
    * The MCP server runs on the same infrastructure as the Surface app. If a call times out, try again in a moment.
    * For large datasets, use pagination parameters (`page`, `limit`) to fetch data in smaller chunks.
  </Accordion>
</AccordionGroup>
