关于 KeyFlight PNR Converter
KeyFlight PNR Converter 是面向旅行代理、旅行社及处理 GDS 预订的开发者的托管 MCP 服务和 PNR API。它可解析 Amadeus、Sabre、Galileo 和 Worldspan 记录,生成行程与 JSON,也能制作 PRO 票 PDF。
主要功能
- 01解析四种 GDS 格式的 PNR
- 02输出可读行程和结构化 JSON
- 03选择行程布局及日期时间格式
- 04生成可选价格的 PRO 票 PDF
适用场景
- 01将 GDS 预订转换为旅客行程
- 02把解析后的预订数据传入预订工具或 CRM
- 03根据 PNR 制作 PRO 票 PDF
MCP 相关
托管 MCP 服务位于 https://keyflight.io/mcp,提供 PNR 解析和 PRO 票 PDF 生成工具。它使用 Streamable HTTP,并要求提供 bearer API 密钥。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://keyflight.io/mcpclaude mcp add --transport http io-keyflight-pnr https://keyflight.io/mcp{"mcpServers":{"io-keyflight-pnr":{"type":"http","url":"https://keyflight.io/mcp"}}}在 Cursor 中打开{"servers":{"io-keyflight-pnr":{"type":"http","url":"https://keyflight.io/mcp"}}}在 VS Code 中打开{"mcpServers":{"io-keyflight-pnr":{"type":"http","url":"https://keyflight.io/mcp"}}}{"mcpServers":{"io-keyflight-pnr":{"serverUrl":"https://keyflight.io/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://keyflight.io/mcp需要授权工具
详细介绍

KeyFlight PNR Converter:MCP 服务和 PNR API
将 GDS(Amadeus、Sabre、Galileo、Worldspan)中的原始预订内容粘贴到 Claude、Cursor 或其他 AI 助手中,即可获取易读的行程、JSON 格式的预订信息或 PRO 机票 PDF。
KeyFlight 在 https://keyflight.io/mcp 托管了 Model Context Protocol 服务,并在 https://keyflight.io/api/v1/pnr/decode 提供 HTTP API。两者使用的解码器与 keyflight.io 上的免费 PNR converter 相同。
此代码库包含文档和示例。服务本身由 KeyFlight 托管:无需安装或运行任何内容。完整参考文档:keyflight.io/pnr-api。
适用对象: 使用 GDS 预订的旅行代理和代理机构,以及希望在预订工具、CRM、聊天机器人或电子邮件工作流中添加 PNR 解码功能的开发者。
获取 API 密钥
MCP 服务和 PNR API 使用同一个密钥,格式为 kfp_ 后接 43 个字母、数字、- 和 _。
- 获取 KeyFlight 订阅(旅行代理订阅)。
- 在同一页面使用 "Already subscribed?",打开我们通过电子邮件发送给你的链接,然后点击 "Create API key"。
- 复制密钥:它只会显示一次。一个订阅最多可同时拥有 2 个密钥;你可以在同一页面撤销密钥。
订阅尚未激活时,密钥会返回 403 subscription_inactive。API 和 MCP 服务均不提供免费套餐。网站上的 PNR converter 面向所有人免费开放,无需密钥。
连接 AI 助手(MCP)
| 服务 URL | https://keyflight.io/mcp |
| 传输方式 | Streamable HTTP,仅支持 POST,不使用会话,也不提供服务器发送事件流 |
| 身份验证 | 请求头 Authorization: Bearer kfp_… |
| 协议版本 | 2025-06-18、2025-03-26、2024-11-05 |
Claude Code
claude mcp add --transport http keyflight https://keyflight.io/mcp --header "Authorization: Bearer kfp_…"
Cursor(.cursor/mcp.json)
{
"mcpServers": {
"keyflight": {
"url": "https://keyflight.io/mcp",
"headers": {
"Authorization": "Bearer kfp_…"
}
}
}
}
Claude Desktop(claude_desktop_config.json,需要 Node.js)
Claude Desktop 通过 mcp-remote 连接:
{
"mcpServers": {
"keyflight": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://keyflight.io/mcp",
"--header",
"Authorization: Bearer kfp_…"
]
}
}
}
然后可以这样提问:“解码此 PNR,并制作一张价格为 850 EUR 的 PRO 机票”,再粘贴预订内容。
其他客户端:任何支持 Streamable HTTP 和自定义请求头的 MCP 客户端。来自其他网站网页(带有浏览器 Origin 请求头)的请求会被拒绝,并返回 403 origin_not_allowed,因此请从桌面应用、命令行或你的服务连接。若没有客户端,请参阅 examples/mcp/raw-jsonrpc.sh:每个 POST 请求发送一条 JSON-RPC 消息,并返回 JSON。
MCP 工具
decode_pnr:解码 PNR
将原始 PNR 转换为易读的行程(文本)和结构化 JSON:乘客、航班、机场、航站楼、本地时间、飞行时长、航空公司定位码。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
text | string, required | GDS 显示的 PNR,最多 20,000 个字符。系统会根据文本识别格式。 | |
view | table、lines2、lines3、whatsapp | table | 行程文本的布局。 |
time_format | "24"、"12" | "24" | 24 小时制或 12 小时制。 |
date_format | "short"、"numeric" | "short" | short:2026 年 5 月 3 日;numeric:03.05.2026。 |
返回行程文本,随后是 JSON: 和与 PNR API 响应相同的 JSON。读取 structuredContent 的客户端可在其中获取该 JSON。
每次成功解码出航班,都会计入订阅的每月解码次数,与 API 调用相同。不含航班的文本会返回错误,且不计入次数。当月解码次数用完后,该工具会一直返回错误,直到 1 日(UTC)。
make_ticket:制作 PRO 机票 PDF
根据原始 PNR 制作 PRO 机票 PDF(PNR、航空公司标志、舱位、可选价格),并返回 PDF 链接。已包含在 KeyFlight 订阅中。
机票是提供给旅客的文件:它不是航空公司的机票,其中的 PNR 也不会与航空公司的系统核对。
| 参数 | 类型 | 默认值 | 描述 |
|---|---|---|---|
text | string, required | PNR,最多 20,000 个字符。每个航班都需要日期和时间。 | |
passengers | 最多包含 20 个字符串的数组 | PNR 中的姓名 | 机票上的乘客姓名,例如 "SMITH/JOHN MR"。 |
pnr | string | 文本中的代码,或随机代码 | 印在机票上的预订代码,由 5–8 个字母和数字组成。 |
booking_class | Economy、Premium Economy、Business、First Class | 第一个航班的预订舱位 | 机票上的舱位。 |
price | string | 机票上不显示价格 | 印在机票上的总价,例如 "1200.50"。 |
currency | 最多 10 个字符的 string | "$" | 价格旁的货币,例如 "USD"、"€"。 |
logo | none、expedition | none | 机票页眉中的标志。 |
time_format | "24"、"12" | "24" | 24 小时制或 12 小时制。 |
date_format | "short"、"numeric" | short 或 numeric。 |
返回一行 PRO ticket PDF: https://keyflight.io/tickets/….pdf,其中包含 PNR、航班数量和乘客信息;并通过 structuredContent 返回:
{ "url": "https://keyflight.io/tickets/….pdf", "pnr": "PQ7XNR", "passengers": ["JOHNSON JOHN", "JOHNSON JANE"], "segments": 2 }
机票不计入每月解码次数;一个密钥每小时最多可制作 30 张机票。
出错时(文本中没有航班、航班缺少日期或时间、没有乘客姓名、pnr 或选项错误、每小时制作超过 30 张机票),工具会返回带有 isError: true 的结果,以便助手读取错误并修正调用。
通过 HTTP 使用 PNR API
使用 Content-Type: application/json 和 Authorization: Bearer kfp_… 向 POST https://keyflight.io/api/v1/pnr/decode 发送请求。请求体为 { "text": "…", "options": { … } }。HTTP API 会以文本和 HTML 形式返回数据及行程;PRO 机票 PDF 则由 MCP 工具 make_ticket生成。以下示例使用来自 examples/pnr-amadeus.txt 的 Amadeus 预订记录。
curl
curl https://keyflight.io/api/v1/pnr/decode \
-H "Authorization: Bearer $KEYFLIGHT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "RP/LHRBA/LHRBA BA/BA 26APR26/1200Z PQ7XNR\nPQ7XNR/BA QLHR 03MAY\n1.JOHNSON JOHN\n2.JOHNSON JANE\n3 BA 178 Y 03MAY 7 LHRJFK HK2 0855 1205 03MAY E BA/PQ7XNR\n4 BA 117 Y 10MAY 7 JFKLHR HK2 1830 0640 11MAY E BA/PQ7XNR\n5 TKT/TIME LIMIT\n6 OPC LHRBA-10MAY:1900/1S2/Q TKT/T-BA\n7 FA PAX 125-2196837482/ETBA/GBP560.20/03MAY26/LHRBA2104/00390755/S3-4",
"options": {
"view": "table"
}
}'
Node.js 18+
// Node.js 18+ (fetch is built in), in an ES module or an async function
const text = `RP/LHRBA/LHRBA BA/BA 26APR26/1200Z PQ7XNR
PQ7XNR/BA QLHR 03MAY
1.JOHNSON JOHN
2.JOHNSON JANE
3 BA 178 Y 03MAY 7 LHRJFK HK2 0855 1205 03MAY E BA/PQ7XNR
4 BA 117 Y 10MAY 7 JFKLHR HK2 1830 0640 11MAY E BA/PQ7XNR
5 TKT/TIME LIMIT
6 OPC LHRBA-10MAY:1900/1S2/Q TKT/T-BA
7 FA PAX 125-2196837482/ETBA/GBP560.20/03MAY26/LHRBA2104/00390755/S3-4`;
const response = await fetch('https://keyflight.io/api/v1/pnr/decode', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KEYFLIGHT_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ text, options: { "view": "table" } }),
});
const data = await response.json();
if (response.ok) {
data.segments.forEach((s) => console.log(s.airlineCode, s.flightNumber, s.departure.date));
} else {
console.error(response.status, data.error, data.message);
}
Python
examples/api/decode.py(需要 requests):
import os
import requests
text = """RP/LHRBA/LHRBA BA/BA 26APR26/1200Z PQ7XNR
PQ7XNR/BA QLHR 03MAY
1.JOHNSON JOHN
2.JOHNSON JANE
3 BA 178 Y 03MAY 7 LHRJFK HK2 0855 1205 03MAY E BA/PQ7XNR
4 BA 117 Y 10MAY 7 JFKLHR HK2 1830 0640 11MAY E BA/PQ7XNR
5 TKT/TIME LIMIT
6 OPC LHRBA-10MAY:1900/1S2/Q TKT/T-BA
7 FA PAX 125-2196837482/ETBA/GBP560.20/03MAY26/LHRBA2104/00390755/S3-4"""
response = requests.post(
"https://keyflight.io/api/v1/pnr/decode",
headers={"Authorization": f"Bearer {os.environ['KEYFLIGHT_API_KEY']}"},
json={"text": text, "options": { "view": "table" }},
timeout=30,
)
data = response.json()
if response.ok:
for s in data["segments"]:
print(s["airlineCode"], s["flightNumber"], s["departure"]["date"])
else:
print(response.status_code, data["error"], data["message"])
选项
| 字段 | 取值 | 默认值 |
|---|---|---|
text | 必填。GDS 显示的预订信息,最多 20,000 个字符。 | |
options.view | table、lines2、lines3、whatsapp:itinerary 的布局。 | table |
options.timeFormat | "24"(18:30)、"12"(6:30 PM) | "24" |
options.dateFormat | "short"(2026 年 5 月 3 日)、"numeric"(03.05.2026) | "short" |
options.show.logo | true / false。航空公司标志(仅限 HTML)。 | true |
options.show.airports | true / false。城市旁显示机场名称和航站楼。 | true |
options.show.cabin | true / false。舱位和预订舱等:经济舱(Y)。 | false |
options.show.status | true / false。航段状态:已确认、候补。 | false |
options.show.passengers | true / false。航班上方显示乘客姓名。 | false |
options.show.pnr | true / false。航班上方显示预订编号和航空公司的编号。 | false |
未知选项或错误的取值会返回 400 invalid_option,并附上字段和允许的取值。
响应
上方示例的完整响应:examples/api/response-example.json(itinerary.html 已缩短)。主要字段:
| 字段 | 含义 |
|---|---|
pnrCode | 文本中找到的预订编号,或 null。 |
passengers[].name | PNR 中记录的乘客姓名。 |
segments[].airlineCode、airlineName、flightNumber | 航空公司和航班号(UA0950 对应 "950")。 |
segments[].bookingClass、cabin | 预订舱等字母及其对应舱位:经济舱、高端经济舱、商务舱、头等舱。 |
segments[].status、statusText | PNR 中的状态代码("HK2"),以及“已确认”“候补”或该代码本身。 |
segments[].logoUrl | 航空公司标志,64×64 PNG。 |
segments[].duration | 按两个机场所在时区计算的飞行时间(分钟),或 null。 |
segments[].distance | 两个机场之间的距离 { km, miles },或 null。 |
segments[].aircraftCode、aircraft | PNR 中显示的机型,或 null。 |
segments[].operatedBy | PNR 中显示的承运航空公司(OPERATED BY …),或 null。 |
segments[].airlineLocator | { airlineCode, code }:航空公司自己的预订编号,或 null。 |
segments[].departure、arrival | code、city、airport、terminal、当地 date(YYYY-MM-DD)和 time(HH:MM)。 |
itinerary | view、text 和 html(带表格和内联样式的电子邮件 HTML;whatsapp 视图下为 null)。 |
以下是示例在 table 视图下、options.show.logo: false 时的 itinerary.html,显示效果与免费转换器一致:
限制
| 限制 | 值 |
|---|---|
| PNR 文本 | 最多 20,000 个字符;JSON 请求体最多 100kb |
| 每个密钥的请求数 | API 和 MCP 服务均为每分钟 60 次;超出后返回 429 too_many_requests,并附带 Retry-After |
| 每个 IP 地址的请求数 | 每分钟 120 次 |
| 每份订阅的解码次数 | 每个日历月(UTC)3,000 次,两个密钥合计;API 和 decode_pnr 合计。仅统计找到航班的解码次数。 |
PRO 机票 PDF(make_ticket) | 每个密钥每小时 30 次 |
HTTP API 的响应会附带 X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset 和 X-Monthly-Limit、X-Monthly-Remaining、X-Monthly-Reset。
错误
PNR API 错误采用 JSON 格式:{ "error": "<code>", "message": "…" }。
| 状态码 | error | 发生情况 |
|---|---|---|
| 400 | invalid_json | 请求正文不是 JSON 对象。 |
| 400 | text_required | 缺少 text 或其值为空。 |
| 400 | invalid_option | 选项未知或值不正确。field 指明相关字段,allowed 列出允许的值。 |
| 401 | missing_api_key | 未提供 Authorization: Bearer … 标头。 |
| 401 | invalid_api_key | 密钥无效或已被撤销。 |
| 403 | subscription_inactive | 密钥对应的订阅未激活。 |
| 404 | not_found | 未找到此端点。 |
| 405 | method_not_allowed | 请求方法不是 POST。 |
| 413 | too_long | 文本超过 20,000 个字符(响应中的 max 字段会显示上限)。 |
| 413 | payload_too_large | 请求正文超过 100kb。 |
| 415 | unsupported_encoding | 请求正文不是 UTF-8 编码。 |
| 422 | no_flights | 文本中没有航班。不会计入每月限额。 |
| 429 | too_many_requests | 超出每分钟限额;请等待 Retry-After 秒。 |
| 429 | monthly_limit_reached | 该订阅本月的解析次数已用完。 |
| 500 | server_error | 我们这边发生了错误。 |
| 503 | service_unavailable | 目前无法验证密钥。请一分钟后重试。 |
工具运行前,MCP 服务会以相同的 JSON 格式返回以下错误:401 missing_api_key / invalid_api_key、403 subscription_inactive、429 too_many_requests 和 503 service_unavailable;此外,对于来自其他网站网页的请求,还会返回 403 origin_not_allowed;对于非 POST 请求,还会返回 405 method_not_allowed。在工具内部发生的错误(包括达到每月限额)会作为工具结果返回,并带有 isError: true。
支持的 GDS 格式
Amadeus (1A)、Sabre (1B/1S)、Galileo (1G) 和 Worldspan (1P)。请按 GDS 显示的格式发送预订信息;无需说明其来源系统。各系统的预订示例:Amadeus、Sabre、Galileo、Worldspan。
链接
- API 和 MCP 参考文档:keyflight.io/pnr-api
- 免费 PNR 转换器(无需密钥):keyflight.io/tickets/pnr
- 面向旅行代理的 KeyFlight 订阅:keyflight.io/subscription
许可证
本仓库中的示例和文档遵循 MIT License。KeyFlight 服务并非开源;使用该服务需要订阅 KeyFlight。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。