关于 Easy!Appointments
Easy!Appointments MCP 服务让预约系统运营人员通过 AI 助手查询服务、客户和空闲时段,并管理预约。OAuth 登录、按连接设置只读或前台权限,所有更改均需先预览再确认。
主要功能
- 01查询服务、客户和预约
- 02按服务及时间筛选空闲时段
- 03创建、改期和取消预约
- 04按连接授予只读或前台权限
- 05更改需预览、签名令牌和幂等键
- 06记录并导出脱敏调用日志
适用场景
- 01为客户查找合适的预约时段
- 02登记新预约或调整现有预约
- 03查看客户的预约记录
- 04审查并导出前台操作日志
MCP 相关
作为远程 MCP 服务,通过 OAuth 向 AI 客户端提供 Easy!Appointments 查询和预约管理工具。写入操作须以同一人员和客户端提交匹配预览的确认令牌。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://ea-mcp-demo.qiyuanlabs.ai/mcpclaude mcp add --transport http ai-qiyuanlabs-easyappointments https://ea-mcp-demo.qiyuanlabs.ai/mcp{"mcpServers":{"ai-qiyuanlabs-easyappointments":{"type":"http","url":"https://ea-mcp-demo.qiyuanlabs.ai/mcp"}}}在 Cursor 中打开{"servers":{"ai-qiyuanlabs-easyappointments":{"type":"http","url":"https://ea-mcp-demo.qiyuanlabs.ai/mcp"}}}在 VS Code 中打开{"mcpServers":{"ai-qiyuanlabs-easyappointments":{"type":"http","url":"https://ea-mcp-demo.qiyuanlabs.ai/mcp"}}}{"mcpServers":{"ai-qiyuanlabs-easyappointments":{"serverUrl":"https://ea-mcp-demo.qiyuanlabs.ai/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
Easy!Appointments MCP 服务
一个远程 MCP 服务,可让 Claude、ChatGPT 和其他 AI 助手为 Easy!Appointments 预约系统处理前台事务:查找空闲时段、查询客户,以及预约、改期或取消预约。
它面向运营预约系统的人员,而不仅仅是开发者:
- 使用 OAuth 登录。 员工使用自己的账号将 AI 助手连接到系统。Easy!Appointments API 令牌不会离开服务器。
- 每个连接有两个访问级别。 只读权限可以查看服务、空闲时段、客户和预约。前台权限还可以预约、改期和取消。管理员会为每个人设置权限上限。
- 未经预览,不会进行任何更改。 每项更改都需要两步调用:先预览,由助手展示给用户;然后确认调用,并附带预览的签名
confirmation_token和幂等键。与预览不匹配的确认会被拒绝,重试请求也绝不会重复预约。 - 调用日志。 每次工具调用都会记录,并屏蔽个人详细信息,同时记录发出的 Easy!Appointments 请求和耗时。员工可以查看日志、将其导出为 CSV,并断开任何助手的连接。
- 避免给 Easy!Appointments 增加负担。 API 每两分钟允许来自每个 IP 的 100 次请求。该服务会缓存目录和空闲时段,限制单次搜索涵盖的天数,并为每个预约系统共用一个请求预算(
EA_REQUEST_BUDGET,默认为每两分钟 90 次),避免多个助手合计请求过多,导致系统被锁定。
本项目与 Easy!Appointments 无关联,也未获其认可。Easy!Appointments 是其所有者的商标。
工具
| 工具 | 访问权限 | 功能 |
|---|---|---|
list_services | 只读 | 查看服务的时长、价格和提供服务的人员,以及每位服务提供者的时区 |
find_open_slots | 只读 | 查找某项服务未来最多 14 天内的可预约开始时间,可指定一位或所有服务提供者,并按上午、下午或晚上筛选 |
find_customer | 只读 | 按姓名、电子邮件或电话号码查找客户 |
list_appointments | 只读 | 查看某位客户、某位服务提供者或某个日期范围内的预约 |
book_appointment | 前台 | 为现有客户或新客户预约 |
reschedule_appointment | 前台 | 将预约改到新的时间或服务提供者 |
cancel_appointment | 前台 | 取消未来的预约 |
通过 API 进行的每项更改,Easy!Appointments 都会照常发送确认、更改和取消邮件。
要求
- Easy!Appointments 1.5 或更高版本,并启用 API(Settings > Integrations > API:设置 API 令牌)。已在 1.6.1 上测试。
- PHP 8.3 或更高版本,或 Docker。
- 生产环境中使用 HTTPS。AI 客户端不会连接互联网上的纯 HTTP 服务器。
在本地运行演示
compose 文件会启动 Easy!Appointments 1.6.1、邮件接收器和此服务,然后为一家虚构的理疗诊所填充服务、服务提供者、客户和两周的预约数据。
cp .env.docker.example .env.docker
# Set APP_KEY (see the comment in the file) and EA_API_TOKEN (any long random string)
docker compose up -d --build
sh demo/setup.sh
然后:
- MCP 服务:http://localhost:8000/mcp(使用
[email protected]/demo-password-1登录) - Easy!Appointments:http://localhost:8080(`administrator` /
administrator) - Easy!Appointments 发送的邮件:http://localhost:8025
若要在没有 AI 客户端的情况下检查完整流程,请运行端到端脚本。该脚本会注册 OAuth 客户端、登录、选择访问级别并调用每个工具,其中包括实际创建一项预约,然后将其改期并取消:
php demo/e2e.php http://localhost:8000 [email protected] demo-password-1 front_desk
php demo/e2e.php http://localhost:8000 [email protected] demo-password-1 read
若要通过 HTTPS 将演示部署到公共服务器,请参阅 docs/deploy-demo.md。
为实际预约系统安装
使用 Docker:
docker run -d --name ea-mcp \
-e APP_KEY=base64:... \
-e APP_URL=https://mcp.example.com \
-e TRUSTED_PROXIES=10.0.0.5 \
-v ea-mcp-data:/data/app \
-p 127.0.0.1:8080:8080 \
ea-mcp-server
将其置于 HTTPS 负载均衡器或反向代理之后,或者设置 SERVER_NAME=mcp.example.com 并发布 80 和 443 端口,让内置 Caddy 获取证书。
TRUSTED_PROXIES 决定信任谁提供的 X-Forwarded-For 标头,速率限制按客户端 IP 计算。仅将其设为代理的地址,并且只将 8080 端口发布给该代理(如果代理运行在同一主机上,则发布给 127.0.0.1)。如果端口可被直接访问,切勿使用 *,否则任何人都可以指定自己的 IP,绕过速率限制。由内置 Caddy 处理 HTTPS 时,请勿设置此项。在第二个容器中使用同一镜像运行 php artisan schedule:work,以便每天清理旧日志和过期令牌。
不使用 Docker 时,它是一个标准的 Laravel 13 应用:运行 composer install --no-dev,将 .env.example 复制为 .env,运行 php artisan key:generate、php artisan passport:keys 和 php artisan migrate,并将 Web 服务器指向 public/。
然后连接预约系统并添加员工:
php artisan ea:connect "Maple Street Physio" https://booking.example.com # asks for the API token
php artisan ea:user [email protected] --name="Anna" --level=front_desk # asks for a password
--level 是此人可以授予助手的最高级别。每位助手的具体级别仍由他们在授权页面上选择。
如果 ea:connect 使用有效令牌却收到 401,说明 Web 服务器没有将 Authorization 标头传递给 PHP。使用 PHP-FPM 的 Apache 环境中,请在 Easy!Appointments 虚拟主机配置中添加 SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1。
连接 AI 助手
将 https://your-server/mcp 添加为自定义连接器(Claude:Settings > Connectors;ChatGPT:在开发者模式下添加工作区连接器)。客户端会自行注册、打开登录页面,然后由用户选择 只读 或 前台。用户可以随时在 /dashboard 上更改或移除此设置。
安全模型
- Easy!Appointments API 令牌具有管理员级别权限,因此会加密存储在此服务器上,绝不会发送给客户端。每个人都使用自己的账户登录,并获得一个仅在此处有效的短期令牌(有效期为 1 小时,可刷新,最长 30 天)。
- 登录前,
initialize和tools/list无需令牌即可响应,以便客户端显示此服务提供的内容。没有有效令牌的任何tools/call(以及其他所有请求)都会收到带有WWW-Authenticate标头的401响应,该标头指向 OAuth 元数据,这会在 Claude 和其他客户端中启动登录流程。登录后,连接无法使用的工具不会列出;即使调用,也会被拒绝。 - 写入操作需要通过第二次调用确认。确认请求必须携带针对完全相同参数的预览所返回的
confirmation_token,并且由同一人和助手在 10 分钟内(MCP_CONFIRMATION_MINUTES)发起,同时还必须提供幂等键。该键会在写入任何内容之前被占用,因此使用同一个键并行重试只会预订一次。 - Easy!Appointments 在 API 创建或移动预订时不会检查可用性。因此,每次确认都会锁定该服务提供者当天的时段,在锁内重新检查未经缓存的时段,之后才进行写入。使用不同键确认同一时段的两次请求中,只有一次会完成预订;另一请求会被拒绝,并返回最近的空闲时段。
- 如果 Easy!Appointments 的响应丢失,或返回服务器错误,该键仍会保持占用状态,并会告知助手改用
list_appointments检查,而不是盲目重试。一旦 Easy!Appointments 确认写入成功,此后发生的任何事情(例如读取姓名)都无法将其转为错误或撤销操作。 - 时间会按照每位服务提供者自己的时区读取和写入,与 Easy!Appointments 中的存储方式一致;每个结果都会说明使用的时区。
- 客户端注册开放,符合 MCP 的预期,但受到限制:重定向 URI 必须使用
https(或回环地址上的http),且不得包含片段或用户信息;客户端注册按 IP 限流(MCP_REGISTRATIONS_PER_HOUR,每小时 10 次);从未使用的客户端会在一天后删除,已使用过但连续 90 天未使用的客户端也会删除。 - 同意页面会将客户端名称标记为未经验证(任何应用都可以自行选择名称),显示此人将被发送到的主机,并在该主机不是已知 AI 助手时发出警告(
MCP_KNOWN_CLIENT_HOSTS)。 - 调用日志中的姓名、电子邮件、电话号码、地址、备注和搜索文本都会被屏蔽。Easy!Appointments 错误消息中回显客户记录的内容会被移除,错误中残留的任何电子邮件地址也会被屏蔽,然后才会显示给助手、写入调用日志或应用日志。
- 登录尝试按 IP 限流,并对每个账户单独限流,因此即使通过多个 IP 分散猜测,也仍会触发限制(
MCP_LOGIN_ATTEMPTS_PER_ACCOUNT,每 10 分钟 10 次)。DEMO_EMAIL中设置的公开演示账户不受账户级限制,因为其密码已公开,限制只会让陌生人锁定该账户。只要APP_URL使用 https,会话 Cookie 就仅限 HTTPS 使用。 - 为新客户创建预订时,会在开始前为所有请求预留额度;如果 Easy!Appointments 随后明确拒绝预订(返回 4xx),则会删除创建的客户。若未收到响应或发生服务器错误,预订可能已经存在,因此客户会保留,并会告知助手使用
list_appointments检查。 .env.example中设置了APP_ENV=production和APP_DEBUG=false。ea:connect会通过提示输入或从EA_API_TOKEN读取 API 令牌,因此令牌不会出现在 Shell 历史记录或进程列表中。- 默认保留日志 90 天(
MCP_LOG_RETENTION_DAYS)。
已知限制
- Easy!Appointments API 无法在忽略正在移动的预约的情况下检查可用时间,因此,如果改期后的时间与预约当前时间重叠,系统会拒绝操作并说明原因。遇到这种情况,请先取消再重新预约。
- 在 Easy!Appointments 中取消预约会将其删除;API 不支持软取消。
- 时段锁仅覆盖通过此服务进行的更改。如果有人同时直接在 Easy!Appointments 中预约同一时段,仍可能导致重复预约,因为其 API 无法预留时段。
- Easy!Appointments 不会存储请求所用的时区,因此,提供者的时区日后发生变化时,其现有预约仍会保持在相同的本地时钟时间。
- 一个服务可以关联多个 Easy!Appointments 实例,每个账户对应一个实例。没有自助注册功能;管理员可以使用
ea:user添加人员。
开发
composer install
cp .env.example .env && sed -i 's/^APP_ENV=production/APP_ENV=local/' .env
php artisan key:generate && php artisan passport:keys && php artisan migrate
php artisan test
vendor/bin/pint
测试使用 Easy!Appointments API 的内存模拟实现(tests/Support/FakeEasyAppointments.php)。demo/e2e.php 使用真实实例运行。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。