Sanity connector

Connect your own Sanity project as an MCP Tool so the marketing agent can publish content straight into it. Once connected, the agent can push content it creates in the app into your Sanity dataset instead of (or in addition to) keeping it only inside the app.

What it does

  • Blog posts, case studies, white papers, and markdown documents publish as structured Sanity documents — real content your Sanity-powered site can query, render, and index like any other Sanity content.
  • Landing pages and web forms publish as reference documents that stay hosted by the app. Sanity holds a pointer to the page (its live URL and embed URL), but the page itself (and its form) keeps running here — submissions keep flowing through the app's own submission endpoint via the embed.

Connecting Sanity

  1. Open Settings and go to the Connectors tab (labeled "MCP Tools").
  2. Choose Sanity from the catalog and click Connect.
  3. Enter:
    • Your Project ID and Dataset name, both found in your Sanity project.
    • An API token created at sanity.io/manage → your project → APITokens. The token needs Editor (write) access so the agent can create and update documents.
    • MCP user role (optional) — leave blank to use the token's own role. Set it only if your Sanity setup expects a specific role name (e.g. developer or editor) for write access.
  4. Assign the connection to the Marketing area so the agent can use it when publishing campaign content.

What you can publish

ModeContent typesWhere it lives
Structured document (thoughtfulyPost)Blog posts, case studies, white papers, markdown documentsFully in Sanity, as a real document
Reference document (thoughtfulyHostedPage)Landing pages, web formsHosted in the app; Sanity holds a reference (title, live URL, embed URL)

The schema: thoughtfulyPost and thoughtfulyHostedPage

The connector uses two document types — thoughtfulyPost for structured content and thoughtfulyHostedPage for hosted-page references.

You usually don't have to create these by hand. When it publishes, the agent checks whether the two types already exist in your project and, if they don't, registers them for you — additively, so it never drops document types your project already has. (If the agent can't safely read your current schema to add to it, it stops and asks you to add the types yourself rather than risk overwriting your schema.)

Registering the schema is what lets Sanity Studio recognize and validate these documents. Your front-end site still needs components to render them (see Rendering below).

If you prefer to manage schema in your own Studio repo, add these type definitions yourself:

// schemaTypes/thoughtfulyPost.ts
import {defineType, defineField} from 'sanity'
import {DocumentTextIcon} from '@sanity/icons'

export const thoughtfulyPost = defineType({
  name: 'thoughtfulyPost',
  title: 'Post',
  type: 'document',
  icon: DocumentTextIcon,
  fields: [
    defineField({name: 'title', type: 'string'}),
    defineField({name: 'slug', type: 'slug', options: {source: 'title'}}),
    defineField({name: 'excerpt', type: 'text'}),
    defineField({name: 'publishedAt', type: 'datetime'}),
    defineField({name: 'heroImage', type: 'image'}),
    defineField({
      name: 'body',
      type: 'text',
      description: 'Markdown — render with a Markdown component',
    }),
    defineField({
      name: 'docKind',
      type: 'string',
      options: {
        list: [
          {title: 'Post', value: 'post'},
          {title: 'Case study', value: 'caseStudy'},
          {title: 'White paper', value: 'whitePaper'},
        ],
        layout: 'radio',
      },
    }),
    defineField({
      name: 'sourceArtifactId',
      type: 'string',
      description: 'Originating app artifact id — used to update the same document on re-publish.',
      readOnly: true,
    }),
  ],
})
// schemaTypes/thoughtfulyHostedPage.ts
import {defineType, defineField} from 'sanity'
import {DocumentIcon} from '@sanity/icons'

export const thoughtfulyHostedPage = defineType({
  name: 'thoughtfulyHostedPage',
  title: 'Hosted page',
  type: 'document',
  icon: DocumentIcon,
  fields: [
    defineField({name: 'title', type: 'string'}),
    defineField({name: 'slug', type: 'slug', options: {source: 'title'}}),
    defineField({name: 'externalUrl', type: 'url', description: 'Live page URL (hosted by the app)'}),
    defineField({name: 'embedUrl', type: 'url', description: 'Iframe embed URL (externalUrl + /embed.js)'}),
    defineField({name: 'description', type: 'text'}),
    defineField({name: 'ogImage', type: 'image', title: 'Social share image'}),
    defineField({
      name: 'sourceArtifactId',
      type: 'string',
      description: 'Originating app artifact id — used to update the same document on re-publish.',
      readOnly: true,
    }),
  ],
})

Rendering

Sanity stores content but doesn't render it — your deployed Sanity front-end does. Add rendering for both types:

  • Render thoughtfulyHostedPage as an iframe of embedUrl. Forms inside the iframe keep posting back to the app's own submission endpoint, so they keep working exactly as they do today — Sanity only holds the reference, not the form itself. externalUrl is the direct link to the live page.
  • Render thoughtfulyPost.body with your Markdown component, the same way you'd render any other Markdown field.

Notes / limits

  • No duplicates on re-publish. The agent stamps each document with a sourceArtifactId and looks it up before writing, so re-publishing the same artifact updates the same Sanity document (Sanity assigns the document _id).
  • Schema registration is additive. The agent only ever adds the two types to your schema; it never removes types you already have.
  • The app keeps hosting landing pages and web forms. Sanity only holds a reference document for these; it never becomes the source of truth for the page or its form.
  • Your API token needs write access to publish. A read-only token will connect but publishing will fail.