为25万+企业解锁深度研究能力:HubSpot如何利用MCP打造首个第三方CRM连接器
HubSpot已成为首个在ChatGPT中推出深度研究连接器的CRM,也是ChatGPT注册表中首个基于远程模型上下文协议(MCP)服务器构建的第三方MCP连接器。该连接器扩展了ChatGPT的能力,同时消除了用户本地安装或配置的需求。
重构MCP服务器基础设施
在此发布之前,我们曾在NPM上发布过本地MCP服务器。虽然对早期测试和反馈很有用,但该方法要求用户手动创建私有应用访问令牌并配置MCP客户端,这带来了技术复杂性,并将采用范围限制在技术娴熟的开发者群体。
我们的新远程MCP服务器彻底改变了这一局面。它通过消除用户在其机器上安装或运行任何内容的需求,代表了从本地服务器的重大飞跃。相反,用户可以通过浏览器使用OAuth等可信赖的身份验证流程来访问功能。这为超过25万家企业 democratizes 了AI访问,同时保持了企业级安全性并尊重用户级权限。
构建MCP服务器:购买还是自建
当需要构建远程MCP服务器时,我们面临着经典的工程困境,有两条清晰路径:
- 购买:使用第三方解决方案,例如Cloudflare的现成MCP解决方案
- 自建:使用HubSpot的基础设施内部开发
选项1很诱人。第三方解决方案已经解决了OAuth 2.1的复杂性,如PKCE(代码交换证明密钥)和动态客户端注册。它们的路径提供了快速上市时间,并且已经解决了MCP授权规范中更棘手的方面。对许多公司来说,这将是显而易见的选择。
然而,我们的基础设施团队已经通过在Dropwizard微服务中扩展MCP Java SDK来原型化MCP服务器。同时,我们早期的本地MCP服务器发布提供了宝贵的经验教训和反馈,帮助我们更好地理解协议的细微差别并奠定必要的基础。
因此,一旦我们考虑到托管自己的基础设施能够实现什么,自建的决定就变得清晰了。通过在HubSpot平台上构建,我们可以利用企业级CI/CD、自动扩展、可观测性,甚至基于Cloudflare Workers构建的区域感知API调用路由——所有这些生产就绪的功能都直接可用,无需任何额外设置。它还使我们能够直接控制MCP如何与现有的OAuth范围模型交互,确保在与MCP工具的任何交互中都尊重用户级权限。
奠定基础:可流式传输的HTTP MCP服务器
我们的MCP服务器使用Java MCP SDK构建。我们选择Java是为了长期可维护性和在我们标准技术栈内的开发。HubSpot的后端库和基础设施工具已经围绕Java微服务构建,因此我们专注于在标准Dropwizard服务中实现MCP。
实现MCP的可流式传输HTTP
远程MCP本质上是一个HTTP API规范,允许LLM自动发现和调用端点。目前,可流式传输HTTP定义了两种标准方法来响应远程MCP HTTP请求:
- 返回JSON响应,类似于传统的REST调用
- 使用唯一会话ID打开服务器发送事件(SSE)连接,然后将初始JSON响应作为流中的事件返回
由于各种原因,我们希望避免支持SSE传输协议。首先,我们不需要SSE连接提供的服务器到客户端通知支持,我们的用例仅关注工具调用。其次,SSE需要长连接,这对负载均衡器可靠处理具有挑战性,特别是在像我们这样服务器频繁扩展或缩减的环境中。第三,管理无状态HTTP请求远比管理会话简单。
SDK
以下是Java MCP SDK中相关接口/方法的高度简化总结:
|
|
这些接口将会话管理与传输实现分离,允许我们注入自定义响应传输,同时仍利用SDK的逻辑来处理、路由和响应MCP请求。
可流式传输HTTP传输实现
HubSpot Java HTTP API使用Dropwizard构建,因此我们实现了自定义传输提供程序来桥接Dropwizard的JAX-RS异步处理与MCP SDK。每个HTTP调用对应一个短暂的会话:
|
|
我们的自定义传输然后实现McpServerTransport来通过HTTP响应体发送MCP响应:
|
|
结果?在无状态HTTP环境中完全符合MCP协议。
服务发现 - 为MCP扩展我们的内部RPC框架
CHIRP:HubSpot的服务通信框架
在HubSpot,我们使用CHIRP(Cool Hubspot Inter-process Remote Procedures的缩写)构建了许多微服务——这是我们内部的RPC框架。CHIRP采用契约优先的方法,开发人员将微服务定义为具有强类型不可变请求/响应模型的Java接口,框架自动生成客户端和服务器代码。
动态MCP工具发现和注册
我们构建了一个MCP网关服务,自动发现和注册我们整个基础设施中的MCP工具,由工具所有者决定MCP服务器。魔法通过一个简单的注解发生——服务可以用@ChirpTool标记它们的RPC方法,表示它们应该作为MCP工具暴露:
|
|
在幕后,我们的MCP服务器定期轮询部署了这些注解的新服务或更新服务。然后系统获取它们的规范,并自动将每个RPC转换为符合MCP规范的工具体。最后,这些包装的RPC被注册到MCP SDK,准备被任何新客户端调用。
安全性:使用用户级访问令牌的OAuth
HubSpot应用:简要历史
历史上,HubSpot应用(如HubSpot深度研究连接器)是由管理员安装的账户范围集成,用于在HubSpot和第三方之间同步数据。然而,我们的OAuth 2.0系统始终支持用户特定的访问令牌。
深入MCP和用户级访问
快进到今天——UI扩展(应用卡片)和AI代理等功能已经改变了格局。因此,现在有更多现实世界用例需要尊重用户级权限。
例如,当用户从ChatGPT内部连接到HubSpot时,他们绝不能能够查询他们没有访问权限的数据。通过ChatGPT采取的操作应反映用户在HubSpot原生UI中体验的相同权限和访问控制。
MCP服务器内部的权限强制执行和范围转发
如前所述,我们的远程MCP服务器基于每个会话绑定JAX-RS端点。在中间添加一些基本代码使我们能够:
- 提取access_token的相关范围
- 获取用户的用户特定范围
- 将这些权限重放到内部API,在CRM数据中尊重用户权限
我们在应用和访问令牌中使用的范围仅包含有限的信息。相比之下,HubSpot的内部用户权限模型更加细粒度。例如,用户可能有权访问:
- 仅他们的记录
- 他们团队的记录
- 未分配的记录
- 甚至由于字段级权限而访问特定属性
未来的用户权限
AI代理连接器只是我们的产品中应尊重用户权限的一种方式。我们有多个带有应用卡片的UI扩展接触点,以及各种其他用例,第三方开发人员希望了解并尊重执行操作的用户。
为深度研究设计查询DSL
深度研究连接器集成搜索语义要求我们暴露一个消耗单个查询字段的搜索MCP工具。我们设计了一个基于令牌的DSL,平衡了功能与简单性(在OpenAI文档中也引用)。每个搜索查询由遵循key[:operator]:value模式的空间分隔令牌组成。
该语法支持从基本对象搜索(object_type:contacts)到复杂过滤器的所有内容,具有contains_token、has_property和in/not_in等多值比较的操作符。我们可以处理关联对象搜索(associated_companies:12345)、分页(limit:100 offset:20)和排序(sort:lastmodifieddate:desc)。
使其与AI模型良好配合的是其可预测的结构和清晰的示例。在实现类似工具时,我们发现,在工具描述中提供全面的示例显著提高了模型生成正确查询的能力。
以AI速度在HubSpot迭代
通过在AI开发的快速步伐中做出周到的工程决策,我们在几周内成功地将复杂协议实现为安全、客户就绪的功能。这展示了我们的团队如何在AI技术前沿解决具有挑战性的问题,同时提供真正的客户价值。