# Tool Bundles



The Surface MCP server exposes 110 tools. Loading every definition upfront is real context pressure for an AI assistant, so a connection that doesn't ask for anything specific gets the **forms bundle**: the core form-building surface plus its responses and AI scores. Everything else is one config change away, as a curated bundle, a tool family, or an exact list of tool names.

## Bundles [#bundles]

Bundles are curated sets of tool families for a kind of session:

| Bundle     | Focus                                                  | Families                                           | Tools |
| ---------- | ------------------------------------------------------ | -------------------------------------------------- | ----- |
| `forms`    | Building forms and reading their results (the default) | forms, responses, scoring                          | 39    |
| `content`  | CMS, blogs, content analytics, AI visibility           | cms, contentReview, contentAnalytics, aiVisibility | 55    |
| `insights` | Responses, leads, analytics, scores, workflow runs     | analytics, scoring, leads, responses, workflows    | 20    |
| `admin`    | Team, members, environments, feedback                  | team, members, environments, feedback              | 4     |
| `all`      | Everything                                             | all 14 families                                    | 110   |

## Families [#families]

Families are the finer-grained unit underneath bundles. You can select any of them directly:

| Family             | What it covers                                               | Tools |
| ------------------ | ------------------------------------------------------------ | ----- |
| `forms`            | Create, edit, style, route, and publish forms                | 31    |
| `responses`        | Read form submissions                                        | 2     |
| `leads`            | Qualified leads and lead counts, lead import                 | 3     |
| `analytics`        | Form, funnel, landing page, and environment analytics        | 7     |
| `workflows`        | Workflow run logs and per-step details                       | 2     |
| `scoring`          | AI lead scores, response search, form comparisons            | 6     |
| `cms`              | Headless CMS content types, entries, and assets              | 25    |
| `contentReview`    | The blog review pipeline                                     | 12    |
| `contentAnalytics` | Content performance and AI traffic sources                   | 7     |
| `aiVisibility`     | AEO/GEO answer-engine visibility reports, prompts, and scans | 11    |
| `team`             | Team, subscription, and billing info                         | 1     |
| `members`          | Member invitations                                           | 1     |
| `environments`     | Environment creation                                         | 1     |
| `feedback`         | Product feedback to the Surface team                         | 1     |

## Choosing what loads [#choosing-what-loads]

Selection rides the `?tools=` query parameter on the one `/mcp` endpoint, so it works in every client that accepts a URL. The value is a comma-separated list mixing bundles, family names, and individual tool names:

```
https://app.withsurface.com/mcp                                       default forms bundle
https://app.withsurface.com/mcp?tools=all                             full surface
https://app.withsurface.com/mcp?tools=content                         one bundle
https://app.withsurface.com/mcp?tools=responses,leads                 families
https://app.withsurface.com/mcp?tools=forms,cms                       bundle + family
https://app.withsurface.com/mcp?tools=list_forms,get_form_analytics   individual tools
```

A few rules worth knowing:

* `forms` names the bundle, not the bare family, so `?tools=forms` also carries the responses and scoring tools.
* A selection containing any unknown name falls back to everything, so a typo cannot produce a zero-tool server or silently narrow the surface.
* A known tool name your connection's credential excludes (a write tool on a read-only connection) is skipped, not treated as a typo.

### Header alternative [#header-alternative]

For clients that configure headers but not URLs, the `X-Surface-Tool-Families` header takes the same comma-separated list. `?tools=` wins when both are present:

```json
{
  "headers": {
    "Authorization": "Bearer <your-api-key>",
    "X-Surface-Tool-Families": "content"
  }
}
```

### Per-client recipes [#per-client-recipes]

<CodeBlockTabs defaultValue="Claude Code">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="Claude Code">
      Claude Code
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Cursor">
      Cursor
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="Claude Desktop">
      Claude Desktop
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="Claude Code">
    ```sh
    # The default forms bundle needs no selection
    claude mcp add --transport http surface-forms "https://app.withsurface.com/mcp" \
      --header "Authorization: Bearer <your-api-key>"

    # An insights session
    claude mcp add --transport http surface-insights "https://app.withsurface.com/mcp?tools=insights" \
      --header "Authorization: Bearer <your-api-key>"
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Cursor">
    ```json
    // .cursor/mcp.json: an insights session
    {
      "mcpServers": {
        "surface-forms": {
          "url": "https://app.withsurface.com/mcp?tools=insights",
          "headers": { "Authorization": "Bearer <your-api-key>" }
        }
      }
    }
    ```
  </CodeBlockTab>

  <CodeBlockTab value="Claude Desktop">
    ```json
    // claude_desktop_config.json: everything
    {
      "mcpServers": {
        "surface-forms": {
          "url": "https://app.withsurface.com/mcp?tools=all",
          "headers": { "Authorization": "Bearer <your-api-key>" }
        }
      }
    }
    ```
  </CodeBlockTab>
</CodeBlockTabs>

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

Add `?readonly=1` to get a connection with no write or admin tools, whatever the credential can otherwise do. It combines with `?tools=`:

```
https://app.withsurface.com/mcp?readonly=1                  reads of the default forms bundle
https://app.withsurface.com/mcp?tools=all&readonly=1        every read tool (59 of the 110)
https://app.withsurface.com/mcp?tools=content&readonly=1    content reads only
```

API keys are full-access by design, so `?readonly=1` is the way to hand a key to an agent that should only read. OAuth connections without the write scope get the same read-only surface either way. This covers CMS tools too: a read-only connection cannot see `cms_delete_entry` or any other CMS write.

<Info>
  Whatever you select, every tool call stays scoped to the environment your API key or OAuth connection belongs to. Tool selection only changes which definitions your assistant loads, never what it's allowed to touch.
</Info>
