SMS MCP 差评短信提醒:地图和应用评论实测
SMS MCP 差评短信提醒实测:几个时刻拉地图和应用商店评论,按评论 ID 去重,定时任务带幂等键防重复扣费,再算每小时和每天查一次各要花多少钱。

我们在 2026 年 11 月 14 日新加坡时间 00:16 到 03:30 之间,每隔约一小时拉一次 Joe's Pizza、洛杉矶 DMV 的 Google 地图评论和 DoorDash 的 App Store、Google Play 评论:地图和 Google Play 各 3 轮,App Store 4 轮。整个测试一共 21 次扣费调用,合计 $0.029167,其中 13 次是轮询,另外 8 次是 3 次地点搜索、1 个后来换掉的样本、幂等测试、MCP 测试、MyChart 对照和脚本试跑各 1 次。几轮之间只有 Google Play 出现了新评论;App Store 返回的「最新评论」比拉取时刻早 28.8~31.9 小时,我们用 Apple 自己公开的评论订阅源对照,最新一条完全相同;Joe's Pizza 第 1 轮返回的 20 条评论跨了 35.7 小时,相邻两条的间隔中位数 0.61 小时,中间也有一段 9.75 小时没有评论,之后两小时的两轮里没有新评论。所以差评短信多久查一次要按来源定:地图上的热闹门店每小时查一次,一个来源一个月的接口费约 $1.00;评论少的地点和应用商店每天查一次,一个月约 $0.042。
去重按评论 ID:几轮之间重叠的 297 条次评论,ID 全部逐字相同。定时任务走 REST 并带 Idempotency-Key,同一小时重发直接回放、不再扣费;短信接口没有幂等键,要靠本地待发短信表保证同一条评论只发一次。短信一侧,TrueDialog 在 11 月 10 日发布的 MCP 能从 Claude、ChatGPT 直接发短信,Twilio 自己的 MCP 只能查文档;短信部分我们没有真发,全部是配置示例。

这件活:差评一出现,店主手机上就有一条短信
同样是 1~2 星评论,量差得很远:按我们的推算,DoorDash 两个商店一天约 94 条,Google 地图上的洛杉矶 DMV 一天不到 1 条。Google 地图、App Store、Google Play 都会给经营者发通知,但通知走的是邮件、应用内消息或者开发者后台。短信几乎每部手机都能收、锁屏就能看见,代价是要花钱、要注册号码、要守运营商的规矩。这里要做的活很窄:每小时或每天查一次指定商户和应用的最新评论,发现新的 1~2 星评论,就给负责人发一条短信,同一条评论只发一次、同一次查询只扣一次钱。
这件活拆开是三段。第一段是读评论:用 EveryInfra 的 google_maps_reviews/reviews、app_store/reviews、google_play/reviews 三项能力,按最新排序拿回最近 20~50 条评论。第二段是判断:和上一次看到的评论比,挑出新出现的那几条,再按星级筛。第三段是发短信:经短信类的 MCP 服务器(MCP 是让 AI 助手调用外部工具的开放协议,见 modelcontextprotocol.io)或者短信服务商的接口把提醒发出去。第一段、第二段我们都在 2026 年 11 月 14 日真调过;第三段需要短信账号、注册过的号码和收件人同意,我们没有真发,全部写成「配置示例」,引用的都是对方官网和文档原文。
样本挑了四个,覆盖热闹程度完全不同的两类对象。纽约时代广场附近的 Joe's Pizza Broadway 是一家客流很大的店,Google 地图上有 27,620 条评论;洛杉矶 Hope Street 的加州机动车管理局(DMV)办事处是公共服务窗口,有 2,321 条评论、平均 3.1 星;外卖应用 DoorDash 代表评论量很大的应用,同时在 App Store 和 Google Play 上拉;患者门户应用 MyChart 代表医疗场景,作为跨领域的对照只拉了一轮。这些商户和应用都是公开的,评论者的名字和头像我们一律不写进文章。
| 样本 | 平台和能力 | 公开信息(11 月 14 日读) | 每次拉几条 | 用来回答什么 |
|---|---|---|---|---|
| Joe's Pizza Broadway(纽约) | google_maps_reviews/reviews | 27,620 条评论,4.4 星 | 20 | 热闹的店,每小时会不会有新评论 |
| Los Angeles DMV(Hope St) | google_maps_reviews/reviews | 2,321 条评论,3.1 星 | 20 | 公共服务窗口,差评多但评论少 |
| DoorDash(App Store,美国区) | app_store/reviews | 应用 ID 719972451 | 50 | 应用商店的「最新」有多新 |
| DoorDash(Google Play) | google_play/reviews | 包名 com.dd.doordash | 40 | 同一个应用在两个商店差多少 |
| MyChart(两个商店,对照) | app_store/reviews、google_play/reviews | 应用 ID 382952264、包名 epic.mychart.android | 50 / 40 | 医疗类应用的差评占比 |
SMS MCP 现在有哪几种:能发短信的和只查文档的
Google 搜索联想里,「sms mcp」下面挂着「sms mcp server」「claude sms mcp」「sms api mcp」几个变体(Google 联想词,2026 年 11 月 14 日读)。三款都叫 MCP:一款能发短信,一款只能查文档,一款要在本机跑。我们按对方原文各找了一个代表:一家短信平台自己托管的 MCP 服务器、一家短信接口公司的文档检索 MCP、同一家公司实验室出的本地 MCP。
第一类是 TrueDialog。这家位于美国奥斯汀的企业短信平台在 2026 年 11 月 10 日发布了 TrueDialog MCP,新闻稿写明它让人和 AI 代理在 ChatGPT、Copilot、Claude、Gemini、Perplexity 等助手里发送短信和 RCS 消息、管理联系人,已经上了 ChatGPT 的插件目录和微软 Copilot 的连接器目录,其他助手经 tdmcp.com 接入(PR Newswire 新闻稿;产品页见 truedialog.com/features/mcp)。新闻稿还写了一句对算账有用的话:MCP 按 TrueDialog 的标准价格提供,不另收 MCP 费用。鉴权走 OAuth 2.1:客户端自动发现 auth.tdmcp.com 上的授权服务器,用户在浏览器里登录自己的 TrueDialog 账号,客户端只拿到短期令牌,不用粘贴任何密钥(tdmcp.com 的配置说明)。端点是 https://connect.tdmcp.com,同时接受加了 /mcp 的写法。
第二类是 Twilio 自己的 MCP 服务器。它在 2026 年 5 月 7 日以公开测试版发布,托管在 mcp.twilio.com/docs,不需要账号、不需要鉴权(Twilio 博客)。它只有 twilio__search 和 twilio__retrieve 两个工具,用来搜索和取回 1,800 多个接口的参数说明;文档写明这个服务器只读,不会替你执行接口调用(Twilio MCP 文档)。所以它能帮编程助手写出调用 Twilio 发短信的代码,自己发不了短信。文档把「可以直接调用接口、用 OAuth 鉴权的工具」列在「下一步」里。
第三类是 Twilio 实验室的 @twilio-alpha/mcp。它在本机用 npx 启动,命令行里带上账号 SID 和 API Key,就能把 Twilio 的公开接口都变成 MCP 工具,其中包括发短信(GitHub 仓库 twilio-labs/mcp)。GitHub 上最后一次提交是 2025 年 7 月 7 日,npm 上的最新版本 0.7.0 也是同一天发布(npm 包页)。仓库 README 提醒,不要把社区写的 MCP 服务器和官方的放在一起跑,防止注入攻击借道拿到 Twilio 账号的工具。
| 项 | TrueDialog MCP | Twilio MCP(公开测试) | @twilio-alpha/mcp(实验室) |
|---|---|---|---|
| 发布或最近更新 | 2026-11-10 发布 | 2026-05-07 公开测试 | 最近提交 2025-07-07 |
| 运行在哪 | 对方托管,connect.tdmcp.com | 对方托管,mcp.twilio.com/docs | 本机 npx 启动 |
| 鉴权 | OAuth 2.1,浏览器登录 | 不需要 | 命令行带 SID 和 API Key |
| 能不能发短信 | 能,send_sms | 不能,只查文档 | 能,经接口工具 |
| 发前试运行 | execute=false 不发、不扣额度 | 不适用 | 文档没写 |
| 能不能读回复 | 不能(只发不收) | 不适用 | 经接口工具可以查 |
| 价格 | 按 TrueDialog 套餐,MCP 不另收费 | 免费 | 按 Twilio 用量计费 |
微软 Learn 的连接器页列了十个工具和七条限制(Microsoft Learn:TrueDialog MCP 连接器)。十个工具里六个只读、四个会写,只有 send_sms 会真的发到手机上;send_sms 默认 execute=true,传 execute=false 是试运行,不发送、不消耗额度,但仍会生成一条群发记录;一次调用可以带多个收件人,所以一句话就可能发出很多条。已知限制里第一条是「只能发、不能收」:这个服务器读不到回复和会话。另外它不支持定时或循环群发,发送都是立即的、点对点的;退订和 10DLC、TCPA 的合规责任仍在账号所有人身上,force_opt_in 参数能发给已经退订的联系人,页面要求只在有合法依据时使用。

微软 Learn 页和 tdmcp.com 写的工具数不同。微软 Learn 页写十个工具,多了一个 report_issue(把问题报告发到 TrueDialog 的支持邮箱);tdmcp.com 的工具一节写的是九个工具、六个只读三个写,没有 report_issue。微软 Learn 页还提到一组可选的 inbox_* 收件箱工具,用于对话式短信会话,send_sms 在这组工具开启时对应 inbox_sms_send;tdmcp.com 说明这类工具按部署开启,connect.tdmcp.com 目前只公布那九个。我们没有 TrueDialog 账号,没能连上去数 tools/list,所以两处原文都写出来,以你连上以后实际看到的工具表为准。
差评提醒只要三样:能发、能试运行、能限定发件号码。TrueDialog MCP 三样都有,它缺的是读回复,对单向提醒没有影响。Twilio 自己的 MCP 现在只能帮你写代码;如果你已经在用 Twilio,可以让定时脚本调用它的 Messages 接口,AI 助手只负责写摘要。
评论这一侧:平台自己的通知做到了哪一步
动手写轮询之前,先看平台自己给经营者的通知能不能直接用。只有 Google 商家资料给了新评论的实时推送,而且只给认领了商户的人;Apple 的通知清单里没有「新评论」这一项;Google Play 的接口只给最近一周的评论。
Google 商家资料(Google Business Profile)的帮助页写明,经营者可以在「客户动态」里打开新评论和新照片的提醒,渠道是邮件、搜索页和地图应用(Google Business Profile 帮助:管理通知)。开发者还可以用 My Business Notifications API 把新评论、评论更新等事件推到 Cloud Pub/Sub 主题,再由自己的服务订阅(实时通知设置,页面 2026-08-28 更新;NotificationSetting 参考)。前提是你拥有这个商户的商家资料,并且在 Google Cloud 里配好 Pub/Sub 和 OAuth;取评论全文还要再调 accounts.locations.reviews.list(评论数据教程)。
App Store Connect 的用户通知一共七类,和评论有关的只有「Developer Response」:当用户修改了你已经回复过的评论时发邮件(App Store Connect 帮助:用户通知)。新评论本身不在清单里。要拿评论全文,开发者可以调 App Store Connect API 的 Customer Reviews 接口,按地区、星级筛选,按时间排序(Apple 文档:Customer Reviews),但前提是这个应用在你的开发者账号下。
Google Play 开发者接口里的「回复评论」接口能列出评论、回复评论,每页默认 10 条、最多 100 条;文档写明只能取到最近一周内新写或修改过的评论,而且只包括带文字的评论,只打分不写字的取不到;读取配额是每小时 200 次(Google Play Developer API:Reply to Reviews)。更早的评论要去 Play 管理中心下载 CSV。
| 平台 | 官方推送新评论 | 官方读评论接口 | 只限自己的商户或应用 | 和本文做法的关系 |
|---|---|---|---|---|
| Google 地图 | 有:邮件、地图应用,或 Pub/Sub 推送 | Business Profile API,取全部评论 | 是 | 自己的店优先用官方推送;竞品、加盟店、没认领的店只能轮询 |
| Google 地图(地点接口) | 无 | Places API 每个地点最多 5 条 | 否 | 5 条不够判断新增,见 BL-70 |
| App Store | 无新评论提醒,只提醒「已回复的评论被修改」 | App Store Connect API | 是 | 自己的应用也要轮询 |
| Google Play | 无 | 只给最近一周、只给带文字的 | 是 | 只打分的差评官方接口看不到 |
如果你要盯的地点不归自己账号管,例如区域经理盯加盟店、代运营公司盯客户的店,官方推送用不上。在 App Store 上,连自己的应用都没有新评论推送。Reddit 上 r/smallbusiness 有人问怎样监测不是自己商户的 Google 评论,回帖里的结论是 Google 只让你监测自己的商户(Reddit r/smallbusiness 讨论)。地图地点接口每个地点最多返回 5 条评论(Places API Place Details 文档),用来判断「有没有新评论」太少。
几个时刻实测:新评论多久出现一次
我们在新加坡时间 00:16–00:20、01:19–01:20、02:19–02:20 这三个时刻拉了全部四个样本,03:20 又拉了一次 App Store,参数每次完全相同。这段时间相当于纽约时间 11 月 13 日上午 11 点到下午 2 点、洛杉矶时间上午 8 点到 11 点,正是这些店和窗口开门营业的时段。每一轮都按 sort=newest 取最新的 20~50 条,记下每条评论的 ID、星级和 posted_at,再和前几轮比,算出「新出现」的条数和其中的 1~2 星条数。表中每一行是一次成功的真实调用,每次扣 $0.001389。
| 样本 | 轮次(新加坡时间) | 返回条数 | 新出现 | 新的里 1~2 星 | 和前几轮重叠 |
|---|---|---|---|---|---|
| Joe's Pizza(地图) | 1 · 00:19 | 20 | — | — | — |
| Joe's Pizza(地图) | 2 · 01:19 | 20 | 0 | 0 | 20 |
| Joe's Pizza(地图) | 3 · 02:19 | 20 | 0 | 0 | 20 |
| 洛杉矶 DMV(地图) | 1 · 00:20 | 20 | — | — | — |
| 洛杉矶 DMV(地图) | 2 · 01:19 | 20 | 0 | 0 | 20 |
| 洛杉矶 DMV(地图) | 3 · 02:19 | 20 | 0 | 0 | 20 |
| DoorDash(App Store) | 1 · 00:16 | 50 | — | — | — |
| DoorDash(App Store) | 2 · 01:20 | 50 | 0 | 0 | 50 |
| DoorDash(App Store) | 3 · 02:20 | 50 | 0 | 0 | 50 |
| DoorDash(App Store) | 4 · 03:20 | 50 | 0 | 0 | 50 |
| DoorDash(Google Play) | 1 · 00:17 | 40 | — | — | — |
| DoorDash(Google Play) | 2 · 01:20 | 40 | 7 | 5 | 33 |
| DoorDash(Google Play) | 3 · 02:20 | 40 | 6 | 4 | 34 |
Joe's Pizza 第 1 轮返回的 20 条评论从 2026 年 11 月 12 日排到 2026 年 11 月 13 日,跨度 35.7 小时,相邻两条的间隔中位数 0.61 小时,按这个速度一天大约 12.8 条;但这 20 条里也有两段长空档,一段 7.7 小时、一段 9.75 小时。之后两轮返回的 20 条和第 1 轮完全相同,也就是说,在我们拉取的这 2 小时里没有新评论。对差评提醒来说,每小时查一次,多数时候拿回的是同一批评论。
洛杉矶 DMV 更安静。20 条评论从 2026 年 10 月 20 日排到 11 月 12 日,跨度 551 小时,平均每天 0.8 条,相邻两条的间隔中位数 14.6 小时,最长一段 117.8 小时;三轮返回完全相同。这类地点每天查一次就够了,查得再勤也只是重复付钱。
App Store 一侧的 DoorDash 4 轮返回的 50 条完全相同,最新一条始终是 2026-11-12T11:26:35Z(新加坡时间 11 月 12 日 19:26)发布的那条,离拉取时刻从 28.8 小时变成 31.9 小时。为了分清这是平台的节奏还是我们这边的延迟,我们在新加坡时间 01:21 另外读了 Apple 自己公开的评论订阅源:itunes.apple.com 上 DoorDash 美国区按最新排序的 customerreviews RSS,第一条的 updated 是 2026-11-12T04:26:35-07:00、1 星,换算成 UTC 和接口返回的最新一条是同一时刻、同一星级。也就是说,Apple 自己公开的「最新评论」列表在那个时刻也停在一天多以前,轮询频率改变不了它。MyChart 的 App Store 评论最新一条也在新加坡时间 11 月 12 日 19:35,和 DoorDash 只差 9 分钟。
Google Play 一侧,DoorDash 第 2 轮(2026 年 11 月 14 日 01:20)的 40 条里有 7 条是新的,其中 5 条是 1 星;第 3 轮的 40 条里 34 条是前两轮见过的 ID,另外 6 条是新 ID,其中 1 星 3 条、2 星 1 条。返回按最新排序,这两轮的新评论都排在列表最前面,在之前见过的那些评论之前,所以它们是这一小时里新进入「最新」列表的评论。四个来源里,只有 Google Play 在每一轮之间都有新评论。
几轮之间重叠的评论一共 297 条次(20+20+20+20+50+50+50+33+34),评论 ID 全部逐字相同,没有一条「同作者、同时间、同正文却换了 ID」的情况;Google Play 里唯一一对「正文相同、ID 不同」的,是两位不同的用户都只写了一个词「expensive」。所以按评论 ID 去重在这四个来源上都站得住。时间戳不适合当去重依据有两个原因:评论会被作者修改,Google Play 的开发者文档就把「新写或修改过的评论」放在一起返回;评论也会晚到,站内 BL-79 记录过一条 posted_at 早于上一轮调用、上一轮却没有返回的评论,按「发布时间晚于上次看到的最新时间」判断就会漏发。
只有 Google Play 在几小时里出现了新评论,地图上的两个地点和 App Store 都没有,所以下一节的「每天新评论」改用单次返回里相邻评论 posted_at 的差来估算,属于估算。
| 样本 | 参与计算的评论 | 时间跨度 | 相邻间隔中位数 | 最长空档 |
|---|---|---|---|---|
| Joe's Pizza(地图) | 20 | 35.7 小时 | 0.61 小时 | 9.75 小时 |
| 洛杉矶 DMV(地图) | 20 | 551.2 小时 | 14.63 小时 | 117.81 小时 |
| DoorDash(App Store) | 50 | 11.7 小时 | 0.11 小时 | 2.33 小时 |
| DoorDash(Google Play) | 47 | 15.2 小时 | 0.20 小时 | 2.45 小时 |
| MyChart(App Store) | 50 | 39.6 小时 | 0.35 小时 | 7.12 小时 |
| MyChart(Google Play) | 40 | 16.9 小时 | 0.29 小时 | 1.32 小时 |
DoorDash(Google Play)一行按前两轮返回的 47 条算。最长空档这一列提醒的是:即使是间隔中位数不到一小时的来源,也会有几个小时一条新评论都没有,所以「这一小时没有新评论」本身不是异常。
| 来源类型 | 实测几轮里的新评论 | 建议频率 | 理由 |
|---|---|---|---|
| 地图上的热闹门店 | 2 小时里 0 条;单次返回推算每天约 12.8 条 | 营业时间每小时一次 | 评论一阵一阵来,空档可达 9.75 小时 |
| 地图上评论少的窗口 | 0 条;推算每天 0.8 条 | 每天一次 | 每天不到一条评论,查得再勤也是同一批 |
| App Store | 3 小时里 0 条 | 每天一次 | 「最新」比拉取时刻早 28.8~31.9 小时,和 Apple 公开订阅源一致 |
| Google Play | 每轮 6~7 条 | 每天一到两次,或按小时汇总 | 每轮都有新评论,但一半是 1~2 星,逐条发量太大 |
两把幂等键:同一小时不重复扣费,同一条评论不重复发短信
轮询最容易出的两种事故,一种是同一次查询被重发了几遍、扣了几遍钱,另一种是同一条差评给店主发了好几条短信。两种事故的原因相同:脚本超时重试、定时任务重叠、进程中途崩溃重启,客户端在重发的那一刻不知道第一次到底成功没有。解决办法也相同:给「一次逻辑上的动作」起一个稳定的名字,服务端或者本地表看到同一个名字就只做一次。
数据这一侧,EveryInfra 的 POST /api/v1/social 接受 Idempotency-Key 请求头,长度 1~255 个可见 ASCII 字符;24 小时内用同一把键发同样的请求,直接返回第一次成功的响应,不再运行、不再扣费,响应体带 replayed: true,响应头带 Idempotent-Replayed: true;同一把键换了参数会回 409 idempotency_conflict(EveryInfra llms-full.txt 的 Retries and idempotency 一节;同样的头和错误码也在 openapi.json 里)。我们把键设成「来源名 + UTC 小时」,例如 alert:gmaps:la-dmv-hope-st:2026111316:同一个小时里不管脚本重跑几次,都只扣一次;到了下一个小时,键自动换新,照常读新评论。定时任务和任何会自动重试的调用都走这条 REST 路径,各种重试情形的实测见 API 幂等键实测(BL-115)。
我们在新加坡时间 00:35:02 和 00:35:10 用同一把键对 DMV 发了两次同样的请求。第一次 HTTP 200,返回 10 条评论,扣 $0.001389;第二次 HTTP 200,响应头 idempotent-replayed: true,响应体 replayed: true,返回的 10 条评论和第一次相同。我们再用 MCP 工具 everyinfra_list_requests 查了账户的请求记录:第一次那条有扣费记录,第二次没有新的扣费记录。

短信这一侧情况不同。Twilio Messages 资源的接口文档(Twilio Message resource,11 月 14 日读)里,创建消息的参数没有幂等键:同一条短信 POST 两次,就是两条短信、两笔费用。TrueDialog 的 send_sms 在连接器页和 tdmcp.com 上也没有写幂等参数,只有试运行开关。所以「同一条评论只发一次」只能在自己这边保证。
我们用的办法是本地一张「待发短信表」,主键是「来源 + 评论 ID」。新评论进来先 INSERT OR IGNORE,主键冲突说明这条已经排过队,直接跳过;发送前先把状态改成 sending 并提交,发完再改成 sent。进程如果恰好在发送途中崩溃,这一条会停在 sending,下次运行不会自动再发,留给人看一眼。宁可漏发一条、让人工补,也不要给店主连发三条一样的短信:短信重复会让人对提醒失去信任,也会多付钱。
| 风险 | 发生在哪 | 我们的防法 | 实测或依据 |
|---|---|---|---|
| 同一次查询扣两次钱 | 数据接口超时重试、定时任务重叠 | REST 请求带 Idempotency-Key = 来源 + UTC 小时 | 第二次回放,账户记录里没有新扣费 |
| 同一条评论提醒两次 | 两次轮询返回了同一条评论 | 本地表按评论 ID 去重 | 297 条次重叠,ID 全部一致 |
| 同一条短信发两次 | 短信接口没有幂等键,发送中途崩溃 | 待发表 + 先改 sending 再发 | Twilio 文档创建参数里没有幂等键 |
| 查询失败被当成「没有新评论」 | 接口返回可重试错误,脚本照常往下走 | 重试 3 次仍失败就抛错,这一轮记为未检查,下一轮补 | llms-full.txt 的错误码说明:retryable、retry_after |
| 查询没结果也扣钱 | since 设成当天、当天没有新评论 | 空结果不扣费 | DMV since=2026-11-13 返回 0 条,$0 |
一次查询失败不等于没有新评论:失败的那一轮记成未检查,seen 表不写任何东西,下一轮用新的幂等键照常查,错过的评论会在下一次返回的最新 20 条里出现。下面的脚本按这个规则写。
# review_alert.py: run once an hour. DRY_RUN=1 prints the texts instead of sending them.
import hashlib, json, os, sqlite3, time, urllib.error, urllib.request
from datetime import datetime, timezone
API, KEY = "https://api.everyinfra.com/api/v1/social", os.environ["EVERYINFRA_API_KEY"]
DRY_RUN = os.environ.get("DRY_RUN") == "1"
LINK_BASE = os.environ.get("ALERT_LINK_BASE", "https://example.com") # your own page that shows the review
DB = sqlite3.connect("review_alert.db")
DB.executescript("""
CREATE TABLE IF NOT EXISTS seen (source TEXT, review_id TEXT, rating INT, posted_at TEXT, first_seen TEXT,
PRIMARY KEY (source, review_id));
CREATE TABLE IF NOT EXISTS outbox (source TEXT, review_id TEXT, stars INT, status TEXT, created TEXT,
PRIMARY KEY (source, review_id));""")
SOURCES = {"gmaps:la-dmv-hope-st": {"platform": "google_maps_reviews", "action": "reviews", "params": {
"url": "https://www.google.com/maps/search/?api=1&query=Los%20Angeles%20DMV&query_place_id=ChIJAQOgfwrIwoARag3eO_IQ0oE",
"sort": "newest", "limit": 20}}}
SHORT_NAME = {"gmaps:la-dmv-hope-st": "LA DMV Hope St"} # ASCII only: keeps each text GSM-7
def call(source, body):
key = f"alert:{source}:{datetime.now(timezone.utc):%Y%m%d%H}" # same hour, same Idempotency-Key
req = urllib.request.Request(API, json.dumps(body).encode(), method="POST", headers={
"Authorization": f"Bearer {KEY}", "Content-Type": "application/json", "Idempotency-Key": key})
for _ in range(3):
try:
with urllib.request.urlopen(req, timeout=100) as r:
return json.load(r)
except urllib.error.HTTPError as e:
err = json.load(e).get("error", {})
if e.code in (429, 502, 503, 504) or err.get("retryable"):
time.sleep(int(err.get("retry_after") or 20)); continue # same key on retry: charged once
raise
raise RuntimeError(f"{source}: no result after 3 tries") # a failed check is not "no new reviews"
def review_key(r): # review id first; fallback hash uses each platform's author field
author = r.get("reviewer_name") or r.get("author_name") or r.get("author")
return r.get("id") or hashlib.sha256(f"{author}|{r.get('posted_at')}|{r.get('text')}".encode()).hexdigest()
def link(source, rid=""):
return f"{LINK_BASE}/r/{hashlib.sha256(f'{source}|{rid}'.encode()).hexdigest()[:6]}"
def run():
now = datetime.now(timezone.utc).isoformat(timespec="seconds")
for source, body in SOURCES.items():
try:
rows = call(source, body).get("results", [])
except RuntimeError as e: # mark this hour "not checked"; seen stays as it was
print(e); continue
for r in rows:
stars, rid = r.get("rating") or r.get("score"), review_key(r)
if DB.execute("INSERT OR IGNORE INTO seen VALUES (?,?,?,?,?)",
(source, rid, stars, r.get("posted_at"), now)).rowcount == 0:
continue # seen before
if stars is not None and stars <= 2:
DB.execute("INSERT OR IGNORE INTO outbox VALUES (?,?,?,?,?)", (source, rid, stars, "pending", now))
DB.commit()
def flush(send): # one text per source per run; mark "sending" first so a crash never resends
for (source,) in DB.execute("SELECT DISTINCT source FROM outbox WHERE status='pending'").fetchall():
rows = DB.execute("SELECT review_id, stars FROM outbox WHERE source=? AND status='pending'", (source,)).fetchall()
if len(rows) == 1:
body = f"{rows[0][1]}-star review: {SHORT_NAME[source]} {link(source, rows[0][0])}"
else:
body = f"{len(rows)} new 1-2 star reviews: {SHORT_NAME[source]} {link(source)}"
body.encode("ascii") # raises if a non-GSM character slips in
DB.execute("UPDATE outbox SET status='sending' WHERE source=? AND status='pending'", (source,)); DB.commit()
send(body)
DB.execute("UPDATE outbox SET status='sent' WHERE source=? AND status='sending'", (source,)); DB.commit()
def send_sms(body):
raise NotImplementedError("connect your SMS provider here (Twilio Messages API or TrueDialog)")
if __name__ == "__main__":
run(); flush(print if DRY_RUN else send_sms)脚本的数据接口部分在新加坡时间 00:37:20 和 00:37:31 真跑过两次:第一次读回 DMV 的 20 条评论,全部是新的,其中 6 条 1~2 星进了待发短信表,扣 $0.001389;第二次在同一个 UTC 小时里,用的是同一把幂等键,接口直接回放,脚本读到 0 条新评论,待发表没有增加,账户请求记录里也没有第二笔扣费。上面这版加了 DRY_RUN 开关、按来源每小时合并成一条的 flush() 和纯 ASCII 的短信模板,我们把第 1 轮的 DMV 返回原样喂给它离线跑了两次(不调接口):第一次打印出一条 6 new 1-2 star reviews: LA DMV Hope St https://example.com/r/2ff3c3,67 个字符;第二次没有输出。send_sms() 留空,接你自己的短信服务商。
1~2 星占多少,一天会发几条短信
短信量取决于两件事:新评论来得多快,其中多少是 1~2 星。表中的评论按 ID 去重后合在一起算;「每天新评论」按每个样本最新几十条评论的 posted_at 跨度推算,是估算;「每天 1~2 星」是两列相乘。两个 MyChart 样本只拉了一轮,数字只来自那一次返回。
| 样本 | 去重后条数 | 1~2 星 | 占比 | 按发布时间推算每天新评论 | 推算每天 1~2 星 |
|---|---|---|---|---|---|
| Joe's Pizza(地图) | 20 | 2 | 10.0% | 12.8 | 1.3 |
| 洛杉矶 DMV(地图) | 20 | 6 | 30.0% | 0.8 | 0.2 |
| DoorDash(App Store) | 50 | 27 | 54.0% | 100.9 | 54.5 |
| DoorDash(Google Play) | 53 | 29 | 54.7% | 72.4 | 39.6 |
| MyChart(App Store) | 50 | 15 | 30.0% | 29.7 | 8.9 |
| MyChart(Google Play) | 40 | 13 | 32.5% | 55.4 | 18.0 |
单看一轮的占比会不会偏?下表是每一轮返回里 1~2 星的占比。地图两个地点和 App Store 每轮返回的是同一批评论,占比自然不变;Google Play 每轮都有新评论,占比从 50.0% 升到 60.0%,第 3 轮新出现的 6 条里有 4 条是 1~2 星。样本只有三轮,这个上升只说明「一小时里进来的几条差评就能让占比动 7.5 个百分点」,不说明 DoorDash 的口碑在变差。
| 样本 | 第 1 轮 | 第 2 轮 | 第 3 轮 | 第 4 轮 |
|---|---|---|---|---|
| Joe's Pizza(地图) | 2/20,10.0% | 2/20,10.0% | 2/20,10.0% | — |
| 洛杉矶 DMV(地图) | 6/20,30.0% | 6/20,30.0% | 6/20,30.0% | — |
| DoorDash(App Store) | 27/50,54.0% | 27/50,54.0% | 27/50,54.0% | 27/50,54.0% |
| DoorDash(Google Play) | 20/40,50.0% | 21/40,52.5% | 24/40,60.0% | — |
星级分布(见上方 fig-02)比占比多说明一件事:评论是两头多、中间少。DoorDash 两个商店 1 星都比 5 星多(App Store 20 对 18,Google Play 24 对 19),每个商店 3、4 星加起来都只有 5 条;MyChart 两个商店 5 星都占六成(30/50、25/40),差评集中在 1 星。Joe's Pizza 一半是 5 星,1 星、2 星各 1 条。对提醒规则来说,这意味着阈值设在「≤2 星」还是「=1 星」,在 DoorDash 上只差 12 条(7+5),在 Joe's Pizza 上只差 1 条:先按 1~2 星设,量太大再收紧到 1 星,效果有限。
Joe's Pizza 去重后 20 条里只有 2 条是 1~2 星,推算一天约 1.3 条差评,逐条发短信可以接受。DMV 的差评占比是 30.0%,但评论本身很少,推算下来一天只有 0.2 条。DoorDash 两个商店的最新评论里一半左右是 1~2 星,推算两个商店加起来一天约 94 条(54.5 + 39.6)。
对这种量级的应用,逐条短信没人看得过来。可以换成两种规则之一。一种是「每小时最多一条」:这一小时有差评,就发一条类似「过去一小时 12 条 1~2 星」的短信,链接指向完整列表,上面脚本的 flush() 就是按来源每小时合并成一条。另一种是「超过平时才发」:先用一周的 DRY_RUN=1 数出每小时差评条数的中位数,只有当某一小时的差评数超过中位数的两倍时才发短信,这通常意味着出了故障或者发版出了问题。两种规则都不改变接口费,只改变短信量。
Google 地图上将近一半的评论只有星级没有正文:Joe's Pizza 和 DMV 都是 20 条里 9 条。应用商店的评论在我们拉到的样本里都带正文。
review alert sms 的账:每天查 24 次和查 1 次
数据这一侧的价格很简单。目录里 google_maps_reviews/reviews、app_store/reviews、google_play/reviews、yelp/reviews 四项能力都是每次调用 $0.001389,一次最多拿回 100、500、200、10 条,按次计费,不按条数计费;返回空结果不扣费(目录 2026 年 11 月 14 日读取,见 价格页)。本次实测一共 21 次扣费调用,账户请求记录里的扣费合计 $0.029167,等于 21 × $0.00138889;同键回放和两次空结果都没有扣费。
| 方案 | 每天调用次数 | 每天接口费 | 30 天接口费 | 适合谁 |
|---|---|---|---|---|
| 1 个来源,每天 1 次 | 1 | $0.0014 | $0.042 | 评论少的地点,例如 DMV 这类窗口 |
| 1 个来源,每小时 1 次 | 24 | $0.0333 | $1.00 | 评论多、要当天处理的门店 |
| 3 个来源,每天 1 次 | 3 | $0.0042 | $0.125 | 一个应用盯两个商店加一个地点 |
| 3 个来源,每小时 1 次 | 72 | $0.1000 | $3.00 | 连锁门店的值班提醒 |
| 3 个来源,营业时间每小时(9:00–21:00,13 次) | 39 | $0.0542 | $1.63 | 夜里不发短信的店 |
按样本把「每天查 1 次」和「每天查 24 次」放在一起看,差别在于能多看到什么。下表的「每次能看到的新评论」用上一节的推算速度乘以两次检查之间的小时数,封顶为一次返回的条数;超过封顶说明两次检查之间进来的评论比一次能拿回的多,会漏。
| 样本(每次拉几条) | 每天 1 次:30 天接口费 | 每天 1 次:每次的新评论 | 每天 24 次:30 天接口费 | 每天 24 次:每次的新评论 |
|---|---|---|---|---|
| Joe's Pizza(20) | $0.042 | 约 12.8,未超 20 | $1.00 | 约 0.5 |
| 洛杉矶 DMV(20) | $0.042 | 约 0.8 | $1.00 | 约 0.03 |
| DoorDash App Store(50) | $0.042 | 约 100.9,超过 50 | $1.00 | 约 4.2 |
| DoorDash Google Play(40) | $0.042 | 约 72.4,超过 40 | $1.00 | 约 3.0 |
对 DMV,每天查 24 次多花的 $0.96 换来的几乎全是重复;对 DoorDash 两个商店,每天查 1 次会漏掉一半以上的新评论,要么每小时查,要么每天查但把 limit 提到 200 以上(App Store 一次最多 500 条,Google Play 最多 200 条),费用都一样是每次 $0.001389。
总账的大头在短信一侧的固定费用:3 个来源每小时查一次,一个月接口费 $3.00。Twilio 的美国价格页写明,普通 10 位号码发一条短信每段 $0.0083,另加运营商收的通道费,例如 AT&T 每段 $0.0035、T-Mobile 每段 $0.0045;最终状态为「失败」的消息每条收 $0.001 的处理费(Twilio 美国短信价格,页面写「价格截至 2026 年 11 月」)。号码月租从 $1.15 起(Twilio 号码价格)。再加上 10DLC 的一次性品牌注册 $4.50 和每个用途 $15 的审核费,以及按用途收的月费。按这些价目算,一条单段短信大约 $0.0118~$0.0128,钱主要花在号码、登记和月费上。
| 项 | Twilio | TrueDialog |
|---|---|---|
| 每条短信 | 每段 $0.0083,另加运营商通道费 | 套餐内(小企业版含 5,000 条) |
| 号码 | 美国本地号码 $1.15/月起 | 长号码 $9.99/月 |
| 10DLC | 品牌 $4.50 一次,每个用途 $15 审核,另收月费 | 价格页写明提供自动 10DLC 注册 |
| 最低月费 | 无,按用量 | $119/月,年度合同 |
| 用 MCP 发短信 | 自己的 MCP 只查文档,不能发 | 能发,MCP 不另收费 |
TrueDialog 是按月订阅的套餐制。价格页列了四档:小企业版每月 $119,含 5,000 条,超出每条 $0.024;专业版每月 $425,含 25,000 条;企业版每月 $900,含 60,000 条;定制版每月 $1,000 起,都是年度合同;运营商的通道费另算,长号码每月 $9.99,短号码每月 $799(TrueDialog 价格页,11 月 14 日读)。新闻稿说 MCP 不另收费,所以通过 Claude 发短信的成本就是这些套餐价。按我们的推算,Joe's Pizza 这类门店一个月约 39 条提醒,在小企业版 5,000 条的额度里占不到 1%;已经用 TrueDialog 做营销短信的商家,提醒可以挂在现有账号上。
| 一家店一个月 | 数据接口费 | 短信条数(估算) | 短信费(Twilio,按每条 $0.0128 估) | 号码月租 | 合计(不含 10DLC 登记和月费) |
|---|---|---|---|---|---|
| Joe's Pizza 这类热闹门店,每小时查 | $1.00 | 约 39 | $0.50 | $1.15 | $2.65 |
| DMV 这类窗口,每天查 1 次 | $0.042 | 约 6 | $0.08 | $1.15 | $1.27 |
| DoorDash 这类大应用,两个商店每小时查,逐条发 | $2.00 | 约 2,823 | $36.13 | $1.15 | $39.28 |
表中短信条数按上一节的「每天 1~2 星条数」乘 30 估算,是量级。大应用逐条发,一个月约 2,823 条;改成营业时间每小时最多一条,最多 390 条,短信费按同样单价约 $4.99。
合规:10DLC 注册、退订,以及 11 月 25 日生效的 FCC 新规
在美国用普通 10 位号码(行业里叫 10DLC)给手机发应用程序产生的短信,要先在 The Campaign Registry 登记品牌和用途。Twilio 的帮助中心列的费用是:低量标准品牌注册一次性 $4.50,每个用途登记的审核费 $15,之后还有按用途收的月费(Twilio 帮助中心:A2P 10DLC 费用)。TrueDialog 的价格页写明它有自动 10DLC 注册,团队会协助完成 10DLC 和短号码的登记(TrueDialog 价格页)。
退订是第二件事。美国无线通信行业协会 CTIA 的《消息原则与最佳实践》把「STOP」定为标准的退订关键词,要求发送方支持多种退订方式(CTIA Messaging Principles and Best Practices,2023 年 5 月版)。TrueDialog 的新闻稿写退订会被自动执行(PR Newswire 新闻稿)。
第三件事是美国联邦通信委员会(FCC)刚改过的撤回同意规则。FCC 在 2026 年 9 月 30 日通过了修订(据 Kelley Drye 的解读,原文见下文联邦公报),联邦公报 2026 年 10 月 26 日刊出,生效日期是 2026 年 11 月 25 日(Federal Register 2026-21821)。公报摘要写了三点:发送方可以把一次撤回理解为只针对它所指向的那一类信息性消息;发送方可以指定一种专门的撤回方式;金融机构发欺诈提醒的豁免条件放宽。FCC 9 月 9 日公布的情况说明也在网上(FCC 情况说明 PDF)。这些条文涉及「收件人怎么退订、退订后哪些消息必须停」,具体到你的业务适用哪一条,请找律师确认;我们只把规则原文和日期摆出来。
| 事项 | 要做什么 | 费用或日期 | 出处 |
|---|---|---|---|
| 10DLC 品牌登记 | 在 The Campaign Registry 登记发送方品牌 | 低量标准品牌一次性 $4.50 | Twilio 帮助中心 |
| 用途登记审核 | 每个用途审核一次 | 每个 $15,之后按用途收月费 | Twilio 帮助中心 |
| 最短计费期 | 用途登记按 3 个月起付(政治类除外) | 页面 2026-09-16 更新 | Bandwidth 支持中心 |
| 退订关键词 | 支持 STOP,并接受多种退订方式 | 不涉及费用 | CTIA 2023 年 5 月版 |
| FCC 撤回同意新规 | 对照退订范围和指定退订方式 | 2026-10-26 刊登,2026-11-25 生效 | 联邦公报 2026-21821 |
短信里写什么:160 个字符,别把评论原文整段转发
美国的普通短信按 160 个字符一段计费,超过就拆成两段、付两段的钱(Twilio 美国价格页的常见问题写明按段计费,Twilio 美国短信价格)。Twilio 的字符上限说明写明,消息里只要出现一个表情符号、一个汉字或者一个「智能引号」这类 GSM-7 以外的字符,整条就改用 UCS-2 编码,一段只能放 70 个字符(Twilio:How long can a message be?)。所以提醒里只放三样:几星、哪个地点或应用、一条能点开的链接,全部用英文和 ASCII 字符,上面脚本的模板就是这样写的。
| 放进短信 | 示例 | 字符数 | 说明 |
|---|---|---|---|
| 星级 | 1-star | 6 | 用英文写;星形符号「★」不在 GSM-7 里,会让整条变成 UCS-2,一段只剩 70 个字符 |
| 地点或应用 | LA DMV Hope St | 14 | 用内部简称,不写评论者名字 |
| 链接 | https://example.com/r/2ff3c3 | 28 | 指向自己的系统,打开后再看全文 |
| 合计(单条,含分隔符) | 1-star review: LA DMV Hope St https://example.com/r/2ff3c3 | 58 | 一段 160 个字符以内,按一段计费 |
| 合计(每小时汇总) | 6 new 1-2 star reviews: LA DMV Hope St https://example.com/r/2ff3c3 | 67 | 离线试跑实际打印的那一条 |
| 不放 | 评论原文、员工外貌和窗口号、患者能被认出的细节 | — | 隐私和误伤同事的风险 |
我们在 DMV 的 20 条评论里看到,6 条 1~2 星评论里有 2 条描述了能认出是谁的工作人员(一条写保安,一条写某个窗口号的职员),用词也很重。把这样的原文整段转发到十几个员工的手机上,等于把对某位同事的指控群发了一遍。医疗场景另有先例:美国卫生与公众服务部民权办公室(HHS OCR)公布过诊所在回复网上差评时泄露患者信息的和解案。2023 年 6 月 5 日公布的一起,新泽西一家精神科诊所在回复 Google 差评时披露了四名患者的信息,和解金额 $30,000(HHS:Manasa Health Center 和解;金额见 HHS 2023 年度报告);2022 年 12 月 14 日的一起是牙科诊所在社交媒体回复评论时披露患者信息(HHS:New Vision Dental 和解;全部和解列表见 HHS 决议协议页)。这两起的起因都是回复评论时披露了患者信息。短信提醒本身不是回复评论,具体怎么处理,请按你们机构的隐私制度和法务意见办。
美国联邦贸易委员会(FTC)的《消费者评论和推荐规则》§465.7 禁止用没有依据的法律威胁、恐吓、虚假指控等手段压制评论,也禁止按评论好坏选择性地隐藏(16 CFR Part 465,§465.7 Review suppression;FTC 的问答见 Consumer Reviews and Testimonials Rule Q&A)。
跨领域:社区诊所和公共服务窗口的评价提醒
把同一套做法搬到社区诊所、医院门诊、车管所、社保窗口这类地方,技术上几乎不用改,改的是「谁收短信、短信里写什么、多久看一次」。这里只讲数据方法,不涉及任何医疗判断,也不构成法律或医疗建议。我们用的两个对照样本,一个是洛杉矶 Hope Street 的 DMV 办事处,一个是很多美国医疗机构给患者用的 MyChart 应用。
DMV 这个样本的特点是「评论少、差评多」。11 月 14 日新加坡时间 00:20 那一轮,最新 20 条评论里 1 星 5 条、2 星 1 条,1~2 星占 30%;这 20 条的 posted_at 从 2026 年 10 月 20 日排到 11 月 12 日,平均每天不到 1 条。其中 2026 年 11 月 1 日以来的有 10 条,这 10 条里 5 条只打了分、没写字。这类地点每小时查一次没有意义,每天查一次就能覆盖,钱也只有每天 $0.001389。提醒脚本要能处理空正文:上面的模板不放正文,空正文不会把短信弄乱。
MyChart 这个样本说明了应用评论和地点评论的不同。App Store 一侧 50 条里 1 星 11 条、2 星 4 条,占 30%;Google Play 一侧 40 条里 1 星 10 条、2 星 3 条,占 32.5%。两个商店的应用评论都带正文,Google Play 那 13 条低星评论平均 96 个字符,App Store 的低星评论常带一个标题。我们按关键词粗分了一下 App Store 的 15 条低星(一条可以命中多类):6 条提到消息或预约,2 条提到登录或验证码,2 条提到更新。这种分类适合放进每天的汇总里,交给负责患者体验的人,不适合拆成一条条短信发给一线员工。
公共服务机构做这件事,可以对照两份现成的框架。美国医疗研究与质量局(AHRQ)把 CAHPS 系列调查定义为患者报告的就医体验测量,并在说明页里分开「患者体验」和「患者满意度」两个概念,还专门提到开放式的文字评论对发现安全问题很有用(AHRQ:什么是患者体验;CAHPS 总页见 ahrq.gov/cahps,CMS 的介绍页见 CMS:CAHPS)。联邦政府的服务窗口则有 OMB 通函 A-11 第 280 节,要求被指定的高影响服务提供方部署办完事后的反馈问卷、按季度向 OMB 报告反馈,并把收到的反馈用于改进和「服务补救」(A-11 Section 280 说明)。网上评论和这些问卷不同:它不抽样、不匿名验证,也没有标准题目,所以只适合当「早一点发现问题」的信号,不能拿来替代正式的体验调查。
具体到流程,诊所和窗口可以把提醒分成两档。第一档是短信,只发给值班负责人,内容只有星级、地点和链接,不放评论原文,也不放能推出患者身份或病情的词;第二档是每天一份汇总,按主题(排队、预约、态度、系统故障)分类,交给质量或体验负责人。点名员工的差评先交给主管核实。
| 档 | 发给谁 | 内容 | 频率 |
|---|---|---|---|
| 第一档:短信 | 当班负责人一人 | 星级、地点、链接;不放原文和能推出患者身份的词 | 新的 1~2 星评论出现后,下一次检查时发 |
| 第二档:每日汇总 | 质量或患者体验负责人 | 按排队、预约、态度、系统故障分类的条数和摘要 | 每天一次 |
| 点名员工的差评 | 主管 | 原文和链接,不进群发 | 出现时 |
用 MCP 把两边接起来(配置示例)
只要定时脚本就能跑完整个流程;接 AI 助手的价值在于「看懂差评、写一句给店主的摘要、决定要不要升级给区域经理」。下面是在 Claude 里同时接两个远程 MCP 服务器的做法:EveryInfra 负责查能力、对账和读脚本整理好的新评论,TrueDialog 负责发短信。EveryInfra 一侧我们真调过 tools/list 和 tools/call;TrueDialog 一侧我们没有账号,按 tdmcp.com 和 Claude 帮助中心的原文写成配置示例。
在 Claude 桌面应用或 claude.ai 里,按 Claude 帮助中心的说明打开「自定义连接器」,填名称和地址就能添加远程 MCP 服务器;连接从 Anthropic 的云端发起,所以服务器必须能从公网访问(Claude 帮助中心:自定义连接器)。TrueDialog 填 https://connect.tdmcp.com/,点连接后在浏览器里登录 TrueDialog;EveryInfra 填 https://api.everyinfra.com/mcp,按 MCP 接入页 带上自己的 Key。在 Claude Code 里,远程 HTTP 服务器用 claude mcp add --transport http 添加(Claude Code MCP 文档),定时跑可以用非交互的 claude -p(Claude Code 编程方式运行)。
{
"mcpServers": {
"everyinfra": {
"type": "http",
"url": "https://api.everyinfra.com/mcp",
"headers": { "Authorization": "Bearer ${EVERYINFRA_API_KEY}" }
},
"truedialog": {
"type": "http",
"url": "https://connect.tdmcp.com/"
}
}
}我们在新加坡时间 00:29 真调了 EveryInfra 的 tools/list:返回 12 个工具,读评论用的是 everyinfra_call_api,它的注解是 readOnlyHint: false、destructiveHint: true、openWorldHint: true,因为它会扣费;everyinfra_list_capabilities、everyinfra_get_job、everyinfra_list_requests 都标为只读。everyinfra_call_api 的参数是 platform、action、params、mode 四个。每小时跑的定时任务交给上面的脚本走 REST 带 Idempotency-Key,AI 助手只读脚本整理好的新评论、写摘要、决定要不要升级。00:35 和 00:36 我们经 MCP 调了两次 google_play/reviews:第一次把 MyChart 的包名写成 com.epic.mychart.android,返回 0 条,没有扣费,原因 empty_result_refunded;改成正确的 epic.mychart.android 后返回 40 条,扣 $0.001389。
| 工具 | 来自 | 只读 | 在这套提醒里做什么 |
|---|---|---|---|
everyinfra_list_capabilities | EveryInfra | 是 | 查能力、参数和价格,不扣费 |
everyinfra_call_api | EveryInfra | 否(会扣费) | 临时查一个地点;每小时的定时任务走 REST 带 Idempotency-Key |
everyinfra_list_requests | EveryInfra | 是 | 对账:看哪次调用扣了费 |
send_sms | TrueDialog | 否(会发短信) | 发提醒;execute=false 只试运行(配置示例,未实测) |
每天 9:00–21:00 每小时运行一次:
1. 读 review_alert.db 里 outbox 表状态为 pending 的新差评(由定时脚本写入)。
2. 每个来源合成一条英文短信,不超过 60 个字符,不写评论者名字、不写员工外貌和窗口号,只用 ASCII 字符。
3. 先用 truedialog 的 send_sms,execute=false 试运行一遍,把将要发的内容列给我看;我回复「发」再 execute=true。
4. 同一来源同一小时只发一条。第 3 步的「先试运行、人确认再发」对应连接器页那句「send_sms 默认真发」。TrueDialog 新闻稿说开发者可以只给代理只读工具;如果你要无人值守地每小时发,就要接受由代理直接调用 send_sms,这时收件人名单要固定写在提示里,不让模型自己去搜联系人。
和站内另外几篇的区别
站内另外几篇没有写短信渠道和每小时的成本:BL-88 写的是三家小店用 Claude Duet 每天早上出一份差评早报,结论是小店近 90 天只有 4~8 天有新评论,所以每天看一次就够。BL-79 写的是 Claude Managed Agents 每晚巡检 Google、Yelp、Tripadvisor 三个平台,发现过一条 posted_at 早于上一轮调用、上一轮却没有返回的评论,说明只按时间判新会漏。BL-70 比较了抓 Google 地图评论的几条路,包括 Places API 5 条的上限。BL-115 把幂等键的各种重试情形测全了。工具选择的另一面见 数据接口和工具路由。
行业动向
| 日期 | 事件 | 对差评短信提醒的影响 | 出处 |
|---|---|---|---|
| 2026-11-10 | TrueDialog 发布 TrueDialog MCP | 在助手里加连接器就能发短信;号码注册和退订仍要在短信平台办 | PR Newswire |
| 2026-10-28 | TikTok 推出餐厅指南 Must Eat | 餐厅多了一个要盯的评论来源 | TikTok |
| 2026-10-26 | FCC 撤回同意新规刊登,2026-11-25 生效 | 退订流程要对照新规再看一遍 | 联邦公报 |
| 2026-09-16 | Bandwidth 更新 10DLC 费用页 | 短信用途登记按 3 个月起付 | Bandwidth |
| 2026-07-28 | MCP 规范发布新版本 | 远程 MCP 服务器更接近无状态接口 | MCP 更新日志 |
2026 年 10 月 28 日,TikTok 在纽约、洛杉矶和旧金山湾区推出餐厅指南 Must Eat,用户可以在应用里给餐厅打分写评论(TikTok 官方介绍;The Verge 报道)。餐厅要盯的评论来源又多了一个,提醒脚本的 SOURCES 表要留出扩展的位置。
MCP 规范在 2026 年 7 月 28 日发布了新版本,去掉了会话和初始化握手,远程服务器更接近无状态的普通接口(MCP 规范更新日志;GitHub 发布页)。tdmcp.com 把自己描述为无状态、不保存凭据的转接层,和这次规范的方向一致。
边界:做不到或要注意的
| 限制 | 影响 | 怎么办 |
|---|---|---|
| 短信只证明发出 | 不知道负责人看没看到 | 让负责人回复关键词,用短信平台的回调记下来 |
| App Store「最新」列表本身有延迟 | 应用商店的差评要一天多以后才出现在列表里 | 应用评论每天查一次 |
since=当天 会漏晚到的评论 | 昨天写、今天才出现的评论被过滤 | since 设成昨天,按评论 ID 去重 |
| 样本小、时段短 | 每天几条短信只是量级 | 先用 DRY_RUN=1 跑一周 |
样本小,结论有边界。我们只测了 2 个地点和 2 个应用(外加 MyChart 一轮对照),跨了约 3 个小时,正好是美国东部的上午到中午。新评论的速度和差评占比会随店、随时段、随促销和事故变化,文中的每天几条短信只能当量级参考。要给自己的店定频率,先用 DRY_RUN=1 跑一周,看待发表每天进几条。
常见问题
Claude 能直接发短信吗?SMS MCP 怎么接?
Claude 本身不发短信,要接一个能发短信的 MCP 服务器。按 tdmcp.com 的说明,在 Claude 的「自定义连接器」里填 https://connect.tdmcp.com/ 并登录 TrueDialog 账号即可;Twilio 自己的 MCP 只能查文档,发不了短信。问题来自 Google 联想词「claude sms mcp」(Google 联想词,2026 年 11 月 14 日读)。
Google 商家资料自带新评论通知,还需要 review alert sms 吗?
自己认领的店可以先用 Google 的邮件和地图应用通知,或用 Pub/Sub 推送自建提醒;需要短信、需要合并多家店、需要盯不归自己账号管的地点时,才需要轮询加短信。问题来自 Google 联想词「google business review notifications」(11 月 14 日读)。
收到一条写着 review alert 的短信,怎么分辨是不是诈骗?
自建的提醒应该固定从一个登记过的号码发出,内容只有星级、地点和一条指向你们自己系统的链接,从不要求登录密码或付款。陌生号码发来「你有新差评,点此登录处理」之类的短信,按钓鱼处理。问题来自 Google 联想词「review alert sms scam」(11 月 14 日读)。
App Store Connect 有没有新评论通知?
按 App Store Connect 帮助页的通知清单,没有。和评论有关的只有「Developer Response」:你回复过的评论被用户修改时发邮件。新评论要靠轮询 Customer Reviews 接口或评论数据。问题来自 Google 联想词「app store connect review notifications」(11 月 14 日读)。
店主回短信,能自动回复那条评论吗?
用 TrueDialog MCP 做不到:微软 Learn 连接器页的已知限制第一条就是只发不收,读不到回复和会话。要做这件事,得用短信平台的入站回调把回复接回自己的系统,再由人或程序去平台上回复评论。问题来自 Google 联想词「review alert sms auto reply」(11 月 14 日读)。
能监测不是自己商户的 Google 评论吗?
Google 的官方通知和 Business Profile API 只对你管理的商户开放,Reddit r/smallbusiness 的讨论帖里回帖也是这个结论。公开地点的评论可以用 google_maps_reviews/reviews 读,按评论 ID 去重后自己做提醒。问题来自 Reddit r/smallbusiness 帖子。
上手步骤
第一步,在 EveryInfra 控制台建一把 API Key,放进环境变量 EVERYINFRA_API_KEY;免费目录 GET /api/v1/social/catalog 列着每项能力的参数、允许值和 price_usd,按 快速上手 跑通第一条请求。第二步,用 google_maps_reviews/search 找到要盯的地点,复制返回里带 query_place_id 的网址;应用就记下 App Store 的数字 ID 和 Google Play 的包名,各平台能力见 Google 地图评论接口、App Store 接口、Google Play 接口,Yelp 商户可以加 yelp/reviews。第三步,把上面的脚本放进 cron,DRY_RUN=1 先跑一周,看待发表里每天进几条。第四步,再接短信:把 send_sms() 换成 Twilio 的 Messages 接口,或者用 TrueDialog 的 MCP 或接口,先试运行、再真发。价格按 价格页 和目录为准,失败和空结果不扣费的对账方法见 失败退款对账。
参考资料
- Model Context Protocol, Specification 2026-07-28,2026-11-14 读取
- TrueDialog MCP, tdmcp.com (setup, tools, security),2026-11-14 读取
- PR Newswire, TrueDialog Launches MCP for ChatGPT, Copilot and Other AI Assistants, 2026-11-10,2026-11-14 读取
- TrueDialog, MCP feature page,2026-11-14 读取
- Twilio Blog, Introducing Twilio MCP and skills, 2026-05-07,2026-11-14 读取
- Twilio Docs, Twilio MCP server,2026-11-14 读取
- GitHub, twilio-labs/mcp,2026-11-14 读取
- npm registry, @twilio-alpha/mcp,2026-11-14 读取
- Microsoft Learn, TrueDialog MCP connector,2026-11-14 读取
- Google Business Profile Help, manage notifications,2026-11-14 读取
- Google for Developers, Business Profile real-time notifications setup,2026-11-14 读取
- Google for Developers, My Business Notifications API: NotificationSetting,2026-11-14 读取
- Google for Developers, Business Profile review data,2026-11-14 读取
- Apple, App Store Connect Help: user notifications,2026-11-14 读取
- Apple Developer Documentation, App Store Connect API: Customer Reviews,2026-11-14 读取
- Google for Developers, Google Play Developer API: Reply to Reviews,2026-11-14 读取
- Reddit r/smallbusiness, Google reviews monitoring thread,2026-11-14 读取
- Google for Developers, Places API Place Details,2026-11-14 读取
- EveryInfra, llms-full.txt (Retries and idempotency),2026-11-14 读取
- EveryInfra, OpenAPI specification,2026-11-14 读取
- Twilio Docs, Message resource,2026-11-14 读取
- Twilio, SMS pricing for the United States,2026-11-14 读取
- Twilio, phone number pricing,2026-11-14 读取
- TrueDialog, pricing,2026-11-14 读取
- Twilio Help Center, A2P 10DLC pricing and fees,2026-11-14 读取
- CTIA, Messaging Principles and Best Practices, May 2023 (PDF),2026-11-14 读取
- Kelley Drye, FCC revises TCPA consent revocation rules,2026-11-14 读取
- Federal Register 2026-21821, consent revocation rule, published 2026-10-26,2026-11-14 读取
- FCC, fact sheet DOC-424844A1, 2026-09-09 (PDF),2026-11-14 读取
- Bandwidth Support, 10DLC fees (updated 2026-09-16),2026-11-14 读取
- Twilio Docs, How long can a message be?,2026-11-14 读取
- HHS OCR, Manasa Health Center settlement, 2023-06-05,2026-11-14 读取
- HHS OCR, 2023 report to Congress on HIPAA compliance (PDF),2026-11-14 读取
- HHS OCR, New Vision Dental settlement, 2022-12-14,2026-11-14 读取
- HHS OCR, resolution agreements,2026-11-14 读取
- eCFR, 16 CFR Part 465 (Consumer Reviews and Testimonials),2026-11-14 读取
- FTC, Consumer Reviews and Testimonials Rule: Q&A,2026-11-14 读取
- AHRQ, What Is Patient Experience?,2026-11-14 读取
- AHRQ, CAHPS,2026-11-14 读取
- CMS, Consumer Assessment of Healthcare Providers & Systems,2026-11-14 读取
- Performance.gov, A-11 Section 280 explainer,2026-11-14 读取
- Claude Help Center, custom connectors using remote MCP,2026-11-14 读取
- Claude Code Docs, MCP,2026-11-14 读取
- Claude Code Docs, run Claude Code programmatically,2026-11-14 读取
- TikTok, Must Eat announcement, 2026-10-28,2026-11-14 读取
- The Verge, TikTok Must Eat restaurant guide,2026-11-14 读取
- Model Context Protocol, specification changelog,2026-11-14 读取
- GitHub, modelcontextprotocol releases,2026-11-14 读取
引用编号 BL-146