关于 tebra
tebra-mcp-server 将 Tebra 诊所管理账户连接到兼容 MCP 的 AI Agent,提供 SOAP 业务操作及可选的 FHIR 临床数据访问,适用于使用 Tebra 的诊所。需要有效 API 凭据,临床结果可能包含受保护的健康信息。
主要功能
- 01管理患者记录和预约
- 02处理就诊、费用和付款
- 03访问保险与授权信息
- 04上传和删除患者文档
- 05配置后读取 FHIR 临床数据
- 06验证连接并查看 API 限流
适用场景
- 01在诊所工作流程中搜索患者记录
- 02安排或修改预约
- 03创建就诊记录并推进账单状态
- 04启用 FHIR 后查看患者用药或检验结果
MCP 相关
向 MCP 客户端开放 Tebra SOAP 操作,以及单独配置后可用的 FHIR R4 临床数据工具。服务需要 Tebra 凭据;FHIR 工具还需要额外的 FHIR 凭据。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
33收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| mrn | string | 否 | 病历号 |
| query | string | 否 | 按全名搜索(向后兼容的 fullName 别名) |
| gender | enum | 否 | 按性别筛选Male | Female | Other | Unknown |
| fullName | string | 否 | 按全名搜索 |
| isActive | boolean | 否 | 按启用/停用状态筛选 |
| lastName | string | 否 | 按姓氏筛选 |
| firstName | string | 否 | 按名字筛选 |
| externalId | string | 否 | 外部系统 ID |
| dateOfBirth | string | 否 | 出生日期(YYYY-MM-DD) |
| practiceName | string | 否 | 诊所名称筛选 |
| toCreatedDate | string | 否 | 创建日期范围结束(YYYY-MM-DD) |
| toDateOfBirth | string | 否 | 出生日期范围结束(YYYY-MM-DD) |
| fromCreatedDate | string | 否 | 创建日期范围开始(YYYY-MM-DD) |
| fromDateOfBirth | string | 否 | 出生日期范围开始(YYYY-MM-DD) |
| toLastModifiedDate | string | 否 | 修改日期范围结束(YYYY-MM-DD) |
| fromLastModifiedDate | string | 否 | 修改日期范围开始(YYYY-MM-DD) |
| insuranceCompanyName | string | 否 | 保险公司名称筛选 |
| referringProviderName | string | 否 | 转诊医生姓名筛选 |
详细介绍
tebra-mcp-server
用于 Tebra(前身为 Kareo)诊所管理的 MCP 服务。它将现有的 Tebra 账户连接到 Claude 和其他兼容 MCP 的 AI Agent,提供 34 个 SOAP 工具和 13 个 FHIR 临床工具,用于处理患者、就诊、预约、账单、文档、保险和临床数据。每个请求正文都根据实时 Tebra WSDL 契约生成(成员名称和顺序已对照 KareoServices.svc?xsd=xsd0/xsd7 验证),并通过回归测试套件固定线缆格式。没有有效的 Tebra API 凭据,无法访问任何数据。
这是一个独立的开源项目,与 Tebra Technologies, Inc. 无关联、未获其认可或支持;“Tebra”和“Kareo”是其所有者的商标,在此仅用于标识本服务所连接的 API。工具结果包含受保护的健康信息:将其发送给 Claude 需要使用 Anthropic 会签署业务伙伴协议(BAA)的 Claude 计划。消费者版 Claude 计划不在覆盖范围内;确认计划是否符合要求是运营该服务的诊所的责任。
提供托管版本
不想自行管理凭据、托管和更新?DOCK 是此服务的托管版本:按诊所加密身份验证、审计日志、优先生成草稿的写入操作,以及工作流库。创始诊所可锁定终身价格:前台 $49/月(Zenoti)、账单管理 $99/月(Tebra;DOCK 会与诊所单独签署自己的 BAA,与 Anthropic 的 BAA 分开)、全诊所 $129/月(两者均包含)。https://dockhq.vercel.app
快速开始
npx tebra-mcp-server
前提条件
- Node.js 18+
- Tebra SOAP API 凭据(在 Tebra PM 管理后台的 Settings > API 中生成)
- (可选)用于访问临床数据的 Tebra FHIR API 凭据
环境变量
SOAP API(必需)
| 变量 | 必需 | 说明 |
|---|---|---|
TEBRA_SOAP_USER | 是 | SOAP API 用户(电子邮件) |
TEBRA_SOAP_PASSWORD | 是 | SOAP API 密码 |
TEBRA_CUSTOMER_KEY | 是 | 来自 Tebra PM 管理后台的客户密钥 |
TEBRA_SOAP_ENDPOINT | 否 | 覆盖 SOAP 端点(用于测试) |
FHIR API(可选——启用 13 个临床数据工具)
| 变量 | 必填 | 描述 |
|---|---|---|
TEBRA_FHIR_CLIENT_ID | 用于 FHIR | 从 Tebra appSphere 注册信息中获取的 OAuth2 客户端 ID |
TEBRA_FHIR_PRIVATE_KEY_PATH | 用于 FHIR(JWKS 注册) | SMART Backend Services private_key_jwt 所用 PEM(PKCS#8)私钥的路径;其公钥部分即为你向 Tebra 注册的 JWKS。优先于密钥 |
TEBRA_FHIR_KID | 与密钥路径一同使用 | 已发布 JWKS 中该公钥的 kid(设置密钥路径时必填) |
TEBRA_FHIR_CLIENT_SECRET | 用于 FHIR(密钥注册) | OAuth2 客户端密钥——仅在未设置密钥路径时使用的备用方式 |
TEBRA_FHIR_BASE_URL | 否 | FHIR R4 基础 URL(默认为 https://fhir.prd.cloud.tebra.com/fhir-request) |
TEBRA_FHIR_TOKEN_URL | 否 | OAuth2 令牌端点(默认为 Tebra 生产环境) |
TEBRA_FHIR_SCOPE | 否 | OAuth2 作用域(默认为 system/*.read;需与 appSphere 注册信息一致) |
FHIR 凭据通过 Tebra appSphere 获取。服务使用 OAuth2 客户端凭据流,并自动缓存令牌、在令牌过期前 60 秒刷新,以及在收到 401 时进行一次重试。支持两种客户端身份验证方式:SMART Backend Services private_key_jwt(在 appSphere 中注册为“Confidential (URL for JWKS)”的 Backend App——服务使用 RS384 对客户端断言进行签名,其中 iss=sub=客户端 ID、aud=令牌 URL、exp 为 5 分钟后,且包含唯一的 jti;断言通过 client_assertion 发送,client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer;私钥只从磁盘读取一次,绝不会传输)和旧版 client_secret 流。使用前者时设置密钥路径,使用后者时设置密钥。注意:Tebra Customer Care 必须先激活诊所和后端服务客户端,才会签发令牌——401 可能表示“尚未激活”,而不是“凭据错误”。
安装
Claude Code
将以下内容添加到项目根目录中的 .mcp.json:
{
"mcpServers": {
"tebra": {
"command": "npx",
"args": ["-y", "tebra-mcp-server"],
"env": {
"TEBRA_SOAP_USER": "[email protected]",
"TEBRA_SOAP_PASSWORD": "your-password",
"TEBRA_CUSTOMER_KEY": "your-customer-key",
"TEBRA_FHIR_CLIENT_ID": "optional-fhir-client-id",
"TEBRA_FHIR_CLIENT_SECRET": "optional-fhir-client-secret"
}
}
}
}
Claude Desktop
将以下内容添加到 claude_desktop_config.json:
{
"mcpServers": {
"tebra": {
"command": "npx",
"args": ["-y", "tebra-mcp-server"],
"env": {
"TEBRA_SOAP_USER": "[email protected]",
"TEBRA_SOAP_PASSWORD": "your-password",
"TEBRA_CUSTOMER_KEY": "your-customer-key"
}
}
}
}
Cursor / VS Code
将以下内容添加到 MCP 设置中:
{
"mcpServers": {
"tebra": {
"command": "npx",
"args": ["-y", "tebra-mcp-server"],
"env": {
"TEBRA_SOAP_USER": "[email protected]",
"TEBRA_SOAP_PASSWORD": "your-password",
"TEBRA_CUSTOMER_KEY": "your-customer-key"
}
}
}
}
可用工具(共 47 个)
患者管理
| 工具 | 描述 |
|---|---|
tebra_search_patients | 按姓名、出生日期范围、保险、诊所等搜索患者(16 个服务端筛选条件) |
tebra_get_patient | 获取完整患者记录(通过 Tebra ID 或外部 ID),包括病例、保险单和授权信息 |
tebra_create_patient | 注册新患者并填写人口统计信息、保险和担保人信息 |
tebra_update_patient | 更新患者人口统计信息和联系方式 |
tebra_get_all_patients | 批量获取患者并进行分页(用于同步操作) |
预约
| 工具 | 描述 |
|---|---|
tebra_get_appointments | 按日期范围、资源(提供者)、患者、状态和地点搜索预约 |
tebra_get_appointment_detail | 获取完整预约详情,包括重复规则、群组数据和资源 |
tebra_create_appointment | 创建预约(提供者、地点、开始时间及持续时间/结束时间) |
tebra_update_appointment | 更新或重新安排现有预约 |
tebra_update_appointment_status | 仅更改状态(Confirmed、CheckedIn、NoShow、Cancelled 等) |
tebra_delete_appointment | 永久删除预约 |
tebra_get_appointment_reasons | 列出诊所配置的预约类型/原因 |
tebra_create_appointment_reason | 创建新的预约类型/原因 |
就诊与账单
| 工具 | 描述 |
|---|---|
tebra_get_encounter | 获取就诊详情,包括状态、提供者和服务项目 ID |
tebra_create_encounter | 创建就诊(超级账单),并为每个项目行添加诊断和操作 |
tebra_update_encounter_status | 工作流状态转换:Draft -> Submitted -> Approved / Rejected / Unpayable |
tebra_get_charges | 使用 18 个筛选条件搜索费用(日期、患者姓名、提供者、状态) |
tebra_get_payments | 按入账日期、付款方、批次和参考编号搜索付款记录 |
tebra_create_payment | 将付款记入患者账户 |
保险与授权
| 工具 | 描述 |
|---|---|
tebra_get_patient_authorizations | 获取所有授权信息,包括状态、剩余就诊次数和 CPT 代码 |
tebra_check_insurance_eligibility | 根据已存档的保险数据检查资格 |
诊所配置
| 工具 | 描述 |
|---|---|
tebra_get_providers | 列出所有提供者及其 ID、专科和 NPI 编号 |
tebra_get_service_locations | 列出诊所地点、地址和联系信息 |
tebra_get_practices | 获取诊所元数据(名称、税务 ID、账单信息) |
tebra_get_procedure_codes | 获取操作代码目录,包括描述和默认费用 |
文档
| 工具 | 描述 |
|---|---|
tebra_create_document | 将文档(PDF、图像)上传到患者病历 |
tebra_delete_document | 从患者病历中删除文档 |
财务分析
| 工具 | 描述 |
|---|---|
tebra_get_transactions | 获取用于财务报告的详细交易数据 |
外部供应商与系统
| 工具 | 描述 |
|---|---|
tebra_validate_connection | 健康检查 -- 验证 SOAP 凭证和连接情况 |
tebra_get_throttles | 获取当前 API 速率限制状态和剩余配额 |
tebra_register_external_vendor | 注册外部供应商以关联 ID |
tebra_get_external_vendors | 列出已注册的外部供应商 |
tebra_update_patient_external_id | 将外部系统 ID 关联到 Tebra 患者 |
tebra_set_primary_patient_case | 将现有患者病例设为主要病例(按病例 ID) |
FHIR 临床数据(需要 FHIR 凭证)
这些工具通过 Tebra FHIR R4 API 访问临床数据。它们需要单独的 FHIR 凭证(见上文“环境变量”)。如果未配置 FHIR 凭证,则不会注册这些工具。
FHIR 患者 ID 与 SOAP 患者 ID 属于不同的标识符空间 — 使用 tebra_fhir_search_patients 解析它们。所有 FHIR 搜索都会自动按照 Bundle 分页(最多 10 页);对于 Tebra 要求第二个搜索参数的三个资源(MedicationRequest 的 intent、CarePlan 的 category、CareTeam 的 status),系统会设置合理的默认值,避免搜索结果在没有提示的情况下为空。
| 工具 | 描述 |
|---|---|
tebra_fhir_search_patients | 按姓名、出生日期或标识符查找 FHIR 患者 ID |
tebra_fhir_get_allergies | 患者过敏和不耐受列表 |
tebra_fhir_get_medications | 当前和历史用药列表 |
tebra_fhir_get_conditions | 问题列表 / 活动病症 |
tebra_fhir_get_vitals | 近期生命体征(血压、心率、体温、体重、BMI) |
tebra_fhir_get_lab_results | 实验室检查结果和观察值 |
tebra_fhir_get_immunizations | 疫苗接种记录 |
tebra_fhir_get_procedures | 已执行的操作 |
tebra_fhir_get_care_plans | 当前护理计划 |
tebra_fhir_get_care_team | 护理团队成员及其角色 |
tebra_fhir_get_diagnostic_reports | 诊断报告(放射学、病理学) |
tebra_fhir_get_documents | 临床文档(CDA、笔记) |
tebra_fhir_get_devices | 植入式设备(UDI 数据) |
速率限制
SOAP 客户端会针对每种操作强制执行最小调用间隔,与 Tebra API Technical Guide 中的限流阈值保持一致。当工具的调用频率超过允许的上限时,客户端会短暂休眠,直到满足间隔要求后再发送请求——调用只会延迟,不会被丢弃。
| 操作 | 调用之间的最小间隔 |
|---|---|
GetPatient | 250 ms |
GetPractices、GetProviders、GetServiceLocations、GetProcedureCodes、GetEncounterDetails、GetAppointment,所有 Create* / Update* / Delete* | 500 ms |
GetPatients、GetAppointments、GetAppointmentReasons、GetCharges、GetPayments、GetTransactions、GetExternalVendors、UpdatePatient | 1000 ms |
GetAllPatients、GetThrottles | 5000 ms |
除了客户端限流外,每次 SOAP 调用在返回错误前最多会进行 3 次重试,并采用指数退避(1s、2s、4s)。使用 tebra_get_throttles 可实时查询 Tebra 服务端的速率限制计数器。
示例工作流
预约流程
1. tebra_get_providers -- Get provider IDs
2. tebra_get_service_locations -- Get location IDs
3. tebra_get_appointment_reasons -- Get reason/type IDs
4. tebra_create_appointment -- Create with provider, location, reason IDs
5. tebra_get_appointment_detail -- Verify creation
就诊审批流程
1. tebra_create_encounter -- Create superbill (status: Draft)
2. tebra_update_encounter_status -- Move to Submitted (shows as "Review" in Tebra's UI)
3. tebra_update_encounter_status -- Move to Approved (triggers billing)
OR
3. tebra_update_encounter_status -- Reject back to Draft
前台签到流程
1. tebra_get_appointments -- Today's schedule (resourceName = provider)
2. tebra_update_appointment_status -- CheckedIn on arrival
3. tebra_update_appointment_status -- CheckedOut at departure
付款入账流程
1. tebra_search_patients -- Find patient
2. tebra_get_charges -- Find outstanding charges
3. tebra_create_payment -- Post payment to patient account
4. tebra_get_payments -- Verify payment posted
患者入职
1. tebra_search_patients -- Check for existing patient
2. tebra_create_patient -- Create if not found
3. tebra_update_patient_external_id -- Link Supabase client ID
4. tebra_create_appointment -- Schedule first visit
创建记录时的临床上下文
1. tebra_get_appointments -- Get today's schedule
2. tebra_get_appointment_detail -- Get appointment context
3. tebra_get_patient -- Full patient demographics
4. tebra_get_patient_authorizations -- Check auth status
5. tebra_fhir_get_allergies -- Allergies
6. tebra_fhir_get_medications -- Current medications
7. tebra_fhir_get_conditions -- Problem list
8. tebra_fhir_get_vitals -- Recent vitals
工具依赖链
某些工具需要从其他工具获取 ID。主要依赖关系:
tebra_create_appointment
requires: patientId (from tebra_search_patients or tebra_create_patient)
requires: providerId (from tebra_get_providers)
requires: locationId (from tebra_get_service_locations)
optional: reasonId (from tebra_get_appointment_reasons)
tebra_create_encounter
requires: patientId (from tebra_search_patients)
requires: providerId (from tebra_get_providers)
recommended: practiceName/practiceId (from tebra_get_practices)
optional: authorization number (from tebra_get_patient_authorizations)
tebra_create_payment
requires: patientId (from tebra_search_patients)
tebra_update_encounter_status
requires: encounterId (from tebra_create_encounter or tebra_get_encounter)
tebra_create_document
requires: patientId (from tebra_search_patients)
tebra_update_patient_external_id
requires: patientId (from tebra_search_patients or tebra_create_patient)
recommended: externalVendorId (from tebra_get_external_vendors)
tebra_set_primary_patient_case
requires: patientCaseId (from tebra_get_patient — cases[].caseId)
All clinical tebra_fhir_get_* tools
require: FHIR patientId (from tebra_fhir_search_patients — NOT the SOAP patient ID)
隐私政策
此服务在本地运行,仅使用你自己的凭据与 Tebra API 通信。它没有后端、没有遥测,也不会向磁盘写入任何内容。调试日志和错误消息会清除凭据及患者标识符;每个返回记录的工具都提供 fields 参数,以便按最小必要原则选择字段。工具结果包含受保护的健康信息,因此若要将这些结果发送给 Claude,必须使用 Anthropic 已签署《业务伙伴协议》的 Claude 方案。完整政策请参阅 PRIVACY.md。
桌面扩展(.mcpb)
manifest.json 会将服务打包为供 Claude Desktop 使用的 MCP Bundle,其中每项凭据都声明为敏感的 user_config(存储在操作系统钥匙串中),FHIR 私钥则声明为 file 输入。使用以下命令构建 Bundle:
npm run pack:mcpb # builds, prunes dev dependencies, writes tebra-mcp-server.mcpb
src/__tests__/manifest.test.ts 会将 manifest 固定为与 package.json 和工具注册表一致,因此,如果向服务添加了工具却未在 manifest 中添加条目,测试套件就会失败。
在 Claude Desktop 中安装后,FHIR 私钥必须使用桌面应用可读取的绝对路径(例如 C:\Users\you\keys\fhir.pem 这样的 Windows 路径,而不是相对于某个项目的路径)。如果密钥无法读取,13 个 FHIR 工具会被禁用,并在 stderr 中显示消息;34 个 SOAP 工具不会因此停止运行。安装表单中留空的可选字段可以正常处理:Claude Desktop 会将它们原样作为 ${user_config.<key>} 占位符传入,服务会将其视为未设置。
API 参考
此服务封装了两个 Tebra API:
SOAP API v2.1(34 个工具)
- 端点:
https://webservice.kareo.com/services/soap/2.1/KareoServices.svc - 身份验证:RequestHeader,包含 CustomerKey、Password、User(WSDL 序列顺序很重要)
- 请求正文按 WSDL(
?xsd=xsd0/xsd7)中的成员顺序生成——WCF 会静默丢弃顺序错误的成员 - 所有请求都包含带指数退避的重试(尝试 3 次,间隔 1s、2s、4s)
FHIR R4 API(13 个工具)
- 端点:
https://fhir.prd.cloud.tebra.com/fhir-request(注意其中的连字符——可通过TEBRA_FHIR_BASE_URL配置) - 身份验证:通过 OAuth2 客户端凭据流程访问
https://fhir.prd.cloud.tebra.com/smartauth/oauth/token - 缓存令牌,并在令牌过期前自动刷新;遇到 401 时重试一次
- 自动跟进 Bundle 分页(每次搜索最多 10 页)
开发
git clone https://github.com/jamesrosing/tebra-mcp-server.git
cd tebra-mcp-server
npm install
npm run dev # tsx — runs src/index.ts directly without a build step
npm run build # tsc — compiles to dist/
npm test # node:test via tsx — 37 regression tests covering wire-format invariants
npm start # node dist/index.js — runs the compiled output
回归测试套件锁定了 3 项 Tebra 线格式不变量(SOAPAction 契约片段、RequestHeader 顺序、空 Fields/已填充 Filter),并覆盖每个请求构建器各自的 WSDL 成员顺序——这些问题的失败表现都是静默返回空结果,而不是报错,因此测试是唯一能快速反馈的途径。
路线图
- 针对 0.4.0 写入数据结构,在沙盒诊所运行实时冒烟测试套件(数据结构源自 WSDL 并由单元测试锁定;剩下的步骤是生产环境验证)
- 为大型列表工具添加客户端分页(
limit/offset+has_more),与tebra_get_all_patients保持一致 - 使用
.strict()schema 进行 Zod 运行时验证,让拼写错误的参数明确报错,而不是被丢弃 - 从
Server.setRequestHandler迁移到 SDK 的McpServer/registerToolAPI,并添加outputSchema/structuredContent - 面向 Agent 的评估集(10 个只读且可验证的问题),用于发现错误但看似合理的数据——这是单元测试无法检测的故障类型
更新日志
0.6.0 (2026-09-19)
满足 Connectors Directory 上架要求。线格式没有变化。
- feat(annotations):每个工具都包含
title和 MCP 注解(readOnlyHint、destructiveHint、idempotentHint、openWorldHint),根据工具动词生成,并由tool-annotations.test.ts锁定。 - feat(redact):从 SOAP 调试日志中清除 PHI 和凭据,并从抛出的错误消息中清除请求里的患者标识符(包括 SOAP 错误、FHIR 错误,以及
tebra_get_patient参数错误)。使用合成记录进行测试,确保没有标识符残留。 - feat(fields):返回记录的工具支持使用
fields进行最少必要字段选择(支持通过数组访问点分隔的路径)。tebra_get_all_patients默认使用患者名册投影;除非明确指定,tebra_get_patient不会返回保险保单号和团体编号。 - refactor(fhir):处理器接收在启动时解析一次的
FhirConfig,OAuth 令牌缓存按客户端分别保存。 - feat(mcpb):添加
manifest.json(MCPB 0.2),其中每项凭据都通过敏感user_config配置;新增PRIVACY.md、npm run pack:mcpb,以及在版本标签上打包 bundle 的 CI 工作流。 - fix(fhir):FHIR 密钥路径无法读取时,启动不再退出;未展开的 Claude Desktop
${user_config.*}占位符会被视为未设置(2026-09-19 实时验证:这两种情况都会导致桌面扩展显示“Server disconnected”并停止运行,且没有可见原因)。 - docs:在 README、软件包说明和 skill 中说明本项目独立于 Tebra,且需要 BAA;
server.json现在将TEBRA_SOAP_USER标记为机密。
0.5.1 (2026-09-06)
- fix(retry safety):
tebra_create_payment(以及其他所有 Create* 操作)在超时、发送后连接重置或 HTTP 5xx 后不再重新发送。这些失败的结果无法确定——Tebra 可能已提交写入,只是响应丢失;而 Tebra 的 SOAP API 没有幂等键,因此自动重试可能会向患者账户再次入账(#13)。Create* 操作现在只会在能够确定发生于 Tebra 执行操作之前的故障时重试(429 限流、连接被拒绝/无法解析);其他情况都会抛出AmbiguousOutcomeError,其中会指出应先使用哪个读取工具进行验证,再重新提交。读取操作仍保留完整的 3 次重试。 - “FHIR 工具已禁用”启动消息和环境变量文档注释现在会说明
private_key_jwt路由;package-lock.json已重新同步至软件包版本(#17)。
0.5.0 (2026-09-04)
- 功能(FHIR 身份验证):SMART Backend Services
private_key_jwt客户端身份验证。设置TEBRA_FHIR_PRIVATE_KEY_PATH+TEBRA_FHIR_KID后,令牌请求会携带 RS384 客户端断言(iss=sub=客户端 ID,aud=令牌 URL,exp=5 分钟,每个请求使用唯一的jti),而不是密钥——这是通过 JWKS URL 注册的 appSphere Backend App 所要求的格式。未设置密钥路径时,仍会回退到client_secret;已有的密钥安装不受影响。现在FhirConfig.clientSecret为可选项,并新增了FhirConfig.privateKey。已离线测试:断言通过已发布的 JWKS fixture 验证,从未访问在线令牌端点。
0.4.3 (2026-08-04)
- 修复(外部 ID):在
tebra_create_patient和tebra_update_patient_external_id中,对超过 25 个字符的 ID 采用失败关闭策略——Tebra 的外部 ID 存储会在 25 个字符处静默截断(通过截断值上的 UNIQUE KEY 冲突在线验证),这会导致之后所有使用完整值的查找失败。ID 在每个供应商范围内也必须唯一。(此保护措施刚好未赶上 0.4.2 压缩包。)
0.4.2 (2026-08-04)
写入路径现已通过生产环境验证:针对真实诊所反复运行实时写入冒烟测试,确认了 CreatePatient、CreateAppointment、CreateDocument,以及外部 ID 批量操作和供应商范围内查找的端到端流程(就诊写入操作仍需选择加入验证)。测试发现了另外四项线路层面的事实,现已全部修复:
- 必需成员(CreatePatient 出错并提示 “Expecting element 'Practice'” 后进行的
minOccurs审计):PatientCreate/PatientUpdate 要求Practice;AppointmentCreate 要求PracticeId;AppointmentUpdate 要求PatientId+ServiceLocationId;DocumentCreateRequest 要求PracticeId。 - 外部 ID 按供应商区分,在每个供应商范围内唯一,并会在 25 个字符处静默截断——现在较长 ID 的写入会失败关闭(截断会导致之后所有查找失败)。
DocumentDate实际上是xs:dateTime——仅日期格式的输入会规范化为 ISO 午夜时间;美国格式的字符串会导致反序列化器出错(Filter 日期成员为xs:string,仍可接受这两种格式)。UpdatePatientsExternalID响应中的ItemsUpdated回显为空,即使操作成功也是如此——应改为通过tebra_get_patient中供应商范围内的ExternalID查找来验证。
详情:
- 修复(create/update_patient):
Practice是 PatientCreate 和 PatientUpdate 的必需成员——现在始终会传出;如果未提供 practiceName/practiceId,则会通过 GetPractices 自动解析账户的首个诊所(并缓存)。tebra_update_patient新增可选的 practiceName/practiceId 参数。 - 修复(create_appointment):
PracticeId为必需项——未提供时会自动解析。 - 修复(update_appointment):
PatientId和ServiceLocationId为必需项——未提供时会通过 GetAppointment 自动补全,因此仅更新状态或重新安排时间仍可正常工作。 - 修复(create_document):
PracticeId为必需项——未提供时会自动解析。 - 如果必需成员仍缺失,构建器会给出明确提示并失败关闭;新增 3 项回归测试(共 39 项)。
0.4.1 (2026-08-04)
对 0.4.0 中的请求结构进行线上生产环境验证——完整执行只读冒烟测试(共 24 项检查:每个 SOAP 读取工具以及 FHIR 流水线),现已通过真实的 Tebra 诊所验证。以下修复均是在实际环境中发现的:
- fix(xsd7 namespace):GetServiceLocations 和 GetProcedureCodes 报错“Expecting element 'Fields'”——xsd7 的 targetNamespace 不带尾随斜杠(
…/api/schemas,而 xsd0 为…/api/schemas/),因此它们的 Fields/Filter 成员是不同的 XML 名称。现在信封会声明这两个命名空间,且这两个工具会输出带kar7:前缀的成员。 - fix(get_appointment_reasons):WSDL 要求提供
PracticeId(省略时会报错)。如果未提供,处理程序现在会通过 GetPractices 自动解析该账户的首个诊所 ID,并缓存结果。 - fix(search_patients):服务端将
ToDateOfBirth视为不包含边界——搜索精确的dateOfBirth时,现在会发送 [DOB, DOB+1),而不是会导致匹配结果为空的零宽范围。 - fix(rate limiting):每个端点的限流间隔增加 +250ms 安全余量——即使间隔恰好等于限制,仍会触发 Tebra 服务端的 429;现在会将限流错误(在 HTTP-200 ErrorResponse 块中报告)归类为可重试错误。
- fix(get_encounter):GetEncounterDetails 返回的 EncounterStatus 是从 1 开始的数字代码;现在会将其映射为标签(3=Approved,已通过同一就诊记录的收费条目进行线上验证)。
- fix(FHIR auth):发生
invalid_scope时,令牌服务端会指出客户端注册时使用的范围——客户端现在会自动使用该范围重试一次(不同注册可能使用system/*.read或patient/*.read)。
0.4.0 (2026-08-03)
全面审计 WSDL 合约。根据线上 WSDL(KareoServices.svc?xsd=xsd0/xsd7)重新推导了每个请求构造器,由此发现,0.3.0 中针对 GetCharges 修复的 Fields/Filter 放置错误影响了其他所有列表 GET 操作,而大多数写入操作使用了错误的包装元素或成员名称。所有情况下的失败都不易察觉(未应用筛选、字段被丢弃或服务端报错),这正是这些问题长期存在的原因。新增 26 个回归测试,以确保请求结构正确。
- 修复(列表 GET):patients、appointments、payments、transactions、providers、service-locations、procedure-codes、bulk-patients 和 encounter-details 现在会按 WSDL 序列顺序将筛选条件放入
<kar:Filter>,并使用空的<kar:Fields/>——此前,它们的所有筛选参数都会被静默忽略,每次调用都返回未筛选的结果集。WSDL 中没有对应筛选字段的参数现在会以失败关闭的方式处理,并提供指引(patients.mrn、appointments.providerId→ 使用resourceName,payments.patientId)。 - 修复(get_patient / authorizations / eligibility):
GetPatientReq完全没有 Fields 成员——现在 ID 会放入Filter(SinglePatientFilter),因此单个患者查询可以正常工作。tebra_get_patient也新增了通过externalId/externalVendorId查询的功能。 - 修复(响应解析器):各处均使用 WSDL 中的真实成员名称——嵌套的病例/保单/授权数据(
PatientCaseData→PatientInsurancePolicyData→PatientInsurancePolicyAuthorizationData、AuthorizedNumberOfVisits)、MedicalRecordNumber、NationalProviderIdentifier、用于批量分页的PatientBatchData和nextStartKey、ThrottleDetail、ExternalVendorData、EncounterDetailsData。以前使用的名称都无法匹配,因此保险/授权/病例数据始终解析为空。所有列表解析器都会移除 Tebra 返回的虚假空占位行。 - 修复(写入操作):
create/update_patient的成员现在按 WSDL 顺序重新排列(顺序错误的成员会被静默丢弃——出生日期、性别、电子邮件和地址都未能持久化),并使用正确的名称(SocialSecurityNumber、PatientExternalID、MedicalRecordNumber),保险信息嵌套在Cases → Policies下;create/update_appointment已重写为扁平的AppointmentCreate/Update结构(StartTime/EndTime、PatientSummary、ProviderId);delete_appointment现在会封装Appointment;create_encounter已重写为EncounterCreate(每条服务明细对应DiagnosisCode1–4、RenderingProvider、Practice);update_encounter_status现在会封装包含真实枚举值的EncounterUpdateStatus(Draft/Submitted/Approved/Rejected/Unpayable——“Review” 是 UI 标签,不是 API 状态);create_payment使用PaymentCreate的嵌套分组;create_document按成员顺序封装DocumentToCreate;delete_document发送DocumentId(区分大小写);外部 ID 工具使用ExternalVendor/Updates→UpdateBatch批次结构;create_appointment_reason按成员顺序传递整数颜色值;validate_connection现在会发送GetCustomerIdFromKeyRequest实际所需的凭据。 - 变更:
tebra_update_patient_case→tebra_set_primary_patient_case——底层操作(UpdatePrimaryPatientCase)只能通过PatientCaseId将病例设为主要病例,从不接受名称/付款方场景编辑。旧工具名称仍可正常路由。 - 新增:
tebra_update_appointment_status——通过UpdateAppointmentStatus针对性更新状态(CheckedIn/NoShow/Cancelled...),比完整更新开销更低。 - 修复(FHIR):将默认基础 URL 更正为
https://fhir.prd.cloud.tebra.com/fhir-request(包含连字符——旧的/fhir/request路径对每次调用都会返回 HTTP 200 和空响应体,此问题已于 2026-08-03 通过实时验证);现在空的 200 响应会触发描述明确的配置错误;401 会触发一次自动令牌刷新并重试;起止日期范围现在会生成两个重复的date参数(此前会进行百分号编码并合并成一个格式错误的值);现在会自动跟进 Bundle 分页(link[rel=next],最多 10 页,并标记截断情况);为必需的第二个搜索参数设置了默认值(MedicationRequest intent=order、CarePlan category=assess-plan、CareTeam status=active)——若缺少这些参数,Tebra 会静默返回空 Bundle。 - 新增:
tebra_fhir_search_patients——按姓名/出生日期/标识符查询 FHIR Patient;FHIR 患者 ID 与 SOAP ID 属于不同的标识符空间,以前服务端没有解析这两者的途径。 - 修复(核心):
extractTag/extractAllTags现在要求标签名后有边界(Patient不再匹配PatientData);服务端版本现在从 package.json 读取(此前硬编码为0.2.5);服务端名称更正为tebra-mcp-server;速率限制表现在使用CreatePayment/UpdateAppointmentStatus作为键。
0.3.2 (2026-07-15)
- 杂项:移除了打包附带的项目专用集成模板(
src/integrations/epic-notes-integration.ts、src/integrations/fal-integration.ts)及所有相关引用(README 的“集成服务”部分、工作流示例标签、贡献者文档)。这些模板是供外部下游项目复制粘贴的连接器模块——服务从未导入它们,它们也不属于服务的运行时——因此不应包含在已发布的软件包中。没有新增或移除任何 MCP 工具;45 个工具的范围保持不变,编译后的 tarball 不再包含dist/integrations/。
0.3.1 (2026-07-07)
- 修复(get_charges):现在发送的
<kar:Fields/>为空。0.3.0 中显式设置的列开关触发了 Tebra 的投影反转问题——无论筛选条件是否匹配,每次调用都会返回一个空的<ChargeData/>占位符(没有任何实际字段,也没有故障)。空的 Fields 会返回完整记录,其中包括PrimaryInsurance*理赔裁定列(付款、合同调整及原因、二次调整及原因、裁定日期);这些正是显式开关原本要显示的字段。 - 响应解析器(已导出的
parseChargeBlocks)会丢弃空占位块——之前,无匹配结果的响应会被计为一笔虚构的全空收费记录。 status筛选器文档现列出实时观察到的枚举值:Pending、Completed、Error - Rejection、Voided、Ready。至少有些账户没有Denied状态——拒赔会显示为Error - Rejection。- 已通过生产环境的 Tebra 进行实时验证:一次为期 12 个月、分 14 个时间窗口的拉取返回了 293 笔包含已填充财务数据的实际收费记录;已确认服务端
Status筛选正常工作。
0.3.0 (2026-07-06)
- 修复(get_charges):筛选条件已从
<kar:Fields>移至<kar:Filter>,并按照 WSDL(xsd0)中的顺序输出——放在 Fields 中时,WCF 会静默跳过这些条件,因此 GetCharges 会返回整个软件包历史记录中未经筛选的数据。现在patientId会抛出异常(ChargeFilter 没有患者 ID 成员;请使用patientName)。 - 注意:Tebra 会在服务端强制要求 GetCharges 的入账日期窗口不超过 60 天。
0.2.6 (2026-07-06)
- 修复(get_appointment_detail):
GetAppointment不接受列表端点使用的Fields/Filter请求结构。根据实时 WSDL(KareoServices.svc?xsd=xsd0),GetAppointmentReq = RequestBase + <Appointment>{ AppointmentId: xs:long }</Appointment>(小写 “d”)。旧请求信封每次调用都会出错,报错为'EndElement' 'request' … Expecting element 'Appointment',因此tebra_get_appointment_detail无法用于实时 Tebra。 - 响应采用 WSDL 的
AppointmentCreate结构——患者信息嵌套在<PatientSummary>下(团体参与者位于<PatientSummaries>下),使用 ISO 格式的StartTime/EndTime、AppointmentStatus和字母枚举形式的AppointmentType。该工具的输出现映射这些实际字段(患者姓名和出生日期、预约模式、原因 ID、重复信息、团体参与者、审计时间戳),而不是虚构的AppointmentData字段集。 - 已通过实时验证:成功返回了一条真实预约的完整详情。给贡献者的经验:Tebra 的单条记录操作可能与对应的列表操作采用完全不同的 WSDL 契约——不要想当然地套用 Fields/Filter 模式,请先阅读
?xsd=xsd0。
0.2.5 (2026-04-28)
- 修复(soap):现在每个 GET 请求正文都会在
<kar:Fields>后添加同级的<kar:Filter />。Tebra 的 WSDL 将Filter标记为minOccurs="0",但其服务端GetFilteredX(...)方法会在不进行空值检查的情况下解引用 filter 参数,当参数缺失时就会抛出NullReferenceException。已修复的工具:practices、providers、service-locations、procedure-codes、transactions、payments、charges、encounters、patients(搜索和按 ID 获取)、bulk-patients、appointments。没有 0.2.5 时,每次 GET 调用都会因服务端 NullRef 而失败。 - 新增回归测试,断言
<kar:Filter />按照 WSDL 要求的顺序输出(Fields 在前,Filter 在后)。
0.2.4 (2026-04-28)
- fix(soap):现在
<RequestHeader>子元素会按 WSDL 要求的顺序序列化(CustomerKey → Password → User)。此前的CustomerKey → User → Password顺序会导致授权静默失败,即使凭据有效也一样。此结论已由 Tebra 客户服务书面确认。
0.2.3 (2026-04-28)
- fix(soap):现在
SOAPActionHTTP 标头包含 Kareo 调度器要求的KareoServices/WCF 合约段。0.2.2 及更早版本发送的是${SOAP_NAMESPACE}${operation},调度器会拒绝该值并返回 HTTP 500(ContractFilter mismatch at the EndpointDispatcher)。现在还会按照 RFC 3902 §3.2 显式为标头值加上引号。 - 添加了回归测试,用于断言标头的确切值(
npm test)。
0.2.2 (2026-04-27)
- fix(soap):现在
RequestHeader(User/Password/CustomerKey)会放在请求正文内,这是 Tebra 的 WSDL 预期的位置,而不是放在 SOAP 信封标头中。
0.2.1 (2026-04-26)
- 已在 MCP Registry 中以
com.jamesrosingmd/tebra发布(已验证域名命名空间)。
0.2.0
- 首次公开发布。
请立即从 0.2.4 或更早版本升级。 所有先前版本都至少存在上述三个线格式错误之一,只有 0.2.5 能够端到端满足 Tebra 的全部三项 WSDL/运行时要求。
许可证
MIT License
Copyright (c) 2026 James H. Rosing, MD, FACS
特此免费授权任何获得本软件及相关文档文件(以下简称“软件”)副本的人不受限制地处理本软件,包括但不限于使用、复制、修改、合并、发布、分发、再许可和/或出售本软件副本的权利,并允许向其提供本软件的人也这样做,但须遵守以下条件:
上述版权声明和本许可声明应包含在本软件的所有副本或主要部分中。
本软件按“原样”提供,不附带任何明示或默示的保证,包括但不限于对适销性、特定用途适用性和不侵权的默示保证。在任何情况下,作者或版权持有人均不对因本软件或本软件的使用或其他处理而产生的任何索赔、损害或其他责任承担责任,无论是在合同、侵权或其他诉讼中。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。