Skip to main content
Glama
Aa-ronJS

Doorknock

by Aa-ronJS

Doorknock

一个远程 MCP 服务器,它从公司自己的域名研究该公司,根据你提供的潜在客户画像进行判断,并将结果写入 HubSpot。

它报告的所有内容都是实时从公司自己的网站或其公共 DNS 记录中读取的,并带有产生这些内容的 URL 或 DNS 查询。它不向数据提供商购买任何东西,也不推断收入、员工人数或所有权。

在线:https://doorknock-eight.vercel.app MCP 端点:https://doorknock-eight.vercel.app/mcp OpenAPI:https://doorknock-eight.vercel.app/openapi.json 健康检查:https://doorknock-eight.vercel.app/health

连接它

claude mcp add --transport http doorknock https://doorknock-eight.vercel.app/mcp

任何支持 Streamable HTTP 的 MCP 客户端都可以使用相同的 URL。它仅支持 POST:服务器是无状态的,因此 GET 和 DELETE 按设计返回 405。

研究工具完全不需要凭据。HubSpot 工具需要一个私有应用令牌,具有 crm.objects.companies.read 和 .write 权限,作为请求头提供:

claude mcp add --transport http doorknock https://doorknock-eight.vercel.app/mcp \
  --header "X-HubSpot-Token: pat-na1-..."

对于不支持 MCP 的任何东西,相同的操作位于 /v1/<operation>,并由 /openapi.json 描述,该文件由路由器使用的相同常量生成,因此两者不会出现偏差。这就是自定义 GPT Action 或 n8n HTTP 节点应该指向的地方。

Related MCP server: HubSpot Extended MCP Server

七个工具

工具

功能

research_company

读取首页和 DNS。返回页面上加载的营销和 CRM 工具、存在哪些标准页面、谁处理他们的电子邮件,以及他们的外发电子邮件是否受到保护。

qualify_lead

运行研究,然后根据你传入的画像进行评分,返回一个等级,并附上每条规则的推理。

check_email_posture

MX、SPF 和 DMARC,用通俗的语言读取。将“我的邮件能否送达他们”和“他们的邮件能否送达”分开,因为它们是不同的问题。

list_signals

画像规则所依据的词汇表:每个命名的事实、其含义,以及其缺失能证明什么和不能证明什么。

hubspot_check_connection

确认令牌有效,并报告门户和范围,避免写入在最糟糕的时刻失败。

hubspot_find_company

按确切域名查找公司,以便丰富操作不会创建重复项。

hubspot_write_company

创建或更新公司,并可选地添加时间线备注。

三个值得争论的决定

凭据永远不会触及模型。 显而易见的设计是在 HubSpot 工具上使用 token 参数。这会把秘密放在提示词中、上下文窗口中、客户端的记录中以及任何记录工具调用的日志中,并且使令牌成为模型可能被说服发送到其他地方的东西。在这里,它改为通过 HTTP 请求传输,放在 X-HubSpot-Token 请求头中,并且没有工具模式为其提供字段。模型可以请求写入;它永远不会处理凭据。对抗性检查之一的存在纯粹是为了断言没有任何工具模式曾经增加过凭据字段。

规则是数据,不是代码。 资格规则随调用一起到达,并随答案一起返回,因此产生裁决的逻辑始终可见,并且改变谁算作好的潜在客户永远不需要部署。命名不存在的信号的规则会被报告为未知信号,而不是被静默计为未命中,而无法确定其信号的规则会阻止该等级,而不是使其失败,因为“我们无法判断”和“否”会将潜在客户发送到不同的地方。

缺失被报告为缺失。 标签可以通过标签管理器加载、位于同意横幅后面,或者只存在于内部页面上。因此,答案会说“在首页上未检测到”,而不是“他们不使用 HubSpot”,并且每个信号都附带一句关于其缺失不能证明什么的话。

本地运行

npm install
npm run typecheck     # tsc, no emit
npm run smoke         # every operation against the real internet
npm run smoke:mcp     # every endpoint over a real node:http server
npm run smoke:live -- https://doorknock-eight.vercel.app    # the deployment, via the official client SDK
npm run adversarial -- https://doorknock-eight.vercel.app   # tries to break it
npm run prove -- https://doorknock-eight.vercel.app         # independent evidence

任何地方都没有模拟。模拟的解析器只能证明我的模拟返回了我告诉它的内容;值得捕获的失败是上游改变形状,而没有任何模拟捕获过这种失败。

npm run adversarial 是能发现问题的那个。它针对云元数据端点,向部署的服务器抛出恶意主机名、错误类型、4000 字符的域名和格式错误的协议帧,并将对服务器本应拒绝的问题给出自信回答视为最严重的失败。它在第一次运行时发现了三个真实缺陷。

在不信任此仓库的情况下检查它

npm run prove 的存在是因为我自己通过的测试对没有编写它们的人来说证明力很小。它通过官方 MCP 客户端 SDK 调用部署的服务器,然后从与服务器使用的不同解析器重新获取每个 DNS 事实,并直接从公司重新获取页面,逐字段比较并打印每个来源 URL。

还有三种不需要这里任何东西的方法:

# Anthropic's own inspector, not my code
npx @modelcontextprotocol/inspector --cli https://doorknock-eight.vercel.app/mcp --transport http --method tools/list

# raw JSON-RPC, no client, no session, because it is stateless
curl -s -X POST https://doorknock-eight.vercel.app/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

# let your own client run its health check against it
claude mcp add --transport http doorknock https://doorknock-eight.vercel.app/mcp
claude mcp list

以及只需要浏览器的版本。打开两者并比较:

出了什么问题,以及我做了什么

到目前为止有六个缺陷。三个来自对抗性脚本在部署上的第一次运行,一个来自独立验证脚本,还有一个在测试中而不是在服务器中。

1. 包裹在成功中的拒绝。 询问服务器关于 169.254.169.254 或 metadata.google.internal 返回了 HTTP 200 和结果对象。没有泄露任何内容:获取守卫正确拒绝了请求,因此从未联系过内部地址。但研究调用并行运行站点获取和 DNS 查找,而 DNS 部分愉快地继续,因此调用者得到了包裹在拒绝周围的 200。纵深防御起作用了,但响应契约没有。地址规则现在在 normaliseDomain 中运行,在前门,因此整个操作以 400 拒绝。

2. 重定向由运行时跟随,而运行时没有检查任何内容。 第一个版本传递了 redirect: 'follow' 并仅验证了第一跳。一个返回 302 到内部地址的公共主机将直接穿过守卫。重定向现在由手动跟随,最多五次,每一步都重新解析和重新检查,然后才采取,并且链在答案中返回,因为域名将你发送到哪里本身就是一个发现。

3. 接受了 4000 字符的域名。 没有任何地方进行长度检查。DNS 本身在 253 个字符和每个标签 63 个字符处停止,因此任何更长的东西都不可能是真实名称。现在以解释拒绝。

4. 同等优先级的 MX 记录每次调用都以不同顺序返回。 由独立验证脚本发现,该脚本报告了服务器所说的与第二个解析器所说的之间的差异。记录是相同的;只有顺序不同,因为解析器轮换同等优先级的答案,而排序仅按优先级进行,这不是全序。现在按主机名打破平局,因此相同的记录总是产生相同的输出。

5. 一个测试在它从未查看的东西上失败。 对抗性脚本在检查之前将每个响应体截断为 600 个字符,因此未知信号断言在响应中大约四千字节处查找字段,从未看到它,并在服务器正确时报告服务器损坏。这比任何真实缺陷都花费了更多时间。现在保留整个主体,仅在打印时截断。一个根据它从未实际读取的内容决定通过或失败的测试比没有测试更糟糕,因为它被相信了。

6. 平台向处理程序传递 Node IncomingMessage,而不是 Web Request。 继承自我之前以这种方式构建的服务器,也是 npm run smoke:mcp 启动真实的 node:http 服务器并通过套接字与其通信而不是在内存中构建请求对象的原因。构建自己的请求形状的测试只测试该形状。

限制,明确说明

  • 它只读取首页。通过标签管理器加载或位于内部页面上的标签会被遗漏,答案会这样说,而不是暗示该工具不存在。

  • 它对员工人数、收入、所有权或联系人姓名一无所知,并且不会从公司名称猜测域名。

  • 不检查 DKIM。选择器无法从 DNS 中发现,因此检查它意味着猜测,而猜测失败看起来与根本没有 DKIM 的域名完全相同。

  • 地址守卫解析名称,检查地址,然后按名称获取,因此在这两个步骤之间更改的 DNS 记录并未完全关闭。将连接固定到已检查的地址需要此运行时未公开的代理。缓解措施是,没有响应体以原始形式到达调用者,只有命名的匹配信号,因此成功的重新绑定不会向尝试者返回任何可读内容。这在代码中以及这里都有写明。

布局方式

src/core.ts            the operations, shared by both front doors
src/mcpServer.ts       the MCP tool surface
src/lib/guard.ts       what this server is allowed to fetch
src/lib/dns.ts         DNS over HTTPS, so every fact has a URL
src/lib/site.ts        redirect-by-hand page fetching and reading
src/lib/fingerprints.ts  the technology table, one literal string per entry
src/lib/email.ts       MX, SPF and DMARC, read in plain words
src/lib/signals.ts     the published vocabulary
src/lib/qualify.ts     the rules engine
src/lib/hubspot.ts     the CRM writes, with the caller's own token
api/                   the four endpoints
scripts/               five suites, no mocks

MIT 许可。

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    An MCP server that provides AI agents with ICP Triangulation Framework™ for scoring prospects across firmographics, behaviors, and growth signals, plus RFM analysis and pipeline health scoring, with optional HubSpot integration.
    3
    Business Source 1.1
  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that uses a browser extension to interact with HubSpot through the logged-in browser, enabling reading, searching, creating, and updating HubSpot records without API tokens.
    8 npm
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP-native sales intelligence server enabling prospect enrichment, LinkedIn scraping, and CRM push to HubSpot/Salesforce via natural language.
    81 npm
    Mozilla Public 2.0