Optimizely CMS MCP Server

An MCP server that exposes the Optimizely CMS Content Management API to Claude and any other MCP client over Streamable HTTP — deployed as a single Cloudflare Worker.

I work with Optimizely CMS daily, and I wanted my AI tooling to perform real editorial operations — create content, update properties, publish — instead of just talking about them. MCP is the bridge: this server translates the Model Context Protocol into Optimizely's Content Management REST API.

It runs as one stateless Cloudflare Worker; the fiddly part is Optimizely's OAuth client-credentials flow with five-minute tokens, which the server caches and refreshes so the agent never has to know it exists.

View the source on GitHub · Related: Paperboy — the same idea taken further, a CMS built agent-native from the start · Azure DevOps MCP Server

OeGhbasJN626rFhtOi-gkYd-.jpg

Why This Project

Optimizely uses OAuth 2.0 client_credentials for authentication, which requires:

  1. POST to /oauth/token with clientid + clientsecret → short-lived JWT bearer

  2. Cache it (tokens expire in ~5 minutes)

  3. Refresh on 401

This server runs the OAuth dance once on every cold start (or when a 401 invalidates the cache) and ferries plain bearers to Optimizely.

Endpoint

Deployed at: https://optimizely-mcp.hans-christian-thjomoe.workers.dev/mcp

POST https://optimizely-mcp.hans-christian-thjomoe.workers.dev/mcp

JSON-RPC 2.0 over HTTP POST. Clients that send Accept: text/event-stream get the response as a single SSE message frame (Streamable HTTP).

Authentication

Send your Optimizely API clientid and clientsecret as HTTP Basic auth:

Authorization: Basic <base64(client_id:client_secret)>

The server handles the OAuth client_credentials exchange to https://api.cms.optimizely.com/oauth/token and caches the resulting JWT.

Tools Available

  • Content — listcontentitems, getcontent, getcontentpath, createcontent, copycontent, updatecontent, deletecontent, undeletecontent

  • Versions — listversions, getversion, createversion, updateversion, deleteversion, deletelocale

  • Status transitions — markversionready, publishversion, draftversion, approveversion, rejectversion

  • Content types — listcontenttypes, getcontenttype, createcontenttype, updatecontenttype, deletecontenttype

  • Applications — discovercontentroots, listapplications, getapplication, createapplication, updateapplication, delete_application

  • Property groups — listpropertygroups, getpropertygroup, createpropertygroup, updatepropertygroup, deletepropertygroup

  • Blueprints — listblueprints, getblueprint, createblueprint, updateblueprint, delete_blueprint

  • Discovery — listlocales, listdisplaytemplates, walkcontent_tree

  • Bulk operations — purgecontentsubtree, purgecustomcontent_types