MCP server for CMS 13
Set up the Model Context Protocol (MCP) server for CMS 13 to connect AI developer tools like Claude Code, Cursor, and Codex to your CMS content and configuration.
The Optimizely.Cms.Opal.Tools package includes a Model Context Protocol (MCP) server that exposes the same CMS tools available through Opal Chat to any MCP-compatible AI client. Manage CMS content, content types, and display templates from your development environment with an MCP client such as Claude Code or Cursor. The MCP server puts these tools in the editor where you write code, so you can create content types and display templates while building the templates that render them.
The MCP server shares the same tools and descriptions as the Opal protocol. See Available tools for CMS 13 for the full tool reference.
Prerequisites
- .NET 10.0 or later.
Optimizely.Cms.Opal.Tools13.2.0 or later.- An authentication method configured (see Authentication and authorization).
Install and configure
Register the MCP server
Add the MCP server to your service collection in Startup.cs or Program.cs. Chain an authentication method to configure how MCP clients authenticate.
services.AddCmsMcpServer().WithClientSecretAuthentication();AddCmsMcpServer() registers the MCP server with stateless HTTP transport and all CMS tools. The chained authentication method (for example, WithClientSecretAuthentication()) configures how the server validates incoming requests.
Map the MCP endpoint
Map the MCP endpoint in your application pipeline and apply the matching authorization policy.
app.UseEndpoints(endpoints =>
{
endpoints.MapContent();
endpoints.MapMcp("/mcp").RequireClientSecretAuthorization();
});The convenience extension method RequireClientSecretAuthorization() applies the correct authorization policy for the authentication method.
Authentication and authorization
Every MCP tool call executes CMS operations on behalf of an authenticated user. The MCP server requires an authentication method that establishes a user identity so that all content operations respect CMS permissions.
Choose an authentication method
| Method | Use case | Identity | Permissions |
|---|---|---|---|
| Client secret | Local development, secure internal environments | Application identity with CmsAdmins role | Full access to all tools |
| Custom | Integration with existing auth systems | Depends on implementation | Depends on identity mapping |
| Optimizely Identity | Coming in a future release | Individual Opti ID user | Per-user CMS permissions |
Client secret authentication is designed for local development where the network is trusted and permission scoping is not required. For production environments, implement a custom authentication handler that integrates with your existing authentication system. Optimizely Identity (Opti ID) authentication with per-user permission scoping will be available in a future release.
How tool authorization works
When the MCP server receives a request:
- The authentication handler validates the credentials (secret or custom token).
- The handler creates a
ClaimsPrincipalrepresenting the authenticated identity. - Each tool impersonates this identity for all CMS API calls.
- CMS enforces the standard permission model (the tool can only access content the impersonated user has permission to access).
All tools require an authorized identity. Some tools, such as content type management, require the CmsAdmins role. Other tools operate under the authenticated user's own content permissions.
Optimizely Identity authentication
NoteOptimizely Identity (Opti ID) authentication for the MCP server will be available in a future release. This will enable per-user authentication and permission scoping for production and multi-user environments. For now, use client secret authentication or a custom authentication handler.
Client secret authentication
Use WithClientSecretAuthentication() for local development and secure (non-public) environments. This method authenticates requests with a shared secret in the Authorization header.
services.AddCmsMcpServer().WithClientSecretAuthentication();endpoints.MapMcp("/mcp").RequireClientSecretAuthorization();Configure the secret in appsettings.json:
{
"Optimizely": {
"Cms": {
"Mcp": {
"Secret": "your-secret-value"
}
}
}
}Or use user secrets for local development:
dotnet user-secrets set "Optimizely:Cms:Mcp:Secret" "your-secret-value"MCP clients send the secret as the value of the Authorization header:
Authorization: your-secret-value
ImportantClient secret authentication transmits the secret in plain text. Use this method only on a trusted network, such as localhost, an internal network, or a virtual private network (VPN). Do not use client secret authentication in production environments exposed to the internet.
The client secret handler creates an identity with the CmsAdmins role, which grants full access to all CMS tools. This is suitable for development where permission scoping is not required.
Custom authentication
For scenarios where client secret authentication is not appropriate, you can implement a custom authentication handler. This is useful when you want to authenticate MCP requests with an existing authentication system such as the CMS Management API's OAuth2 flow.
A custom authentication implementation follows a three-part pattern:
- Authentication handler – Create a class that extends
AuthenticationHandler<AuthenticationSchemeOptions>and overrideHandleAuthenticateAsync(). The handler validates incoming credentials (for example, a JWT or API key) and returns aClaimsPrincipalrepresenting an authenticated identity that CMS can resolve. IMcpServerBuilderextension method – Register the authentication handler withAddScheme<>(), define an authorization policy withAddAuthorizationBuilder().AddPolicy(), and optionally register anISynchronizedApplicationsRepositoryinterceptor so the MCP application identity is visible in the CMS permission system.IEndpointConventionBuilderextension method – Apply the authorization policy to the MCP endpoint withRequireAuthorization().
Register and map using the same pattern as client secret authentication:
services.AddCmsMcpServer().WithYourCustomAuthentication();
endpoints.MapMcp("/mcp").RequireYourCustomAuthorization();The authenticated identity's CMS permissions determine which tools it can use. Some tools, such as content type management, require the CmsAdmins role. Other tools operate under the identity's own content permissions. Your authentication handler should verify the identity has the required permissions, not assign roles it does not have.
Connect an MCP client
After configuring the MCP server, connect your AI development tool by pointing it to the MCP endpoint. The configuration depends on the authentication method you chose.
Connect with client secret authentication
With client secret authentication, the MCP client sends the secret directly in the Authorization header. This works with any MCP client that supports streamable HTTP transport.
Claude Code
Add to .mcp.json or project settings:
{
"mcpServers": {
"optimizely-cms": {
"type": "http",
"url": "https://YOUR_CMS_HOST/mcp",
"headers": {
"Authorization": "your-secret-value"
}
}
}
}Cursor
Add to .cursor/mcp.json in your project root (or ~/.cursor/mcp.json for global configuration):
{
"mcpServers": {
"optimizely-cms": {
"type": "http",
"url": "https://YOUR_CMS_HOST/mcp",
"headers": {
"Authorization": "your-secret-value"
}
}
}
}Codex
Add to ~/.codex/config.toml (or .codex/config.toml in a trusted project directory):
[mcp_servers.optimizely-cms]
type = "http"
url = "https://YOUR_CMS_HOST/mcp"
[mcp_servers.optimizely-cms.headers]
Authorization = "your-secret-value"Other MCP clients
Any MCP client that supports streamable HTTP transport can connect. Configure the client with:
- Endpoint URL:
https://YOUR_CMS_HOST/mcp - Transport: Streamable HTTP (stateless)
- Authentication: The shared secret value in the
Authorizationheader
Updated about 20 hours ago