关于 callwright
Callwright 是可自托管的 MCP 语音 Agent,通过 Retell 拨打电话,并按助手整理且经用户确认的指示执行。它支持受约束的多语言通话,并返回通话结果。
主要功能
- 01经用户确认回读后拨打电话
- 02查询通话结果和转录
- 03管理通话配置与设置
- 04添加并验证通话语言
- 05根据通话学习资料
- 06未接通时默认重拨一次
适用场景
- 01致电确认已安排的预约
- 02在获批时间范围内预订座位
- 03向商家询问信息但不预订
- 04使用已保存的资料更改预约
MCP 相关
Callwright 向 MCP 客户端提供拨打电话、查询结果、管理资料和设置、语言及学习功能。拨号前会先回读内容,并要求明确确认。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y callwrightRETELL_API_KEY密钥Your Retell secret API key (stays server-side)MCP_AUTH_TOKEN密钥Bearer token clients must send; required when exposed beyond localhostPORTPort the HTTP MCP server listens on (default 8787)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Callwright
一个可代你拨打电话的语音 Agent,处理预订、预约、确认和一般咨询,由大模型的指引和上下文信息塑造。它会说明自己是 AI,在你设定的范围内协商,绝不捏造信息,并汇报结果。
基于 Retell 构建。它以 MCP 服务的形式提供,因此任何兼容 MCP 的助手(Claude、ChatGPT、Cursor、Copilot)都能替你拨打电话——将 callwright(执行器)与其他 MCP(WorkIQ、Gmail、calendar——传感器)结合起来获取上下文。
只需开口询问
你无需填写表单——只要用日常语言询问助手,它就会收集上下文(来自日历、邮件或聊天),安排通话内容,先读给你听,并在你同意后拨打:
“在我的日历里找到维修预约,然后打电话给承包商,确认周四是否仍按计划进行。”
“打电话给 Sakura Sushi,预订本周五晚上 7 点的 4 人桌——6:30 到 8 点之间都可以。”
“打电话给我的牙医,把洗牙预约改到下周的某个时间;我的会员 ID 在个人资料里。”
“電話して、東京の美容院に明日の午後カットの予約を取って.” — (用日语拨打电话)
“打电话给京都这家酒店,询问他们到机场的租车价格——只收集信息,不要预订。”
助手只会提取每通电话所需的最少信息,先与你确认计划,再以无需等待的方式拨打;你询问时,它会获取通话结果。
工作原理
You (chat) --> Host LLM --gathers context from other MCPs--> shapes a place_call
|
v
callwright MCP --validate + profile + compose + guard--> Retell --> phone
| |
+-- get_call_outcome / learn_from_call <-- outcome --+
- 通用 Agent,而非针对每种场景单独定制。 一个 Agent 提示词 = 固定护栏(说明 AI 身份、绝不付款、绝不捏造、尽量减少 PII)+ 注入的单次通话指引。可处理任何场景和语言。
- 支持多种语言,可在运行时扩展。 初始支持英语和日语;通过
add_language,完全在聊天中即可新增一种通话语言(翻译后的提示词 + 原生语音 + 专属 Agent),无需重新部署。所有语言措辞都作为数据存放于lang-phrases.json,而非代码中。 - 以目的为先的身份说明。 开场先说明目标(“我是 AI 助手。我打电话是为了确认……”),而不是报姓名。只有在商家需要时才会透露你的姓名。
- 尽量减少数据,只在需要时补充。 PII 存放在
principal.facts中(仅在被询问时共享);每通电话只携带最少的相关信息,并会在回读时明确列出将提供哪些类型的数据。当通话用到你尚未保存的长期有效信息时,它会询问是否要记住这些信息——因此个人资料会在使用过程中逐步完善,而非一开始就通过访谈收集。 - 从每次通话中学习。 如果通话因缺少信息而暂缓,个人资料会得到补充,下次便可提前收集这些信息——既可手动操作(
learn_from_call),也可通过经过签名验证的 Retell webhook 自动完成。遇到真正的新场景时,会先暂存并提议(绝不会静默创建),同时通过护栏避免过度细分。 - 有限重试。 无人接听或占线时会重新拨打——默认恰好重拨一次,未经明确要求绝不多拨(防止骚扰)。
工具
设置与配置
| 工具 | 用途 |
|---|---|
get_setup_status | 查看已配置 / 缺少的内容 |
configure | 保存你的姓名、回拨信息、固定事实(+ 可选的资源配置) |
list_scenarios | 已知的场景配置(+ 待处理候选项) |
拨打电话
| 工具 | 用途 |
|---|---|
place_call | 默认仅试运行(返回回读信息);设置 confirm:true 后才会拨号。支持 lang 和 overrides.retry |
get_call_outcome | 根据 call_id 获取结果 + 分析 + 转录 |
list_recent_calls | 最近的通话 |
list_retries | 最近自动重拨的无人接听通话 |
语言
| 工具 | 用途 |
|---|---|
list_voices | 浏览 Retell 语音(用于添加语言) |
list_languages | 此服务支持拨打电话的语言 |
add_language | 在运行时添加新的通话语言(翻译 → Agent) |
verify_language | 对新语言进行质量把关(审核卡片 + 可选的实时测试通话) |
update_language / remove_language | 更改 / 移除已添加的语言 |
学习
| 工具 | 用途 |
|---|---|
learn_from_call | 丰富配置,或暂存新场景候选项 |
list_candidates | 已暂存的场景候选项(待创建的新配置) |
create_profile | 创建新的场景配置(先提议再确认,并有保护措施) |
add_scenario_alias | 将一种通话类型合并到现有配置中 |
reject_candidate | 丢弃噪声 / 一次性候选项 |
place_call 是即发即忘的,并且有门控:首次调用会返回回读信息(包括 PII 涉及范围);只有通过 confirm:true 确认后才会拨号。
get_call_outcome 会返回规范的 outcome 对象。当 Retell 的内置 call_successful 信号与之不一致时,自定义分析优先的状态具有权威性;两个原始信号仍可用于诊断。成功的信息咨询通话使用 completed,而 booked 仅用于实际的预订、预约或承诺。
Retell 设置(前置条件)
Callwright 通过 Retell 拨打电话,因此你需要拥有一个已启用外拨功能的 Retell 账户才能开始使用。在 Retell 控制面板中:
- 创建账户并添加付款方式(Stripe)。通话和电话号码按需付费;Callwright 不会额外收费。
- 完成 KYC 验证。 要启用外拨功能和购买电话号码,这一步是必需的;未完成验证时,通话会被拦截。(这是一次性身份 / 企业验证,通常很快就能获批。)
- 购买电话号码。 这会成为你的来电显示号码(
from号码)。美国本地号码最便宜;Callwright 会在configure run_provisioning期间自动选择该号码。 - 创建 API 密钥(Settings → API Keys)。这是你的
RETELL_API_KEY,它会保留在服务端,绝不能放入浏览器或聊天中。
可选,建议启用:
- 已验证电话号码 / 品牌呼叫(控制面板 → Telephony)——注册你的号码,降低运营商将其标记为 "Spam Likely" 的可能性,从而显著提高外拨电话的接听率。
不需要(目前在此处未启用):
- A2P 10DLC 注册——仅在需要发送 SMS 时才需要,须经过多个步骤:企业资料 → 品牌 → 活动审批,并产生周期性费用。Callwright 的 SMS 通知功能已构建完成,但目前搁置,因此拨打电话时完全可以跳过此项。
费用按分钟计费,并取决于目的地(美国大约为每分钟 ~$0.015,国际通话费用更高),此外还需支付每月的号码租用费。
安装
在 npm 上发布为 callwright。全局安装后即可使用 callwright(服务端)和 callwright-init(设置向导)命令:
npm install -g callwright
或者克隆此仓库并运行 npm install,从源码运行(node server.js、node init.js)。
无论采用哪种方式,callwright 都是一个可自托管的单用户 HTTP MCP 服务:你运行自己的实例,并使用自己的 Retell 凭据(参见上文的 Retell 设置)。数据不会共享,也不支持多租户。
本地运行
使用全局安装:
callwright-init # one-time setup wizard (number, agent, your identity)
export RETELL_API_KEY=key_xxx # [Environment]::SetEnvironmentVariable on Windows
callwright # MCP server on :8787 (POST /mcp)
如果是从克隆的仓库运行,请改用 node init.js 和 node server.js。
随时检查设置状态:callwright-init status(或 node init.js status)。
从命令行发起通话(绕过 MCP):node dispatch.js <job.json> --go。
用于本地场景时,
MCP_AUTH_TOKEN是可选的——未设置时,服务仅接受环回连接。当你将服务暴露到 localhost 之外时再设置(参见部署为托管服务)。
部署为托管服务(单用户)
目标:部署一个只有你能使用的远程 MCP URL。适用于 Web 客户端(claude.ai、chatgpt.com)和本地客户端。
1. 选择具有持久磁盘的主机
config.json 和 scenario-profiles.json 会在运行时写入(由 configure 和 learn_from_call 写入),因此请避免使用临时或无服务器文件系统。适用选项包括:Fly.io(卷)、Railway(卷)、Render(磁盘)。小型常驻实例即可——通话量很少。
2. 设置环境变量(主机控制面板)
RETELL_API_KEY = key_xxx # your Retell secret - stays server-side
MCP_AUTH_TOKEN = <long random> # the bearer token only you hold
PORT = 8787 # or whatever the host injects
CALLWRIGHT_DATA_DIR = /data # persistent volume for runtime state
CALLWRIGHT_PUBLIC_URL = https://your-host.example.com # optional: enables the auto-learn webhook (Retell posts call_analyzed back here)
CLAUDE_ROUTINE_URL = https://api.anthropic.com/v1/claude_code/routines/trig_xxx/fire # optional immediate call completion wake-up
CLAUDE_ROUTINE_TOKEN = <routine trigger token> # dedicated token generated by the Claude Routine
参见 .env.example。切勿在浏览器或聊天中填写 Retell 密钥。
当通话来自 TickTick 任务时,发起通话的助手可以将
tracking.ticktick_task_id 传递给 place_call。Callwright 会将该不透明 ID
存储在 Retell 仅用于存储的元数据中,在自动重试时保留该 ID,并通过最终的
call_analyzed webhook 唤醒已配置的 Claude Routine。
Routine URL 和令牌为可选项;每小时轮询仍是备用方案。
3. 部署
提供了 Docker:
docker build -t callwright .
docker run -p 8787:8787 --env-file .env callwright
或者将主机指向此仓库(它会自动检测 Dockerfile)。在应用目录挂载一个卷,使 config.json / scenario-profiles.json 能在重启后保留。
无需 Docker 的替代方案:在主机上通过 npm 安装并直接运行二进制文件(将 CALLWRIGHT_DATA_DIR 指向持久卷,使运行时状态在重启后保留):
npm install -g callwright
CALLWRIGHT_DATA_DIR=/data callwright # reads RETELL_API_KEY / MCP_AUTH_TOKEN from env
4. 通过 MCP 完成首次运行设置(无需网页)
在聊天中完成设置:
- 连接服务(见下文)。
- 请求助手调用
configure,并设置run_provisioning: true,同时提供你的姓名和回拨号码。此操作会验证密钥、选择你的 Retell 号码、创建通用 Agent 并保存你的个人资料。 - 此时
get_setup_status应返回ready: true。
(如果你更愿意,也可以在主机 shell 中运行一次 node init.js。)
连接客户端
将 URL 替换为你部署的主机地址,并将令牌替换为你的 MCP_AUTH_TOKEN。服务支持通过两种方式传递令牌:Authorization: Bearer 请求头(Desktop/Code/Cursor),或 ?key= URL 查询参数(连接器表单没有请求头字段的 Web 客户端)。
Claude.ai(Web)
Web 连接器表单只接受 URL,因此请将令牌放入 URL:
- 设置 → 连接器 → 添加自定义连接器(或浏览连接器 → 添加自定义连接器)。
- 名称:
Callwright - URL: 粘贴你的主机地址 +
/mcp,并通过?key=添加令牌:https://your-host.example.com/mcp?key=<MCP_AUTH_TOKEN> - 保存,然后在聊天中启用该连接器(🔌/工具菜单)。询问 “你有哪些 callwright 工具?” 以确认连接成功。
由于令牌位于 URL 中,请将该连接器 URL 视同密码——任何拥有该 URL 的人都可以使用你的 Retell 账户拨打电话。更换
MCP_AUTH_TOKEN并更新连接器即可轮换令牌。
Claude Desktop / Cursor
{
"mcpServers": {
"callwright": {
"url": "https://your-host.example.com/mcp",
"headers": { "Authorization": "Bearer <MCP_AUTH_TOKEN>" }
}
}
}
Claude Code
claude mcp add --transport http callwright https://your-host.example.com/mcp \
--header "Authorization: Bearer <MCP_AUTH_TOKEN>"
ChatGPT(Developer mode / connectors)
使用相同的 URL 添加自定义 MCP connector——请求头和 ?key= 两种方式均可。
请保持开启 “运行工具前确认”。
place_call默认已采用试运行模式,但对于会花钱并联系真实人员的执行工具,工具确认是很好的第二道关卡。
安全注意事项
- **单个 bearer token 就是你的锁。**任何拥有该 token 的人都可以拨打电话,费用记入你的 Retell 账户。请像对待密码一样保管它;修改
MCP_AUTH_TOKEN即可轮换。 - **Retell 密钥遵循最小权限原则。**如果不需要完整的管理员权限,请使用受限密钥。
- **PII。**固定信息存储在主机上的
config.json中。拨打电话时仅发送最少的信息,且只在商家提出要求时才分享;每次都会在回读内容中显示所涉及的信息。 - 如果未设置
MCP_AUTH_TOKEN,服务仅接受 loopback 连接(本地开发)。
关键文件
| 文件 | 用途 |
|---|---|
server.js | MCP 服务(Streamable HTTP、bearer 身份验证)+ 自动学习 / 重试 webhook |
dispatch-core.js | 验证 → 配置档案 → 组合变量 → 分派(共享核心) |
dispatch.js | 基于 dispatch-core 的 CLI |
setup-core.js | 配置资源 + config + 状态 + 延迟保存辅助函数(由 init 和 MCP 共享) |
lang-core.js | 运行时语言管理(添加/验证/更新/移除、语音) |
lang-phrases.json | 按语言整理的措辞(数据,非代码) |
learn-core.js | 配置档案补充 + 新场景候选项暂存(防止场景碎片化) |
retry-core.js | 无人接听重试策略 + 有限的重新拨号决策 |
routine-core.js | 幂等处理 Retell 通话完成事件 → 触发 Claude Routine |
init.js | 终端配置向导(node init.js / node init.js status) |
update-prompt.js | 将提示词 + 工具 + 礼仪规范 + webhook 推送到现有 Agent |
place_call.schema.json | LLM 填写的任务约定 |
generic-prompt.md / .ja.md | 通用 Agent 提示词(防护规则 + {{variables}}) |
scenario-profiles.json | 学习配置档案(按场景推荐的详细信息) |
learn.js / get-call.js | CLI:补充配置档案 / 获取通话结果 |
paths.js | 解析可变状态路径(遵循 CALLWRIGHT_DATA_DIR) |
scripts/release.ps1 | 一键发布:提升版本号 + 测试 + 推送 + 发布到 npm 和 MCP 注册表 |
docs/ | 设计规范(add-language、profile-learning) |
webhook/ | 可选的无服务器 Retell→Resend 邮件通知器(独立于 MCP) |
每位用户的运行时文件——
config.json、agents.json、.retell-ids.json、job.*.json、grounding.*.json——均已加入 git 忽略规则。它们会在运行时创建(由init/configure创建),或包含个人通话数据;切勿提交。请从config.example.json和examples/开始。
关于信息披露与合法性的说明
Agent 每次通话开始时都会说明自己是 AI——这是不可移除的固定行为。在某些司法辖区(例如加利福尼亚州的 B.O.T. Act),法律要求披露 AI 通话信息;在其他地方这样做也是良好实践。Agent 也绝不会捏造信息,且只会在商家提出要求时分享个人数据。若用于商业用途或大规模使用,请咨询法律顾问,确认所在司法辖区的相关要求。
可选:每次通话后主动发送邮件
参见 webhook/——一个无服务器 Retell→Resend 通知器,会通过邮件向你发送每次通话的结果。
它独立于 MCP(MCP 会通过 get_call_outcome 按需检索通话结果),且默认不会部署或接入。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。