mcpField
L
Less Annoying CRM (remote, OAuth)

Less Annoying CRM (remote, OAuth)

远程服务
github.com商业与营销01 天前更新

关于 Less Annoying CRM (remote, OAuth)

这是部署在 Cloudflare Workers 上的 Less Annoying CRM 非官方远程 MCP 服务,供支持 OAuth 的 MCP 客户端使用。它通过 OAuth 2.1 授权访问,并提供可选只读权限及与本地版本相同的 10 个工具。

主要功能

  1. 01OAuth 2.1 浏览器授权
  2. 02Streamable HTTP 远程连接
  3. 03读取联系人、备注和任务
  4. 04查看销售管道及项目
  5. 05创建记录并更新项目状态
  6. 06按授权范围限制读写

适用场景

  1. 01在 claude.ai 中连接 CRM
  2. 02通过浏览器授权远程 MCP 客户端
  3. 03授予只读权限以查询 CRM
  4. 04部署到自己的 Cloudflare 账户

MCP 相关

远程 MCP 服务通过 Streamable HTTP 提供 10 个 Less Annoying CRM 工具,并使用 OAuth 2.1 和授权范围控制访问。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://lacrm-mcp.northkeellabs.com/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

详细介绍

lacrm-mcp-remote

为 Less Annoying CRM(LACRM)提供的远程 MCP 服务,托管于 Cloudflare Workers,并支持 OAuth 2.1 登录。它提供的 10 个工具与本地 lacrm-mcp 服务相同(由 Northkeel Labs 开发,也使用 Python 和 stdio),但通过 Streamable HTTP 提供,因此可用作 claude.ai 自定义连接器,也可用于任何支持带 OAuth 的远程服务的 MCP 客户端。

独立且非官方项目。与 Less Annoying CRM 无关联,未经其认可或支持。

托管端点

https://lacrm-mcp.northkeellabs.com/mcp

Northkeel Labs 在该 URL 上运行此代码。将其粘贴到任何支持带 OAuth 的远程服务的 MCP 客户端中(参见连接客户端),登录,然后在授权页面粘贴你的 LACRM API 密钥。Worker 仅存储加密后的 OAuth 授权凭据;不会保留你的密钥或 CRM 数据副本。免费提供,尽力维护,不提供 SLA,每个连接每分钟最多 60 次工具调用。若要改为在你自己的 Cloudflare 账户上运行,请参见自行部署。

为什么采用远程服务和 OAuth

本地 stdio 服务要求每位用户安装 Python、将 API 密钥存储在配置文件中,并让进程持续运行在自己的计算机上。远程服务只需一个 URL。用户将其粘贴到 claude.ai、Claude Desktop 或 Cursor 中,在浏览器中登录一次,客户端便会获得一个短期有效、可撤销的令牌。API 密钥不会暴露给客户端、配置文件或模型上下文。

LACRM 本身不支持 OAuth,只提供 API 密钥。此服务通过“自带密钥,获取 OAuth”的模式连接两者:Worker 是符合标准的 OAuth 2.1 授权服务器(发现元数据、动态客户端注册、Client ID Metadata Documents、PKCE S256、刷新令牌轮换),用户只需在授权页面粘贴一次 LACRM 密钥。系统会通过一次只读的 LACRM 调用验证密钥,之后密钥便只存在于加密后的 OAuth 授权凭据中。

架构

flowchart LR
  subgraph Client["MCP client (claude.ai, Claude Desktop, Cursor, Inspector)"]
    C[OAuth + Streamable HTTP]
  end
  subgraph Worker["Cloudflare Worker: lacrm-mcp-remote"]
    OP["OAuthProvider<br/>discovery, register, token"]
    AU["Consent page at authorize<br/>key + access level"]
    MCP["MCP endpoint<br/>rate limit, scope gate, 10 tools"]
    RL[("RateLimiter<br/>SQLite Durable Object<br/>one per grant")]
  end
  KV[("KV: OAUTH_KV<br/>clients, grants, token hashes<br/>props encrypted")]
  LACRM["LACRM API v2<br/>api.lessannoyingcrm.com"]
  C -- discovery, DCR/CIMD, token --> OP
  C -- browser sign-in --> AU
  C -- Bearer token --> MCP
  OP <--> KV
  AU -- GetUser (validate key) --> LACRM
  AU -- completeAuthorization --> OP
  MCP --> RL
  MCP -- key from decrypted grant --> LACRM

代码索引:src/index.ts(OAuthProvider 接线)、src/authorize.ts(授权页面)、src/mcp.ts(受保护端点)、src/tools.ts(10 个工具)、src/lacrm.ts(API 客户端、重试、错误映射)、src/security.ts(截断、不可信数据包装、脱敏)、src/ratelimit.ts(Durable Object)。

基于 @cloudflare/workers-oauth-provider 1.2.4、agents 0.33.0(createMcpHandler)和 MCP TypeScript SDK v2(@modelcontextprotocol/server 2.4.0)构建。处理程序是无状态的:每个请求都会为对应的授权凭据创建一个全新的 MCP 服务。它通过同一个 /mcp 端点同时支持 2025 年推出的 Streamable HTTP 客户端和 2026 年的无状态协议。没有 /sse 端点。McpAgent 自 agents 0.33.0 起已弃用,因此这里改用 createMcpHandler;唯一的 Durable Object 是按授权凭据隔离的速率限制器。

授权流程,一步步说明

  1. 客户端不带令牌调用 POST /mcp,收到 401,响应中包含 WWW-Authenticate: Bearer resource_metadata=".../.well-known/oauth-protected-resource/mcp", scope="lacrm.read"。
  2. 客户端读取受保护资源元数据(RFC 9728),然后读取位于 /.well-known/oauth-authorization-server 的授权服务器元数据(RFC 8414)。
  3. 客户端通过 Client ID Metadata Document URL 表明身份,或在 /oauth/register 注册(RFC 7591 动态客户端注册)。
  4. 客户端在浏览器中打开 /authorize,并使用 PKCE(仅支持 S256)、state 和 resource。服务器会拒绝未知客户端以及任何未注册的重定向 URI,并在本地显示错误,而不会重定向。
  5. 同意页面会显示发起请求的客户端信息(名称、CIMD 客户端的已验证域名、重定向主机;本地应用会显示警告),并要求输入 LACRM API 密钥和访问级别:只读(lacrm.read)或读写(lacrm.read lacrm.write)。
  6. 提交时(仅限 POST;CSRF 句柄绑定到 __Host- Cookie,且只能使用一次,有效期为 10 分钟),服务器会使用该密钥调用 LACRM GetUser。如果密钥无效,则显示错误,且不会存储任何内容。
  7. 服务器完成授权。密钥、LACRM 用户 ID、已授予的作用域和授权 ID 会作为授权属性存储,并使用由令牌包装的密钥材料加密。随后,浏览器会携带授权码重定向到客户端。
  8. 客户端在 /oauth/token 使用授权码和 PKCE 验证器换取访问令牌(有效期 1 小时)和轮换刷新令牌。
  9. 每次 /mcp 调用都会按授权进行速率限制(默认每分钟 60 次)并检查作用域:只读授权在 tools/list 中只能看到 6 个工具,而且任何写入工具调用都会被拒绝,无论该工具是否列出。

工具

工具访问权限LACRM 函数功能
search_contacts读取GetContacts按文本搜索联系人和公司;每条记录返回摘要,支持分页
get_contact读取GetContact获取单个联系人或公司的完整记录
list_contact_notes读取GetNotesAttachedToContact获取联系人的备注,支持分页
list_tasks读取GetTasks获取指定日期范围内的任务(最长 366 天),可选联系人筛选条件
list_pipelines读取GetPipelines获取管道及其状态 ID
list_pipeline_items读取GetPipelineItems获取单个管道中的项目,可选状态筛选条件
create_contact写入CreateContact新建联系人或公司;所有者默认为密钥对应的用户
add_note写入CreateNote为联系人添加纯文本备注
create_task写入CreateTask新建任务,可选关联联系人
update_pipeline_item_status写入EditPipelineItem将项目移至另一状态;不会运行自动化流程

没有删除工具。限制与 Python 版本一致:每页最多返回 50 条结果,并提供 has_more_results;文本字段最多截断至 2,000 个字符;列表最多包含 50 个项目;每个包含 CRM 记录的响应都会带有 data_notice,标明其中的内容是不可信数据,而非指令。在请求发送到 LACRM 之前,会使用 zod 验证输入(ID 必须是数字字符串,枚举值、ISO 日期、电子邮件格式和长度限制均会进行检查)。

部署自己的实例

你需要一个 Cloudflare 账户(免费套餐即可:一个 Worker、一个 KV 命名空间、由 SQLite 支持的 Durable Objects)以及 Node 22+。

git clone <this repo> lacrm-mcp-remote && cd lacrm-mcp-remote
npm install
npx wrangler login
npx wrangler kv namespace create OAUTH_KV

将打印出的命名空间 ID 粘贴到 wrangler.jsonc 中的 kv_namespaces[0].id(仓库中的 ID 属于托管实例,无法在你的账户中使用)。仓库配置会通过我们的自定义域名提供 Worker,因此也要更改地址:

  • 使用自己的域名(该区域必须位于同一个 Cloudflare 账户中):将 routes[0].pattern 设置为你的主机名,例如 mcp.example.com,并将 vars.MCP_RESOURCE 设置为 https://mcp.example.com/mcp。
  • 或使用 workers.dev:删除 routes 条目,设置 "workers_dev": true,并将 vars.MCP_RESOURCE 设置为 https://lacrm-mcp-remote.<your-workers-subdomain>.workers.dev/mcp(你的子域名显示在 Cloudflare 控制面板的 Workers and Pages 下)。

令牌与此精确 URL 绑定。然后:

npm test                 # unit and integration tests in the Workers runtime
npx wrangler deploy

无需服务器端密钥:每位用户的 LACRM 密钥都会通过授权页面提交,并且仅存储在其加密授权信息中。可选设置是 wrangler.jsonc 中的普通变量(RATE_LIMIT_PER_MINUTE,默认值为 60)。如果之后添加自己的密钥,请在生产环境中使用 npx wrangler secret put NAME,在本地使用 .dev.vars(参见 .dev.vars.example;.dev.vars 已被 gitignore 忽略)。

本地开发:将 .dev.vars.example 复制为 .dev.vars(其中会将 MCP_RESOURCE 设置为 http://localhost:8787/mcp,覆盖生产环境中的值),然后运行 npx wrangler dev,即可通过 http://localhost:8787 提供所有内容。

连接客户端

使用托管端点 https://lacrm-mcp.northkeellabs.com/mcp 或你自己的部署 URL。

  • claude.ai:依次前往 Settings > Connectors > Add custom connector。粘贴 URL,然后点击 Connect。浏览器标签页会打开授权页面;粘贴你的 LACRM 密钥(LACRM:Settings > Programmer API),并选择访问级别。

  • Claude Desktop:依次前往 Settings > Connectors > Add custom connector,URL 和操作流程与 claude.ai 相同。

  • Cursor:将配置添加到 ~/.cursor/mcp.json 并启用服务;Cursor 会打开浏览器进行登录。

    { "mcpServers": { "lacrm": { "url": "https://lacrm-mcp.northkeellabs.com/mcp" } } }
    
  • MCP Inspector:运行 npx @modelcontextprotocol/inspector,选择传输方式 "Streamable HTTP",输入 URL,并完成 OAuth 登录流程。针对本地开发时,请使用 http://localhost:8787/mcp。

如需撤销访问权限,请在 LACRM 中删除或轮换 API 密钥。使用该密钥创建的所有授权信息都会失效,无论令牌由哪个客户端持有。

安全

摘要(详情和威胁模型请参阅 SECURITY.md):

  • LACRM 密钥绝不会作为工具参数接收、返回给客户端或写入日志。LACRM 返回的错误文本会经过脱敏处理后才会出现在工具结果中。
  • 授权属性(其中保存着密钥)由 OAuth 提供方加密;访问令牌、刷新令牌和授权码仅以哈希形式存储。
  • 授权页面:仅接受 POST;CSRF 句柄只能使用一次,并与浏览器绑定;所有由客户端提供的文本都会进行 HTML 转义;使用 Content-Security-Policy: default-src 'none'; script-src 'none'; frame-ancestors 'none',并仅包含一个带 nonce 的内联样式;不使用 JavaScript 和第三方资源;设置 X-Frame-Options: DENY 和 no-store。
  • 严格匹配重定向 URI;未知客户端和未注册的重定向 URI 会显示为本地错误,绝不会触发重定向。
  • 每次调用都会强制执行作用域限制;每项授权都有速率限制;写入操作在遇到 5xx 错误或超时时绝不会自动重试。
  • CRM 内容会限制长度并标记为不可信,以降低提示词注入风险。无法彻底消除风险;写入操作时应有人类介入,进行摘要时优先使用只读授权。

测试

测试结果(2026-11-10):npm test 通过 50 项测试(通过 @cloudflare/vitest-plugin 使用 Workers 运行时;通过 fetch 模拟 LACRM);tsc --noEmit 检查通过;wrangler deploy --dry-run 执行成功;端到端实测(scripts/e2e-live.mjs 针对 wrangler dev 和一个包含演示数据的真实 LACRM 账户)20/20 个步骤通过;针对生产部署 https://lacrm-mcp.northkeellabs.com 进行的同一测试也为 20/20。已脱敏的输出:本地、生产环境。2026-11-10 还将其作为 claude.ai 自定义连接器进行了测试(只读授权)。

测试涵盖每个工具的请求映射和输出格式、截断、分页、不可信数据包装、错误映射和脱敏、重试策略、权限范围控制(只读授权既无法查看也无法调用写入工具,包括批量调用)、授权页面(错误密钥、缺少或伪造的 CSRF 令牌、未知重定向 URI、未知客户端、HTML 转义、拒绝授权、一次性句柄)、速率限制,以及确保密钥不会出现在任何响应或日志行中。

如需自行运行实时测试:先启动 npx wrangler dev,然后运行 LACRM_API_KEY=... node scripts/e2e-live.mjs。该测试会执行一次写入操作:在名为 “Maya Demo” 的联系人上添加一条备注。

免责声明

这是一个独立的非官方项目,与 Less Annoying CRM 无关,未获其认可或支持。“Less Annoying CRM” 是其所有者的商标。使用风险自负;连接生产 CRM 账户前,请先检查代码。采用 MIT 许可证,详见 LICENSE。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。