Optimizely Cms
FreeNot checkedEnables AI assistants to interact with Optimizely CMS via its GraphQL and Content Management APIs, supporting dynamic content discovery, retrieval, and manageme
About
Enables AI assistants to interact with Optimizely CMS via its GraphQL and Content Management APIs, supporting dynamic content discovery, retrieval, and management.
README
A Model Context Protocol (MCP) server for Optimizely CMS, providing AI assistants with comprehensive access to Optimizely's GraphQL API and Content Management API.
Version
Current Version: 2.0.0-beta Status: Beta / Pre-Release
This is an active development version and is not yet a release candidate. Features are subject to change, and additional testing is required before production use.
Features
Core Capabilities
- Discovery-First Architecture: Zero hardcoded assumptions about content types or fields
- Dynamic Schema Introspection: Discovers available content types and fields at runtime
- Unified Content Retrieval: Get any content by URL, key, GUID, or search term in one call
- Visual Builder Support: Full support for Optimizely Visual Builder pages with composition structure
- Content Management: Create and manage content via interactive wizard
- Intelligent Field Mapping: Pattern-based field matching with confidence scoring
- GraphQL & CMA Integration: Direct access to both Graph API (read) and Content Management API (write)
- Smart Caching: Built-in caching for improved performance
- Type Safety: Full TypeScript support with runtime validation
API Support
- Graph API: Fast content retrieval, search, and discovery
- Content Management API: Content creation, updates, and draft access
- Dual Authentication: Supports both Graph (single key, HMAC) and CMA (OAuth2) authentication
Installation
# Clone the repository
git clone https://github.com/your-org/optimizely-mcp-server.git
cd optimizely-mcp-server
# Install dependencies
npm install
# Build the project
npm run build
Configuration
Create a .env file in the project root:
# Server Configuration
SERVER_NAME=optimizely-mcp-server
SERVER_VERSION=1.0.0
TRANSPORT=stdio
# Optimizely Graph Configuration
GRAPH_ENDPOINT=https://cg.optimizely.com/content/v2
GRAPH_AUTH_METHOD=single_key # Options: single_key, hmac, basic, bearer, oidc
GRAPH_SINGLE_KEY=your-single-key
# For HMAC auth:
# GRAPH_APP_KEY=your-app-key
# GRAPH_SECRET_KEY=your-secret-key
# Content Management API Configuration
CMA_BASE_URL=https://api.cms.optimizely.com/preview3
CMA_CLIENT_ID=your-client-id # Get from Settings > API Keys in CMS
CMA_CLIENT_SECRET=your-client-secret
CMA_GRANT_TYPE=client_credentials
CMA_TOKEN_ENDPOINT=https://api.cms.optimizely.com/oauth/token
CMA_IMPERSONATE_USER= # Optional: User email to impersonate (see Impersonation section)
# Optional Configuration
CACHE_TTL=300000 # Cache TTL in milliseconds (default: 5 minutes)
LOG_LEVEL=info # Options: debug, info, warn, error
MAX_RETRIES=3
TIMEOUT=30000
Running the Server
Development Mode
# Run with hot reloading
npm run dev
# Run with debug logging
LOG_LEVEL=debug npm run dev
Production Mode
# Build and run
npm run build
npm start
# Or run directly
node dist/index.js
Testing the Server
# Run all unit tests
npm test
# Run tests with coverage
npm run test:coverage
# Type checking
npm run typecheck
# Linting
npm run lint
How MCP Servers Work
MCP servers communicate via stdio (standard input/output), not HTTP ports:
- No port required - The server doesn't listen on any network port
- Process-based - Claude Desktop spawns your server as a child process
- JSON-RPC messages - Communication happens through stdin/stdout pipes
- Secure - No network exposure, runs only when Claude needs it
MCP Client Configuration
Claude Desktop Setup
Step 1: Find your config file
Open the configuration file in a text editor:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
For Windows, you can open it quickly with:
notepad %APPDATA%\Claude\claude_desktop_config.json
Step 2: Add the server configuration
{
"mcpServers": {
"optimizely": {
"command": "node",
"args": ["%USERPROFILE%\\path\\to\\optimizely-mcp-server\\dist\\index.js"],
"env": {
"LOG_LEVEL": "error",
"GRAPH_ENDPOINT": "https://cg.optimizely.com/content/v2",
"GRAPH_AUTH_METHOD": "single_key",
"GRAPH_SINGLE_KEY": "your-key",
"CMA_BASE_URL": "https://api.cms.optimizely.com/preview3/experimental",
"CMA_CLIENT_ID": "your-client-id",
"CMA_CLIENT_SECRET": "your-client-secret",
"CMA_GRANT_TYPE": "client_credentials",
"CMA_TOKEN_ENDPOINT": "https://api.cms.optimizely.com/oauth/token",
"CMA_IMPERSONATE_USER": ""
}
}
}
}
In JSON on Windows, you must use double backslashes (\). If your folder path has spaces, this still works because each argument is a separate JSON string.
- Windows: %USERPROFILE% expands to your home directory (e.g., C:\Users\Alice). If Claude doesn’t expand it automatically, replace it with your actual path (e.g., C:\Users\Alice\path\to\optimizely-mcp-server\dist\index.js). In PowerShell, the equivalent is $env:USERPROFILE, but inside this JSON config you should keep %USERPROFILE% or use the full path.
- macOS/Linux: the equivalent shortcut is ~ or $HOME (e.g., /Users/alice or /home/alice). If ~/$HOME isn’t expanded correctly, replace it with the full path.
Step 3: Restart Claude Desktop
After saving the config file:
- Completely quit Claude Desktop (not just close the window)
- Start Claude Desktop again
- The Optimizely tools should now be available
Step 4: Verify it's working
In a new Claude conversation, try:
- "Can you list the available Optimizely tools?"
- "Use the health-check tool to test the connection"
Troubleshooting
If the server doesn't load:
- Check the file path is correct and uses proper escaping (
\\for Windows) - Ensure you've built the project (
npm run build) - Verify the
dist/index.jsfile exists - Check Claude's logs for errors
Other MCP Clients
For other MCP-compatible clients, use the stdio transport configuration:
{
"name": "optimizely",
"transport": {
"type": "stdio",
"command": "node",
"args": ["/path/to/optimizely-mcp-server/dist/index.js"]
},
"env": {
// Environment variables as above
}
}
Available Tools (14 Total)
🌟 Core Discovery & Retrieval Tools
These tools use the Graph API to dynamically discover your CMS structure and retrieve content without hardcoded assumptions.
help- 🚀 START HERE! Get context-aware help and learn the discovery-first workflow- Examples:
help({}),help({"topic": "workflow"})
- Examples:
get- 🎯 UNIFIED TOOL - Get content by ANY identifier in ONE call- Replaces the old
search→locate→retrieveworkflow - Auto-discovers fields and returns complete content
- ✅ Supports Visual Builder pages with full composition structure
- Examples:
get({"identifier": "/"}),get({"identifier": "Article 4"})
- Replaces the old
discover- Find content types and fields dynamically- No hardcoded assumptions about your CMS structure
- Examples:
discover({"target": "types"}),discover({"target": "fields", "contentType": "ArticlePage"})
analyze- Deep analysis of content type requirements- Understand fields, constraints, and defaults
- Example:
analyze({"contentType": "ArticlePage"})
search- Intelligent content search with auto-discovery- ⚠️ Note:
getis usually better for most use cases - Example:
search({"query": "mcp", "contentTypes": ["ArticlePage"]})
- ⚠️ Note:
locate- Find specific content by ID, key, or path- ⚠️ Note:
getis usually better for most use cases - Example:
locate({"identifier": "/news/article-1"})
- ⚠️ Note:
retrieve- Get full content from Content Management API- ⚠️ Note:
getis usually better (uses faster Graph API) - Use only when
getsuggests it or you need CMA-specific data - Example:
retrieve({"identifier": "12345"})
- ⚠️ Note:
🔧 Utility Tools (3)
health-check- Check API connectivity and server healthget-config- Get current server configuration (sanitized)get-documentation- Get documentation for available tools by category
🔧 Content Management Tools (CMA API)
These tools use the Content Management API for write operations and detailed content access:
content_creation_wizard- Interactive content creation with discovery- Essential for creating new content
- Example:
content_creation_wizard({"step": "start"})
content-test-api- Test CMA connectivity and endpoints- Validates authentication and permissions
- Example:
content-test-api({})
Note: The retrieve tool (listed in Core Tools above) also uses CMA for accessing draft content and version history.
⚠️ Deprecated Tools (Being Removed)
These Graph API discovery tools are duplicates of the new discover tool and will be removed in a future version:
graph-introspection- Usediscoverinsteadtype-discover- Usediscover({"target": "types"})insteadtype-match- Usediscoverinsteadcontent_type_analyzer- Useanalyzeinsteadgraph_discover_types- Usediscover({"target": "types"})insteadgraph_discover_fields- Usediscover({"target": "fields"})insteadgraph-query- Usegetorsearchinstead
Key Architecture Principles
Discovery-First Design
Unlike traditional integrations that hardcode content types and field names, this MCP server:
- Never hardcodes content types - No assumptions about "ArticlePage", "StandardPage", etc.
- Never hardcodes field mappings - No predefined paths like "SeoSettings.MetaTitle"
- Discovers everything dynamically - Uses introspection to understand your CMS
- Adapts to any CMS configuration - Works with custom content types and fields
Intelligent Field Mapping
The server uses pattern matching and similarity scoring to:
- Map user-friendly field names to actual CMS fields
- Handle nested properties automatically
- Generate appropriate default values based on field types
- Provide confidence scores for mappings
Recommended Workflows
Simple Content Retrieval (Most Common)
1. get({"identifier": "homepage"}) # That's it! One call gets everything.
The get tool automatically:
- Detects identifier type (search term, URL, key, or GUID)
- Finds the content
- Discovers all available fields
- Returns complete content including Visual Builder composition
Advanced Discovery Workflow
1. help({}) # Learn the workflow
2. discover({"target": "types"}) # Find content types
3. discover({"target": "fields", "contentType": "..."}) # Get fields
4. get({"identifier": "..."}) # Retrieve content
Content Creation Workflow
1. discover({"target": "types"}) # Find available types
2. analyze({"contentType": "ArticlePage"}) # Understand requirements
3. content_creation_wizard({...}) # Create with guidance
Visual Builder Support
The get tool fully supports Optimizely Visual Builder (formerly known as Visual Experience Composer) pages:
Features
- ✅ Automatic Detection - Recognizes Visual Builder pages by interface (
_IExperience) - ✅ Complete Composition Retrieval - Returns full structure in a single call
- ✅ Nested Structure - Handles grids, rows, columns, and components
- ✅ Component Content - Includes inline component data directly in composition
- ✅ Recursive Depth - Supports any level of nesting
Understanding Component Types
Visual Builder components come in two types:
1. Inline Components (Embedded Content)
- Key:
nullor not present - Content Location: Stored directly in the composition structure
- Access: Content is already included in the
getresponse - Example: Text components with content like "Welcome to our site"
{
"component": {
"_metadata": {
"types": ["Text", "_Component"],
"key": null // ← NULL = inline
},
"Content": "Welcome Text" // ← Content is here
}
}
Important: Do NOT try to retrieve inline components separately - the content is already provided!
2. Referenced Components (Separate Content Items)
- Key: Valid GUID (e.g., "f7e7f5c9-1e77-4884-a8fc-a9c9ae56560c")
- Content Location: Stored as separate content items in CMS
- Access: Use
get({"identifier": "component-key"})to retrieve full details - Example: Shared components like Site Settings, reusable blocks
{
"component": {
"_metadata": {
"types": ["ArticleList", "_Component"],
"key": "f7e7f5c91e774884a8fca9c9ae56560c" // ← Has key
}
// May include basic fields, use get() for full content
}
}
Best Practices
When working with Visual Builder pages:
- First, retrieve the page with
get({"identifier": "/"}) - Inspect the composition structure for components
- For inline components (null key): Content is already in the response ✅
- For referenced components (has key): Use
get({"identifier": "key"})to fetch full details
Example Usage
// Get a Visual Builder homepage
get({"identifier": "/"})
// Returns complete structure with inline content:
{
"content": {
"_metadata": { ... },
"composition": {
"nodes": [
{
"key": "grid-id",
"displayName": "Welcome Section",
"nodes": [
{
"component": {
"_metadata": {
"types": ["Text"],
"key": null // Inline - content included
},
"Content": "Welcome to our site"
}
},
{
"component": {
"_metadata": {
"types": ["ArticleList"],
"key": "f7e7f5c9..." // Referenced - fetch separately
}
}
}
]
}
]
}
}
}
Known Limitations
- Performance - Large compositions may take longer to retrieve due to nested structure
- Referenced Component Details - Basic metadata only; full content requires separate
get()call - Display Settings - Not included in current implementation (can be added if needed)
Important Notes
Content Indexing Delay
After creating new content using the content_creation_wizard or other creation tools:
- Immediate availability in CMA: Content is immediately available via
retrievetool - Graph API indexing delay: Content may take 1-5 minutes to appear in Graph API results
- Tool behavior: The
getandsearchtools use Graph API and will return "not found" for newly created content until indexing completes
Best practice: After creating content, wait a few minutes before attempting to retrieve it with get or search. Alternatively, use the retrieve tool which queries the CMA directly and has no indexing delay.
Draft vs Published Content
- Graph API: Only returns published content
- CMA API: Returns both draft and published content
- New content: Created in draft status by default
- To make content searchable via
get/search, it must be published first
Development
Project Structure
optimizely-mcp-server/
├── src/
│ ├── index.ts # Server entry point
│ ├── register.ts # Tool registration
│ ├── config.ts # Configuration management
│ ├── clients/ # API clients
│ │ ├── graph-client.ts
│ │ └── cma-client.ts
│ ├── logic/ # Tool implementations
│ │ ├── utility/
│ │ ├── graph/
│ │ └── content/
│ ├── types/ # TypeScript types
│ └── utils/ # Utilities
├── tests/ # Test files
├── dist/ # Built output
└── package.json
Adding New Tools
- Create tool implementation in
src/logic/ - Add tool registration in appropriate section
- Add TypeScript types if needed
- Write tests in
tests/ - Update documentation
Testing Guidelines
- Unit tests for all tool implementations
- Integration tests for API clients
- Mock external API calls
- Test error scenarios
- Maintain >80% coverage
Testing & Debugging
Unit Tests
Run automated tests with Vitest:
# Run unit tests
npm test
# Run with coverage report
npm run test:coverage
Unit tests are located in /tests/ and cover:
- GraphQL client functionality
- CMA client operations
- Health check features
Integration Testing & Debugging
Test your setup with these npm scripts:
# Check credentials are valid
npm run check:credentials
# Test MCP tools
npm run test:tools
# Test with debug output
npm run test:tools:debug
# Test GraphQL connection
npm run debug:graph
# Validate API key format
npm run validate:key
Troubleshooting
Common Issues
Authentication Errors
- Verify your API credentials in
.env - For CMA: Create API keys in Settings > API Keys in your Optimizely CMS instance
- Check token expiration for CMA (tokens expire after 5 minutes)
- Ensure correct auth method for Graph
- Verify your API credentials in
Connection Issues
- Verify network connectivity
- Check firewall settings
- Confirm API endpoints are accessible
Build Errors
- Run
npm installto ensure dependencies - Check Node.js version (>=18 required)
- Clear
dist/and rebuild
- Run
403 Forbidden Errors (Content Creation)
- This typically means insufficient permissions
- See the Impersonation section below for a solution
- Verify the user has content creation rights
- Check the target container allows the content type
Debug Mode
Enable debug logging for troubleshooting:
LOG_LEVEL=debug npm start
Health Check
Test server connectivity:
# Using the built tool
echo '{"method": "tools/call", "params": {"name": "health_check"}}' | node dist/index.js
User Impersonation
If you encounter 403 Forbidden errors when creating content, you can use user impersonation to execute API calls as a specific user who has the necessary permissions.
When to Use Impersonation
Use impersonation when:
- The API client lacks content creation permissions
- You need to test with different user permission levels
- You want actions attributed to a specific user
Setup Instructions
Enable Impersonation in Optimizely CMS:
- Log into Optimizely CMS as an administrator
- Navigate to Settings > API Clients
- Find your API client
- Enable the "Allow impersonation" option
- Save the changes
Configure the MCP Server:
# In your .env file [email protected]Update Claude Desktop Config (if using environment variables):
{ "mcpServers": { "optimizely": { "env": { "CMA_IMPERSONATE_USER": "[email protected]", // ... other settings } } } }
How It Works
When impersonation is configured:
- Authentication requests use JSON format with
act_asfield - All content operations execute as the impersonated user
- Created content shows the impersonated user as the author
Testing Impersonation
Test that impersonation is working:
# Run the impersonation test script
node scripts/test-impersonation-final.js
This will create test content and show which user created it.
Security Best Practices
- Only enable impersonation when necessary
- Use accounts with minimal required permissions
- Regularly review API client permissions
- Monitor API usage logs for unusual activity
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Run
npm testandnpm run typecheck - Submit a pull request
License
MIT
Installing Optimizely Cms
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/first3things/optimizely-cms-mcpFAQ
Is Optimizely Cms MCP free?
Yes, Optimizely Cms MCP is free — one-click install via Unyly at no cost.
Does Optimizely Cms need an API key?
No, Optimizely Cms runs without API keys or environment variables.
Is Optimizely Cms hosted or self-hosted?
A hosted option is available: Unyly runs the server in the cloud, no local setup required.
How do I install Optimizely Cms in Claude Desktop, Claude Code or Cursor?
Open Optimizely Cms on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
by modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
by xuzexin-hzCompare Optimizely Cms with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All ai MCPs
