HubSpot CMS MCP服务器
一个生产就绪的模型上下文协议(MCP)服务器,使Claude能够安全地管理HubSpot CMS内容。专为Core Wrk的健康行业咨询内容而设计,特别强调安全机制和初稿工作流程。
特性
- 安全草稿优先工作流程:所有内容修改都进入草稿状态,需要明确发布
- 获取第一个模式:强制模式,在更新之前获取当前状态,以防止数据丢失
- 速率限制:代币桶实现尊重HubSpot的爆发和每日限制
- 全面的错误处理:带有HubSpot相关ID的用户友好错误消息
- 审计跟踪:完整记录所有操作及其前后状态
- 回滚能力:存储所有修改的先前状态
先决条件
- Node.js 18.0.0或更高版本
- HubSpot私有应用访问令牌,具有适当的作用域
- 具有CMS Hub访问权限的HubSpot帐户
安装
npm install
npm run build配置
所需的环境变量
HUBSPOT_ACCESS_TOKEN:您的HubSpot私人应用访问令牌(必填)
可选环境变量
HUBSPOT_RATE_LIMIT_SAFETY_MARGIN:保留作为安全缓冲的速率限制百分比(默认值:0.1= 10%)HUBSPOT_LOG_LEVEL:记录详细程度(默认值:info,选项:debug,info,warn,error)
设置HubSpot私人应用程序
- 登录您的HubSpot帐户
- 导航到“设置”→ 集成→ 私人应用程序
- 点击“创建私人应用”
- 使用所需范围配置应用程序:
- content (读写) - oauth (用于令牌验证)
- 复制访问令牌并将其设置为
HUBSPOT_ACCESS_TOKEN
安全最佳实践:切勿将访问令牌提交到版本控制。使用环境变量或安全密钥管理器。
用法
运行服务器
# Development mode
npm run dev
# Production mode
npm run build
npm start使用Claude Desktop进行配置
添加到您的Claude Desktop配置文件(claude_desktop_config.json):
{
"mcpServers": {
"hubspot-cms": {
"command": "node",
"args": ["/path/to/hubspot-cms-mcp-server/dist/index.js"],
"env": {
"HUBSPOT_ACCESS_TOKEN": "your-token-here"
}
}
}
}第一阶段工具(MVP)
1.hubspot_authenticate
验证HubSpot连接并检查可用权限。
目的:第一个用于确保令牌有效并具有适当范围的工具。
输入:无
输出:
- 集线器ID和域
- 用户信息
- 可用范围
- 费率限制状态
示例:
{
"success": true,
"connection": {
"hubId": 12345678,
"hubDomain": "example.com",
"userId": 98765,
"userName": "user@example.com",
"scopes": ["content", "oauth"]
},
"rateLimitStatus": {
"dailyRemaining": 499950,
"dailyPercentUsed": "0.01%"
}
}2.hubspot_list_blog_posts
使用灵活的过滤选项发现和列出博客文章。
目的:查找用于分析、系列管理或发现的博客文章。
输入:
limit(数字,可选):返回的最大结果(最大100,默认20)offset(数字,可选):分页偏移量(默认值0)state(字符串,可选):按草稿、已发布或已安排进行筛选authorName(字符串,可选):按作者筛选(部分匹配)name(字符串,可选):按帖子标题筛选(部分匹配)created(字符串,可选):过滤日期后创建的帖子(ISO 8601)updated(字符串,可选):过滤日期后更新的帖子(ISO 8601)archivedInDashboard(布尔值,可选):按存档状态筛选
输出:
- 总计数和分页结果
- 发布包含关键元数据的摘要
- 费率限制状态
示例:
{
"success": true,
"total": 45,
"count": 20,
"posts": [
{
"id": "123456789",
"name": "Understanding Wellness Practice Billing",
"slug": "wellness-practice-billing",
"state": "PUBLISHED",
"authorName": "Jane Doe",
"publishDate": "2024-01-15T10:00:00Z",
"url": "https://example.com/blog/wellness-practice-billing"
}
]
}3.hubspot_get_blog_post
获取特定博客文章的完整详细信息。
目的:必须在任何更新操作之前调用(fetch first模式)。返回完整的post对象。
输入:
postId(string,必填):博客帖子ID
输出:
- 完整的博客文章对象包括:
- 内容(postBody) - 所有元数据 - 标签,特色图片 - 小部件和布局部分 - 出版状态
示例:
{
"success": true,
"post": {
"id": "123456789",
"name": "Understanding Wellness Practice Billing",
"slug": "wellness-practice-billing",
"state": "PUBLISHED",
"postBody": "...",
"metaDescription": "Learn about billing best practices...",
"featuredImage": "https://...",
"tagIds": [1, 2, 3]
}
}4.hubspot_update_blog_post_metadata
安全地更新博客帖子元数据,而不涉及帖子内容。
目的:安全更新SEO元数据、特色图片、标题、蛞蝓、作者和标签。从不修改postBody。
安全保证:
- 自动实现fetch first模式
- 永远不要触摸postBody、小部件或布局结构
- 所有更改都进入草稿状态
- 需要明确发布
输入:
postId(string,必填):博客帖子IDname(字符串,可选):帖子标题slug(字符串,可选):URL段符metaDescription(字符串,可选):SEO的元描述htmlTitle(字符串,可选):HTML标题标签featuredImage(字符串,可选):特色图片URLfeaturedImageAltText(字符串,可选):特色图像alt文本blogAuthorId(字符串,可选):作者IDauthorName(字符串,可选):作者姓名tagIds(数字数组,可选):标签ID
输出:
- 更新的草稿帖子详细信息
- 用于查看更改的预览URL
- 已更新的字段
- 费率限制状态
示例:
{
"success": true,
"contentId": "123456789",
"previewUrl": "https://example.com/blog/post?preview_key=draft",
"updatedFields": ["metaDescription", "htmlTitle"],
"message": "✓ Draft updated successfully. Changes saved to draft (not yet published)."
}5.hubspot_publish_blog_post_draft
明确发布博客文章草稿以使其生效。
目的:使草案更改对公众可见。可以立即发布或安排未来发布。
⚠️ 警告:这使得内容公开可见。无法自动撤消。
输入:
postId(string,必填):博客文章草稿IDpublishDate(字符串,可选):计划发布的ISO 8601日期(立即省略)
输出:
- 已发布的帖子详细信息
- 实时URL
- 发布时间戳
- 费率限制状态
示例:
{
"success": true,
"contentId": "123456789",
"liveUrl": "https://example.com/blog/wellness-practice-billing",
"message": "✓ Blog post published successfully!"
}Core Wrk特定用例
博客系列管理
创建、标记和发布关于健康实践计费和运营的教育内容系列:
1. List existing posts in series: hubspot_list_blog_posts with name filter
2. Create metadata consistency across series using hubspot_update_blog_post_metadata
3. Apply consistent tags to series posts
4. Publish series posts in sequence主页优化
优化元数据和SEO元素:
1. Get current homepage post: hubspot_get_blog_post
2. Update meta description and title: hubspot_update_blog_post_metadata
3. Review draft preview
4. Publish when ready: hubspot_publish_blog_post_draft内容发现和分析
查找并分析现有内容:
1. List all published posts: hubspot_list_blog_posts with state=PUBLISHED
2. Review individual posts for SEO optimization opportunities
3. Update metadata to improve search visibility安全机制
初稿工作流程
所有内容修改都以草稿端点为目标(/draft 后缀),从不直接直播内容。发布需要通过以下方式采取明确行动 hubspot_publish_blog_post_draft.
获取第一个模式
这 hubspot_update_blog_post_metadata 工具自动:
- 获取当前帖子状态
- 合并元数据更改
- 验证嵌套结构是否保留
- 将完整对象粘贴到
/draft端点
这可以防止可能损坏嵌套对象(小部件、layoutSections)的部分更新。
速率限制
令牌桶实现:
- 突发限制:每10秒100-250个请求
- 涨停:可配置(专业级别通常为500000)
- 安全裕度:10%保留缓冲区(可配置)
- 指数退避:429个错误出现抖动时自动重试
错误处理
所有错误包括:
- 用户友好的消息(非技术术语)
- 用于调试的HubSpot关联ID
- 可采取的解决步骤
- 费率限制状态
示例错误:
{
"success": false,
"error": {
"status": "FORBIDDEN",
"message": "Permission denied. Your access token may be missing required scopes. Original error: Missing scope: content",
"correlationId": "abc-123-def"
}
}审计跟踪
所有操作都记录在:
- 时间戳
- 操作ID
- 在国家之前
- 州之后
- 进行更改的用户/工具
日志以JSON格式写入stderr,以便于解析。
API约束
分页
列表操作每页最多100个结果。使用 offset 分页参数。
部分更新
HubSpot不支持嵌套属性的部分更新。此服务器通过以下方式处理此问题:
- 始终先获取完整对象
- 合并更改
- 在PATCH请求中发送完整对象
筛选语法
博客帖子过滤器使用双下划线语法:
name__icontains=keyword-不区分大小写包含created__gt=2024-01-01-大于日期
草稿与已发布
state:请求中对象的状态currentState:内容的实际当前状态- 草案修改使用
/draft后缀 - 出版用途
/draft/push-live端点
故障排除
认证失败
错误:“身份验证失败。请检查您的HUBSPOT_ACCESS_TOKEN”
决心:
- 验证令牌是否正确且未过期
- 检查令牌是否具有所需的作用域(内容、oauth)
- 确保私人应用程序未被删除或禁用
权限不足
错误:“权限被拒绝。您的访问令牌可能缺少所需的作用域”
决心:
- 在HubSpot设置中检查私人应用范围
- 添加缺失的范围(通常
content) - 在范围更改后生成新的访问令牌
超出费率限制
错误:“已超出速率限制。请稍候,然后再发出更多请求”
决心:
- 等待速率限制窗口重置
- 降低请求频率
- 增加
HUBSPOT_RATE_LIMIT_SAFETY_MARGIN更加保守
资源未找到
错误:“找不到资源。请求的内容可能已被删除”
决心:
- 验证帖子ID是否正确
- 检查HubSpot中的帖子是否已删除
- 使用
hubspot_list_blog_posts找到正确的ID
发展
项目结构
src/
├── index.ts # Main MCP server implementation
├── hubspot-client.ts # HubSpot API client with error handling
├── rate-limiter.ts # Token bucket rate limiter
├── logger.ts # Audit trail logging
└── types.ts # TypeScript type definitions建筑
npm run build将TypeScript编译为JavaScript dist/ 目录。
观察变化
npm run watch文件更改时自动重新编译。
日志记录
集 HUBSPOT_LOG_LEVEL=debug 用于详细的请求/响应日志记录。
许可证
麻省理工学院
支持
有关问题或疑问,请联系Core Wrk技术团队或在存储库中提交问题。
第5阶段工具(安全网页内容编辑)
1.hubspot_get_page_widgets
发现页面上的所有小部件及其位置和内容预览。
目的:小部件编辑前的基本第一步-提供完整的页面结构清单。
输入:
pageId(字符串,必填):页面IDpageType(字符串,必填):“网站页面”或“登录页面”
输出:
- 完整的页面小部件结构
- 小部件位置(节、行、列、小部件索引)
- 每个小部件的内容预览
- 小部件类型和功能
安全:只读操作,随时拨打安全电话。
示例:
{
"success": true,
"pageId": "123456",
"pageName": "Homepage",
"totalWidgets": 8,
"layoutSections": ["dnd_area", "header"],
"widgets": [
{
"id": "widget-1",
"name": "Hero Section",
"type": "rich_text",
"location": {
"sectionName": "dnd_area",
"rowIndex": 0,
"columnIndex": 0,
"widgetIndex": 0
},
"hasHtmlContent": true,
"hasStyles": true,
"hasParams": false,
"contentPreview": "Welcome to our website..."
}
]
}2.hubspot_update_widget_content
安全地更新特定小部件的HTML内容、样式或参数。
目的:在不接触其他页面元素的情况下修改单个小部件的内容或外观。
安全保证:
- 自动实现fetch first模式
- 结构验证确保没有小部件丢失
- 仅修改目标小部件
- 所有更改都进入草稿状态
- 返回验证报告
输入:
pageId(字符串,必填):页面IDpageType(字符串,必填):“网站页面”或“登录页面”sectionName(字符串,必填):布局节名称rowIndex(数字,必填):行索引(从0开始)columnIndex(数字,必填):列索引(从0开始)widgetIndex(数字,必填):小部件索引(从0开始)html(字符串,可选):新建HTML内容styles(对象,可选):要应用的CSS样式params(对象,可选):要更新的模块参数
输出:
- 更新页面详细信息
- 结构验证报告
- 预览URL
- 小部件计数之前/之后
示例:
{
"success": true,
"pageId": "123456",
"previewUrl": "https://example.com/page?hs_preview=draft",
"validation": {
"isValid": true,
"widgetCountBefore": 8,
"widgetCountAfter": 8,
"warnings": [],
"errors": []
},
"message": "✓ Widget updated successfully. Structure validation: PASSED."
}3.hubspot_add_widget_to_page
将新小部件添加到页面上的特定位置。
目的:以编程方式向页面添加新的内容部分、图像、按钮等。
安全保证:
- 通过验证获取第一个模式
- 验证小部件计数是否增加了1
- 所有更改都进入草稿状态
- 返回新的小部件位置
输入:
pageId(字符串,必填):页面IDpageType(字符串,必填):“网站页面”或“登录页面”sectionName(字符串,必填):布局节名称rowIndex(数字,必填):行索引(从0开始)columnIndex(数字,必填):列索引(从0开始)widgetType(字符串,必填):小部件类型(例如,“rich_text”、“image”、“button”)widgetName(字符串,必填):小部件的显示名称html(字符串,可选):初始HTML内容params(对象,可选):模块参数styles(对象,可选):CSS样式
输出:
- 新小部件位置
- 验证报告
- 之前/之后的小部件计数
示例:
{
"success": true,
"pageId": "123456",
"widgetLocation": {
"sectionName": "dnd_area",
"rowIndex": 1,
"columnIndex": 0,
"widgetIndex": 2
},
"validation": {
"widgetCountBefore": 8,
"widgetCountAfter": 9
},
"message": "✓ Widget added successfully..."
}4.hubspot_remove_widget_from_page
从页面中删除特定的小部件。
目的:清理不需要的内容部分。
⚠️ 警告:这将从草稿中永久删除小部件(不会立即生效)。
安全保证:
- 通过验证获取第一个模式
- 验证小部件计数减少了1
- 更改转到需要发布的草稿
- 保留所有其他小部件
输入:
pageId(字符串,必填):页面IDpageType(字符串,必填):“网站页面”或“登录页面”sectionName(字符串,必填):布局节名称rowIndex(数字,必填):行索引(从0开始)columnIndex(数字,必填):列索引(从0开始)widgetIndex(数字,必填):小部件索引(从0开始)
输出:
- 验证报告
- 之前/之后的小部件计数
示例:
{
"success": true,
"pageId": "123456",
"validation": {
"isValid": true,
"widgetCountBefore": 9,
"widgetCountAfter": 8
},
"message": "✓ Widget removed successfully..."
}第5阶段工作流程示例
更新英雄部分文本
1. Get page widget structure: hubspot_get_page_widgets
2. Identify hero widget location from results
3. Update widget HTML: hubspot_update_widget_content with new HTML
4. Review preview URL
5. Publish when ready: hubspot_publish_blog_post_draft (works for pages too)添加行动呼吁按钮
1. Get page structure to find where to add: hubspot_get_page_widgets
2. Add button widget: hubspot_add_widget_to_page with widgetType="button"
3. Update button HTML and styles if needed: hubspot_update_widget_content
4. Review and publish更改小部件样式
1. Get page structure: hubspot_get_page_widgets
2. Update widget styles: hubspot_update_widget_content with styles object
Example styles: {"backgroundColor": "#003366", "padding": "20px"}
3. Preview changes
4. Publish安全功能(第5阶段)
结构验证
每个小部件操作都包括自动验证:
- 小部件计数跟踪:确保小部件不会被意外删除
- 截面完整性:验证是否保留了所有布局部分
- 比较之前/之后:关于变化的详细报告
- 预警系统:有关意外更改的警报
- 错误预防:如果结构受损,操作将安全失败
获取第一个模式
所有第5阶段操作均自动执行:
- 获取完整的当前页面状态
- 对特定小部件进行有针对性的修改
- 验证完整结构是否完好
- 将完整页面对象粘贴到/草稿端点
- 退货验证报告
这可以防止部分更新可能导致的灾难性数据丢失。
初稿工作流程
- 所有小部件修改都以草稿端点为目标
- 直播内容永远不会被直接修改
- 预览为所有更改生成的URL
- 需要显式发布才能上线
- 可以放弃更改并重置草稿
基于位置的寻址
Phase 5使用的不是处理原始JSON,而是:
- 段名:例如,“dnd_area”
- 行索引:本节中的哪一行
- 列索引:行中的哪一列
- 小部件索引:列中的哪个小部件
这使得操作更直观,更不容易出错。
路线图
第一阶段(完成):带有元数据更新的博客帖子管理
第2阶段(完成):内容创建和文件管理
第3阶段(完成):页面管理和高级功能
阶段4:保留用于未来的增强功能(模板、模块、主题)
第5阶段(当前):安全的网页内容和外观编辑
