1. 项目背景与核心需求
作为一名经常出差的开发者,我深刻体会到传统航班查询工具的局限性——需要反复切换不同APP、手动输入繁琐的查询条件、无法获取个性化建议。这促使我萌生了开发AI航班助手的想法,核心需求包括:
- 实时航班查询:支持按航线/航班号快速检索,避免传统APP的多级菜单操作
- 智能评估系统:整合准点率、机型舒适度等数据,提供航班选择建议
- 场景化服务:机场天气、中转方案、实时位置追踪等出行刚需功能
技术选型上,经过对比主流方案,最终确定:
- OpenClaw:作为AI技能托管平台,提供自然语言交互和技能分发能力
- 飞常准MCP:国内最全面的航班数据接口,覆盖90%以上国内航线
提示:选择MCP协议而非直接调用API,是因为其标准化接口能减少70%以上的适配开发量,且内置的密钥隔离机制更符合企业级安全要求。
2. 技术架构设计与实现
2.1 系统分层架构
采用经典的三层架构,但针对AI特性做了优化:
code复制┌────────────────┐
│ 交互层 │ # OpenClaw自然语言处理
├────────────────┤
│ 逻辑层 │ # Node.js业务逻辑+缓存
├────────────────┤
│ 数据层 │ # MCP协议封装+飞常准API
└────────────────┘
2.2 关键代码结构
bash复制src/
├── lib/
│ ├── variflight-client.js # MCP客户端封装
│ ├── mcp-server-manager.js # 服务器生命周期管理
│ └── config-loader.js # 安全配置加载
└── commands/
├── search.js # 航线搜索(核心)
├── info.js # 航班详情
├── comfort.js # 舒适度算法
└── weather.js # 气象数据解析
2.3 按需启动设计
为避免资源浪费,采用独特的"调用时启动"模式:
javascript复制async function queryFlight(flightNo) {
const client = new VariflightClient();
try {
await client.connect(); // 启动MCP服务
return await client.callTool('getFlightInfo', {flightNo});
} finally {
await client.disconnect(); // 确保资源释放
}
}
这种设计带来三大优势:
- 单次调用平均节省58%内存占用
- 错误完全隔离,单次失败不影响整体服务
- 避免守护进程的stdin/stdout连接问题
3. 开发中的关键技术挑战
3.1 YAML Front Matter陷阱
在SKILL.md定义中,YAML与Markdown混合使用时极易出错。以下是血泪教训:
错误示例:
yaml复制requirements: |
```bash
export KEY="value" # 会导致解析崩溃
code复制
**正确方案**:
```yaml
requirements: >-
配置步骤:
1. 设置环境变量 X_VARIFLIGHT_KEY
2. 安装Node.js 18+
经验:YAML中避免嵌套代码块,复杂示例应放在Markdown正文区域。
3.2 MCP协议深度适配
飞常准MCP有这些特殊要求:
- 必须使用
X_VARIFLIGHT_KEY作为密钥变量名 - 返回数据采用首字母大写的驼峰命名(如
FlightDeptimePlanDate) - 需要处理三种传输模式:
- stdio(默认)
- SSE(服务器推送)
- HTTP(兼容旧版)
3.3 航班数据智能解析
针对不同航司的数据差异,开发了智能字段匹配算法:
javascript复制function parseFlight(flight) {
return {
no: flight.FlightNo || flight.flightNo || '未知',
airline: flight.FlightCompany || flight.airlineName || '未知',
depTime: (flight.FlightDeptimePlanDate || '').split(' ')[1] || '待定'
}
}
4. 安全实施方案
4.1 密钥管理金字塔
建立三级密钥保护机制:
- 最高级:环境变量(生产环境)
bash复制export X_VARIFLIGHT_KEY="your_actual_key" - 中间级:本地配置文件(开发环境)
json复制// config.local.json {"apiKey": "dev_key"} - 基础级:示例配置(不含真实密钥)
json复制// config.json {"apiKey": "REPLACE_ME"}
4.2 防泄露措施
.gitignore强制排除敏感文件:code复制*.key *.pem .env config.local.json- 在SKILL.md中仅声明变量名:
yaml复制env: - X_VARIFLIGHT_KEY # 不填写实际值
5. 数据展示优化技巧
5.1 终端友好输出
javascript复制console.log(`🛫 ${depTime} ${depAirport}${depTerminal ? ' T'+depTerminal : ''}`);
console.log(`✈️ ${aircraft} | 准点率: ${ontimeRate || '未知'}`);
示例输出:
code复制1. CA1837 | 中国国际航空
🛫 08:20 PEK T3
🛬 11:15 SHA T2
✈️ A330 | 准点率: 89.5%
5.2 舒适度评估算法
结合多维度数据计算:
javascript复制function calcComfortScore(flight) {
const base = 60;
const rateScore = parseFloat(flight.OntimeRate) || 0;
const typeScore = aircraftScores[flight.ftype] || 0;
return base + rateScore*0.3 + typeScore*0.2;
}
6. 部署与发布全流程
6.1 环境准备清单
- Node.js ≥18.x
- OpenClaw CLI工具
bash复制
npm install -g clawhub - 飞常准开发者账号(申请MCP权限)
6.2 发布命令
bash复制clawhub publish . \
--slug variflight-aviation \
--name "航班助手" \
--version 1.0.0
6.3 用户调用示例
code复制@variflight-aviation search 北京 上海 2024-03-15
@variflight-aviation weather 浦东
@variflight-aviation track CA1837
7. 性能优化实践
7.1 缓存策略设计
javascript复制const cache = new Map();
async function getFlightWithCache(flightNo) {
if (cache.has(flightNo)) {
const { data, timestamp } = cache.get(flightNo);
if (Date.now() - timestamp < 300000) { // 5分钟缓存
return data;
}
}
const freshData = await fetchFlight(flightNo);
cache.set(flightNo, {
data: freshData,
timestamp: Date.now()
});
return freshData;
}
7.2 错误重试机制
javascript复制async function robustCall(toolName, args, retry = 3) {
for (let i = 0; i < retry; i++) {
try {
return await client.callTool({ name: toolName, arguments: args });
} catch (err) {
if (i === retry - 1) throw err;
await new Promise(res => setTimeout(res, 1000 * (i + 1)));
}
}
}
8. 扩展开发思路
8.1 自然语言理解增强
计划集成NLP模块以支持更灵活的查询:
code复制"帮我找明天下午北京到上海最便宜的航班"
"下周二早班机到深圳哪个准点率高"
8.2 多数据源融合
正在接入:
- 机场贵宾厅空余情况
- 高铁接驳时刻表
- 行李转盘实时状态
8.3 预警通知系统
基于SSE实现:
javascript复制client.on('flightChange', (event) => {
if (event.type === 'DELAY') {
sendNotification(`航班${event.flightNo}延误至${event.newTime}`);
}
});
这个项目让我深刻体会到,好的工具应该像称职的助理——不需要明确指令就能理解需求,在合适的时候提供恰到好处的信息。后续会继续优化智能推荐算法,让航班查询从"被动应答"变为"主动服务"。
