Surface docs

Tools

The tools the Surface MCP server offers, with their arguments, results and errors.

Every tool takes a surface_id — never a content source id. Results are scoped to the key holder's workspace: another workspace's surface reads as not found. No tool deletes anything; archive instead, or use the dashboard.

surface_list

List surfaces. Every surface in the key holder's organization.

No arguments.

Returns { surfaces: Surface[] }

surface_get

Get a surface. Full details for one surface, including its edge_url and dashboard_url. To open the surface in the dashboard, open dashboard_url.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.

Returns { surface: Surface, dashboard_url: string }

Errors SURFACE_NOT_FOUND, INVALID_ARGUMENTS

Example arguments
{
  "surface_id": 52
}

surface_create

Create a surface. Creates the surface and its content source. Add content with variant_create.

ArgumentTypeRequiredDescription
namestringYesUnique within the organization.
page_urlstringYesThe page the surface appears on.
paradigmRANKING | VARIANT_SELECTIONYesHow variants are chosen.
descriptionstringNoFree text.

Returns { surface: Surface, dashboard_url: string }

Errors PLAN_LIMIT_REACHED, INVALID_ARGUMENTS

Example arguments
{
  "name": "Homepage hero",
  "page_url": "https://example.com/",
  "paradigm": "VARIANT_SELECTION"
}

surface_setup

Set up a surface on a page. One step from a page to a deployed surface: the fields variants replace, the goals to optimize, and the variants, with the integration bundle built and deployed. Variants are active; nothing shows until the snippet is on the page. The setup_surface prompt walks an agent through it.

ArgumentTypeRequiredDescription
namestringYesUnique within the organization.
page_urlstringYesThe live URL of the page.
fields{ key, selector, value_type, description? }[]YesKeys match ^[a-z][a-z0-9_]*$. value_type: text | html | image | video | input_value.
goals{ name, selector, dom_event }[]Yesdom_event: click | submit. The first is the one the bandit optimizes.
variants{ contents, is_control? }[]YesAt least two; exactly one control, setting every field.
descriptionstringNoFree text.

Returns { surface: Surface, dashboard_url: string, variants: Variant[], events: string[], install_guide: string }

Errors PLAN_LIMIT_REACHED, INVALID_ARGUMENTS, SETUP_FAILED

Example arguments
{
  "name": "Pricing hero",
  "page_url": "https://example.com/pricing",
  "fields": [
    {
      "key": "headline",
      "selector": "[data-surface-field=\"headline\"]",
      "value_type": "text"
    }
  ],
  "goals": [
    {
      "name": "Book a demo",
      "selector": "[data-surface-goal=\"book_demo\"]",
      "dom_event": "click"
    }
  ],
  "variants": [
    {
      "contents": {
        "headline": "Pricing"
      },
      "is_control": true
    },
    {
      "contents": {
        "headline": "Plans that pay for themselves"
      }
    }
  ]
}

surface_update

Update a surface. Change one or more fields. Only the fields listed here are writable.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.
namestringNoUnique within the organization.
descriptionstringNoFree text.
statusACTIVE | ARCHIVEDNoArchive to stop serving.
paradigmRANKING | VARIANT_SELECTIONNoHow variants are chosen.
edge_routestringNoThe /api/<route> the surface serves on.
page_urlstringNoThe page the surface appears on.
locationWORLDWIDE | UNITED_STATES | EUROPE | ASIA_PACIFICNoServing region.

Returns { surface: Surface }

Errors SURFACE_NOT_FOUND, INVALID_ARGUMENTS — also when no field is given

Example arguments
{
  "surface_id": 52,
  "description": "Updated from Claude Code"
}

variant_list

List variants. The content variants a surface serves.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.

Returns { variants: Variant[] }

Errors SURFACE_NOT_FOUND

Example arguments
{
  "surface_id": 52
}

variant_create

Create variants. Adds variants as DRAFT. Fields other than is_control and segment_id are stored as the variant's content.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.
variantsobject[]YesAt least one. Optional is_control (one per segment) and segment_id.

Returns { variants: Variant[] } — the surface's full list

Errors MULTI_SURFACE_SOURCE, SURFACE_NOT_FOUND, INVALID_ARGUMENTS

Example arguments
{
  "surface_id": 52,
  "variants": [
    {
      "headline": "Ship faster"
    },
    {
      "headline": "Launch today"
    }
  ]
}

variant_update

Edit a draft variant. Replace a draft variant's contents. Only drafts can be edited.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.
variant_idintegerYesThe variant id, from variant_list.
contentsobjectYesThe new contents, in the shape variant_create takes.

Returns { variant: Variant }

Errors VARIANT_NOT_FOUND, INVALID_ARGUMENTS — e.g. the variant isn't a draft

Example arguments
{
  "surface_id": 52,
  "variant_id": 300,
  "contents": {
    "headline": "Ship faster"
  }
}

variant_set_status

Set a variant's status. Activate, pause or archive a variant. Only active variants are served. Same rules as the dashboard.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.
variant_idintegerYesThe variant id, from variant_list.
statusACTIVE | PAUSED | ARCHIVEDYesThe new status.

Returns { variant: Variant }

Errors VARIANT_NOT_FOUND, MULTI_SURFACE_SOURCE, INVALID_ARGUMENTS

Example arguments
{
  "surface_id": 52,
  "variant_id": 300,
  "status": "ACTIVE"
}

variant_set_control

Set the control variant. Make a variant the control of its segment, replacing the current control.

ArgumentTypeRequiredDescription
surface_idintegerYesThe surface id, from surface_list.
variant_idintegerYesThe variant id, from variant_list.

Returns { variant: Variant }

Errors VARIANT_NOT_FOUND, INVALID_ARGUMENTS — archived target, or no control to swap

Example arguments
{
  "surface_id": 52,
  "variant_id": 301
}

On this page