Optimizely MCP 服务器
为Optimizely CMS提供的一个模型上下文协议(MCP)服务器,使AI助手能够全面访问Optimizely的GraphQL API和内容管理API。
版本
当前版本2.0.0测试版 状态Beta版/预发布版
这是一个活跃的开发版本,并且是 尚未达到发布候选版本特性可能会有所变动,且在生产使用前需要进行额外测试。
特点/特性
核心能力
- 先发现后构建的架构对内容类型或字段不做任何硬编码假设
- 动态模式内省在运行时发现可用的内容类型和字段
- 统一内容检索通过一次调用,按URL、密钥、GUID或搜索词获取任意内容
- 视觉构建器支持全面支持带有组合结构的Optimizely Visual Builder页面
- 内容管理通过交互式向导创建和管理内容
- 智能田地测绘基于模式的字段匹配与置信度评分
- GraphQL与CMA集成直接访问图形API(读取)和内容管理API(写入)
- 智能缓存内置缓存以提高性能
- 类型安全全面支持TypeScript,具备运行时验证功能
API 支持
- 图API(或 图形应用程序编程接口)快速内容检索、搜索和发现
- 内容管理API内容创作、更新及草稿访问
- 双重认证支持Graph(单密钥、HMAC)和CMA(OAuth2)两种认证方式
安装
# 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配置
创建一个 .env 项目根目录下的文件:
# 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运行服务器
开发模式
# Run with hot reloading
npm run dev
# Run with debug logging
LOG_LEVEL=debug npm run dev生产模式
# Build and run
npm run build
npm start
# Or run directly
node dist/index.js测试服务器
# Run all unit tests
npm test
# Run tests with coverage
npm run test:coverage
# Type checking
npm run typecheck
# Linting
npm run lintMCP服务器的工作原理
MCP服务器通过通信进行交互 stdio(标准输入输出库) (标准输入/输出),而非HTTP端口:
- 无需端口 - 服务器没有监听任何网络端口
- 基于过程的 - Claude Desktop 将您的服务器作为子进程启动
- JSON-RPC 消息 - 通过stdin/stdout管道进行通信
- 安全的 - 无网络暴露,仅在Claude需要时运行
MCP 客户端配置
Claude 桌面版设置
步骤1:找到你的配置文件
在文本编辑器中打开配置文件:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS(发音:/ˈmækɒs/ 或 /ˈmækəs/):
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
对于Windows系统,你可以快速打开它的方式是:
notepad %APPDATA%\Claude\claude_desktop_config.json步骤2:添加服务器配置
{
"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": ""
}
}
}
}在Windows系统中使用JSON时,必须使用双反斜杠(\\\\)。如果您的文件夹路径中包含空格,这仍然有效,因为每个参数都是一个独立的JSON字符串。
- Windows:%USERPROFILE% 会扩展为您主目录的路径(例如,C:\\Users\\Alice)。如果 Claude 无法自动扩展它,请将其替换为您的实际路径(例如,C:\\Users\\Alice\\path\\to\\optimizely-mcp-server\\dist\\index.js)。在 PowerShell 中,等效的表示是 $env:USERPROFILE,但在此 JSON 配置文件中,您应保留 %USERPROFILE% 或使用完整路径。
- macOS/Linux:等效的快捷方式是 ~ 或 $HOME(例如,/Users/alice 或 /home/alice)。如果 ~/$HOME 无法正确展开,请用完整路径替换。
步骤3:重启Claude桌面版
保存配置文件后:
- 完全退出 Claude Desktop(不仅仅是关闭窗口)
- 再次启动Claude桌面版
- 现在应该可以使用 Optimizely 工具了
步骤4:验证其是否正常工作
在新的Claude对话中,尝试:
- “你能列出可用的Optimizely工具吗?”
- “使用健康检查工具测试连接”
故障排除
如果服务器未加载:
- 检查文件路径是否正确,并使用适当的转义字符(
\\(适用于Windows) - 确保你已经构建了项目(
npm run build) - 验证
dist/index.js文件已存在 - 检查Claude的日志以查找错误
其他MCP客户端
对于其他兼容MCP的客户端,请使用stdio传输配置:
{
"name": "optimizely",
"transport": {
"type": "stdio",
"command": "node",
"args": ["/path/to/optimizely-mcp-server/dist/index.js"]
},
"env": {
// Environment variables as above
}
}可用工具(共14个)
🌟 核心发现与检索工具
这些工具使用图API来动态发现您的CMS结构并检索内容,而无需硬编码假设。
help- 🚀 从这里开始!获取上下文感知帮助,并学习以发现为主的工作流程
- 示例: help({}), help({"topic": "workflow"})
get- 🎯 统一工具 - 一次调用即可通过任意标识符获取内容
- 替换旧的 search → locate → retrieve 工作流程 - 自动发现字段并返回完整内容 - ✅ 支持带有完整组合结构的Visual Builder页面 - 示例: get({"identifier": "/"}), get({"identifier": "Article 4"})
discover- 动态查找内容类型和字段
- 不要对您的CMS结构做硬编码假设 - 示例: discover({"target": "types"}), discover({"target": "fields", "contentType": "ArticlePage"})
analyze- 对内容类型需求的深入分析
- 理解字段、约束和默认值 - 示例: analyze({"contentType": "ArticlePage"})
search- 智能内容搜索与自动发现
- ⚠️ 注意: get 对于大多数使用场景来说,通常效果更好 - 示例: search({"query": "mcp", "contentTypes": ["ArticlePage"]})
locate- 通过ID、关键字或路径查找特定内容
- ⚠️ 注意: get 对于大多数使用场景来说,通常效果更好 - 示例: locate({"identifier": "/news/article-1"})
retrieve从内容管理API获取完整内容
- ⚠️ 注意: get 通常更好(使用更快的Graph API) - 仅在……时使用 get 建议使用它,或者您需要CMA特定的数据 - 示例: retrieve({"identifier": "12345"})
🔧 实用工具(3)
health-check检查API连接和服务器健康状况get-config- 获取当前服务器配置(已清理)get-documentation- 按类别获取可用工具的文档
🔧 内容管理工具(CMA API)
这些工具使用内容管理API进行写入操作和详细内容访问:
content_creation_wizard- 与发现相结合的互动内容创作
- 创作新内容所必需 - 示例: content_creation_wizard({"step": "start"})
content-test-api- 测试CMA连接性和终端节点
- 验证身份和权限 - 示例: content-test-api({})
注:该 retrieve 上述核心工具中的工具也使用CMA来访问草稿内容和版本历史。
⚠️ 已弃用工具(即将移除)
这些Graph API发现工具是新工具的重复 discover 该工具将在未来版本中移除:
graph-introspection- 使用discover相反type-discover- 使用discover({"target": "types"})相反type-match- 使用discover相反content_type_analyzer- 使用analyze相反graph_discover_types- 使用discover({"target": "types"})相反graph_discover_fields- 使用discover({"target": "fields"})相反graph-query- 使用get或者search相反
关键架构原则
“Discovery-First Design”可以翻译为“以探索为先的设计”或“探索优先的设计”。这里,“Discovery”指的是探索、发现的过程或理念,“First Design”则强调了设计的首要性或优先性。因此,整个短语可以理解为一种以探索和发现为核心或首要考量的设计方法或理念
与传统的集成方式(其中内容类型和字段名称是硬编码的)不同,此MCP服务器:
- 永远不要硬编码内容类型 - 不对“ArticlePage”(文章页面)、“StandardPage”(标准页面)等做任何假设。
- 不要硬编码字段映射 - 没有预定义的路径,如“SeoSettings.MetaTitle”
- 动态发现所有内容 - 使用内省来理解您的内容管理系统(CMS)
- 适应任何CMS配置 - 支持自定义内容类型和字段
智能场地测绘
服务器使用模式匹配和相似度评分来:
- 将用户友好的字段名称映射到实际的CMS字段
- 自动处理嵌套属性
- 根据字段类型生成适当的默认值
- 为映射提供置信度评分
推荐的工作流程
简单内容检索(最常见)
1. get({"identifier": "homepage"}) # That's it! One call gets everything.这个(或“该”) get 工具自动地:
- 检测标识符类型(搜索词、URL、密钥或GUID)
- 查找内容
- 发现所有可用字段
- 返回完整内容,包括Visual Builder组件
高级发现工作流程
1. help({}) # Learn the workflow
2. discover({"target": "types"}) # Find content types
3. discover({"target": "fields", "contentType": "..."}) # Get fields
4. get({"identifier": "..."}) # Retrieve content内容创作工作流程
1. discover({"target": "types"}) # Find available types
2. analyze({"contentType": "ArticlePage"}) # Understand requirements
3. content_creation_wizard({...}) # Create with guidanceVisual Builder 支持
这个(或“该”) get 该工具完全支持Optimizely Visual Builder(原名Visual Experience Composer)页面:
特点/功能
- ✅ 自动检测 - 通过界面识别Visual Builder页面(
_IExperience) - ✅ 完整作品检索 - 单次调用返回完整结构
- ✅ 嵌套结构 - 处理网格、行、列和组件
- ✅ 组件内容 - 在组合中直接包含内联组件数据
- ✅ 递归深度 - 支持任意级别的嵌套
理解组件类型
Visual Builder 组件有两种类型:
1. 内联组件(嵌入式内容)
- 密钥:
null或者不存在 - 内容位置直接存储在组成结构中
- 访问内容已包含在
get回应 - 示例包含“欢迎访问我们的网站”等内容的文本组件
{
"component": {
"_metadata": {
"types": ["Text", "_Component"],
"key": null // ← NULL = inline
},
"Content": "Welcome Text" // ← Content is here
}
}重要的不要尝试单独提取内联组件 - 内容已经提供!
2. 引用组件(独立内容项)
- 关键有效的全局唯一标识符(GUID)(例如,“f7e7f5c9-1e77-4884-a8fc-a9c9ae56560c”)
- 内容位置在内容管理系统(CMS)中以独立的内容项形式存储
- 访问使用
get({"identifier": "component-key"})以检索完整详情 - 示例共享组件,如站点设置、可重用模块
{
"component": {
"_metadata": {
"types": ["ArticleList", "_Component"],
"key": "f7e7f5c91e774884a8fca9c9ae56560c" // ← Has key
}
// May include basic fields, use get() for full content
}
}最佳实践
在使用 Visual Builder 页面时:
- 首先,用(某种方式)检索页面
get({"identifier": "/"}) - 检查 组件的构成结构
- 对于内联组件 (空键): 内容已在响应中 ✅
- 对于引用的组件 (有密钥):使用
get({"identifier": "key"})获取完整详情
示例用法
// 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
}
}
}
]
}
]
}
}
}已知的限制
- 演出 - 由于嵌套结构,大型组合可能需要更长时间来检索
- 引用组件详细信息 - 仅包含基本元数据;完整内容需单独获取
get()打电话 - 显示设置 - 未包含在当前实现中(如有需要可添加)
重要注意事项
内容索引延迟
使用(工具/方法)创建新内容后 content_creation_wizard 或其他创作工具:
- 在CMA(可能指某个公司、机构或系统的缩写)中立即可用内容可立即通过
retrieve工具 - 图API索引延迟内容可能需要1-5分钟才会出现在Graph API结果中
- 工具行为这个(或:该)
get并且search工具使用Graph API,并且在索引完成之前,对于新创建的内容将返回“未找到”
最佳实践创建内容后,请等待几分钟再尝试使用 get 或者 search或者,使用 retrieve 一种直接查询CMA且无索引延迟的工具。
草稿与已发布内容
- Graph API(图应用程序编程接口)仅返回已发布的内容
- CMA API返回草稿和已发布的内容
- 新内容默认情况下以草稿状态创建
- 为了使内容可通过(某种方式)进行搜索
get/search它必须先被发表
发展
项目结构
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添加新工具
- 创建工具实现
src/logic/ - 在适当的部分添加工具注册
- 如果需要,请添加 TypeScript 类型
- 编写测试用例
tests/ - 更新文档
测试指南
- 所有工具实现的单元测试
- API客户端的集成测试
- 模拟外部API调用
- 测试错误场景
- 保持覆盖率>80%
测试与调试
单元测试
使用 Vitest 运行自动化测试:
# Run unit tests
npm test
# Run with coverage report
npm run test:coverage单元测试位于 /tests/ 以及封面:
- GraphQL 客户端功能
- CMA客户端操作
- 健康检查功能
集成测试与调试
使用这些 npm 脚本测试您的设置:
# 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故障排除
常见问题
- 认证错误
- 验证您的API凭据在 .env - 对于CMA:在您的Optimizely CMS实例中,进入“设置”>“API密钥”以创建API密钥 - 检查CMA的令牌是否过期(令牌在5分钟后过期) - 确保为Graph使用正确的认证方法
- 连接问题
- 验证网络连接 - 检查防火墙设置 - 确认API端点可访问
- 构建错误
- 跑 npm install 确保依赖关系 - 检查 Node.js 版本(需 >=18) - 清晰 dist/ 并重建
- 403 禁止访问错误(内容创建)
- 这通常意味着权限不足 - 请参阅下文的“模拟”部分以获取解决方案 - 验证用户是否具有内容创作权限 - 检查目标容器是否允许该内容类型
调试模式
启用调试日志以进行故障排除:
LOG_LEVEL=debug npm start健康检查
测试服务器连接性:
# Using the built tool
echo '{"method": "tools/call", "params": {"name": "health_check"}}' | node dist/index.js用户伪装(或用户冒充)
如果你在创建内容时遇到403禁止访问错误,你可以使用 用户伪装(或用户冒充) 以具有必要权限的特定用户身份执行API调用。
何时使用模拟身份
在以下情况下使用身份冒充:
- API客户端缺少内容创建权限
- 你需要用不同的用户权限级别进行测试
- 您希望将操作归因于特定用户
安装说明
- 在 Optimizely CMS 中启用模拟身份功能:
- 以管理员身份登录 Optimizely CMS - 导航至 设置 > API 客户端 - 找到您的API客户端 - 启用 “允许模拟身份” 选项 - 保存更改
- 配置MCP服务器:
# In your .env file
CMA_IMPERSONATE_USER=user@example.com- 更新Claude桌面配置 (如果使用环境变量):
{
"mcpServers": {
"optimizely": {
"env": {
"CMA_IMPERSONATE_USER": "user@example.com",
// ... other settings
}
}
}
}它是如何工作的
当配置了身份冒充时:
- 认证请求使用JSON格式,并且
act_as田野;领域;现场 - 所有内容操作均以模拟用户的身份执行
- 创建的内容显示冒充的用户为作者
测试身份冒充
测试模拟身份是否有效:
# Run the impersonation test script
node scripts/test-impersonation-final.js这将生成测试内容并显示创建该内容的用户。
安全最佳实践
- 仅在必要时启用模拟身份功能
- 使用具有最小必要权限的帐户
- 定期审查API客户端权限
- 监控API使用日志,以检测异常活动
做出贡献
- 为仓库创建分支(或:克隆仓库)
- 创建一个特性分支
- 进行你的更改
- 添加测试
- 跑
npm test并且npm run typecheck - 提交一个拉取请求
许可证
麻省理工学院(MIT)
