Developer Demo
CMS MCP Server
The Optimizely SaaS CMS ships a native Model Context Protocol server. Connect any MCP-compatible AI assistant to your CMS and interact with content, schemas, and navigation through natural language - no GraphQL or REST knowledge required.
Setup #
Add one entry to your project's .mcp.json file. The MCP server is hosted by Optimizely - there is nothing to deploy or maintain on your side. Your AI assistant discovers available tools automatically on first connection.
{
"mcpServers": {
"cms": {
"type": "http",
"url": "https://cms.mcp.opal.optimizely.com/mcp"
}
}
}What the server exposes
Returns all registered content types with their property schemas and base types
Fetches a content item by key, URL, or Graph reference - supports draft and published modes
Creates a new content item via the Management API with typed property validation
Patches an existing content item - accepts partial property updates
Issues a Graph query described in plain language and returns the matching items
Moves a draft to published status and triggers ISR revalidation
How a prompt becomes a CMS operation
Developer prompt
natural language
MCP client
Claude / Cursor / Copilot
MCP server
cms.mcp.opal.optimizely.com
Graph / Mgmt API
authenticated request
CMS updated
draft or published
Content Type Exploration #
Auditing content types in the CMS UI means navigating menus for each type individually. With MCP it is a single natural-language query. Useful when onboarding to an existing project, debugging a Graph query that returns unexpected fields, or figuring out what properties are available before writing a seed script.
Example
Inspect a content type
Developer prompt
“What properties does ArticlePage expose? Which ones are searchable and which are content references?”
- 1MCP calls list_content_types and filters to ArticlePage
- 2Returns property names, types (string, richText, contentReference, array), and indexing flags
- 3Searchable fields are highlighted - these are what Graph full-text search covers
- 4Content reference fields include their allowedTypes so you know what can be linked
Example
Find all types that extend a base type
Developer prompt
“Which content types use _page as their base type, and which ones support display template variants?”
- 1MCP calls list_content_types and groups results by baseType
- 2Types with registered display templates are flagged
- 3Useful when deciding whether a new page type should extend _page or _experience
- 4Returns the compositionBehaviors for each type (elementEnabled vs sectionEnabled)
Example
Check allowed types in a content area
Developer prompt
“What blocks are allowed inside the sections content area on DynamicExperience pages?”
- 1MCP fetches the DynamicExperience content type definition
- 2Returns the allowedTypes array for the sections property
- 3Lists each allowed block type with its own property schema
- 4Useful before building a composition script to know what block types are valid
Example
Understand a property constraint
Developer prompt
“Does HeroBlock use elementEnabled or sectionEnabled? Can it contain child content areas?”
- 1MCP fetches HeroBlock from the content type registry
- 2Returns compositionBehaviors: elementEnabled means it is a leaf node
- 3Confirms that adding a content area property to it would be silently ignored by the CMS
- 4Saves a round-trip of deploying a broken schema to find this out at runtime
Querying & Auditing #
Ask questions about your content library in plain language. The MCP server translates them into Graph queries with the correct filters, pagination, and locale scope - useful for audits, debugging, and ad hoc content checks during development.
Example
Find stale content
Developer prompt
“Which ArticlePages in the investments category haven't been updated in the last 60 days? Show me their titles and last-modified dates.”
- 1MCP builds a Graph query filtering by category='investments' and publishDate
- 2Sorts results by publishDate ascending to surface the most stale items first
- 3Returns titles, slugs, publishDate, and Management API edit links
- 4Can be followed up with: 'Flag all of them for review' to batch-patch their status
Example
Debug a missing content item
Developer prompt
“The page at /en/insights/articles/mortgage-rates-explained isn't rendering. Is it published? Does it have an author set?”
- 1MCP calls get_content with the URL to fetch the item regardless of publish state
- 2Checks _metadata.status to confirm whether it is draft, published, or deleted
- 3Inspects the author field - single content references return only base metadata
- 4Reports missing fields and suggests the next fix (set author, publish draft, etc.)
Example
Count content by type
Developer prompt
“How many ArticlePages exist per category? I want to know if any category is underpopulated before we launch.”
- 1MCP queries ArticlePages with a facet on the category field
- 2Graph returns facet counts without fetching all items - efficient for large libraries
- 3Results show each category label alongside its article count
- 4Immediately actionable: 'Create two more articles in the business-banking category'
Example
Inspect navigation structure
Developer prompt
“Show me the full nav tree. I want to see every node, its URL, and how many levels deep it goes.”
- 1MCP calls query_content with the @recursive directive on the navigation type
- 2Returns the full tree with node labels, hrefs, and nesting depth
- 3Useful before running a seed script that modifies nav to understand the current shape
- 4Can be followed up with: 'Add a node under Insights for the new Savings hub'
Example
Plan a type deprecation
Developer prompt
“We are deprecating LegacyBannerBlock. Find every page that still has it in a content area and give me a list of URLs and edit links.”
- 1MCP queries Graph for all content items whose composition includes LegacyBannerBlock
- 2Returns parent page keys, titles, and CMS edit links for each affected item
- 3Surfaces draft and published pages separately so the migration can be phased
- 4Immediately actionable - follow up with 'Replace each one with HeroBlock using the same heading and image'
Developer Workflow Integration #
The MCP server fits into common development tasks - not just one-off content operations. These examples show how it speeds up the feedback loop when building new content types, writing seed scripts, or debugging Graph query issues. It also helps when onboarding new developers - instead of learning the CMS UI to understand the content model, they can ask the MCP server directly.
Example
Validate a new content type before pushing
Developer prompt
“I'm about to push a new PressReleasePage type. Check whether anything in the existing schema conflicts with the property names I've defined.”
- 1MCP lists all registered content types and their property key namespaces
- 2Cross-references against the new type's property list for collisions
- 3Flags any property key that already exists on a parent or sibling type
- 4Saves a round-trip of running opti:push only to hit a schema validation error
Example
Generate a seed script from an existing item
Developer prompt
“Look at the case study at /en/insights/case-studies/local-bakery-growth and generate a seed script stub that creates a similar item.”
- 1MCP calls get_content on the case study URL to fetch its full property shape
- 2Reads referenced OutcomeItemBlock and TestimonialBlock keys from the composition
- 3Outputs a TypeScript snippet following the scripts/seed-modeling.ts pattern
- 4Includes the cms://content/{key} reference format for all content area items
Example
Reproduce a Graph query result locally
Developer prompt
“The GetArticles query is returning no results for the 'market-insights' category. Run it against the live CMS and tell me what's coming back.”
- 1MCP executes the query against the Graph delivery API with the given filter
- 2Returns the raw response including any empty arrays or null fields
- 3Reports whether the category enum value matches what is stored on published items
- 4Surfaces whether the articles exist as drafts but haven't been published yet
Example
Clean up after a seed run
Developer prompt
“The seed script created duplicate FAQ items. Find all FaqItemBlocks whose question starts with 'What is' and delete the extras, keeping only the most recently created one.”
- 1MCP queries FaqItemBlocks matching the question prefix filter
- 2Sorts by _metadata.created descending to identify the newest item
- 3Calls the Management API delete endpoint for each duplicate key
- 4Confirms deletion by re-querying and returning the remaining item count
Example
Scaffold a block component from a content type
Developer prompt
“Read the PricingTierBlock content type and generate a TypeScript React component that renders all its properties with the correct data-component attribute and preview utils.”
- 1MCP calls list_content_types and returns PricingTierBlock's full property schema
- 2AI maps each property type to its rendering pattern - string to <p>, richText to <RichText />, contentReference to <Image />
- 3Generates the component with correct TypeScript types, pa() preview attributes, and data-component
- 4No need to open the CMS UI, copy field names by hand, or guess at property shapes
Supported MCP clients
Any tool implementing the Model Context Protocol can connect to the same server endpoint. No per-client integration is needed on the Optimizely side.
OPTIMIZELY_CMS_CLIENT_ID and OPTIMIZELY_CMS_CLIENT_SECRET ). Set them once in your environment and every tool call in the session is automatically authenticated - no token management in prompts.