1. AI 接入
龙虾开放平台(通用版)
  • 欢迎语
  • 快速开始
    • 接入流程
    • 公共请求头
    • 注意事项
    • 速率限制与配额策略
    • 鉴权说明
    • 错误码
  • AI 接入
    • AI接入说明
    • MCP
    • Code Mode
  • 机票
    • 机票接口说明
    • 机场搜索
      GET
    • 创建机票订单
      POST
    • 机票验价
      POST
    • 机票查询列表
      POST
    • 发起支付
      POST
  • 酒店
    • 酒店接口说明
    • 酒店查询列表
      POST
    • 酒店房型详情
      POST
    • 创建酒店订单
      POST
  • 数据模型
    • response.Response
    • schema.AirportSearchResponse
    • schema.FlightOrderCancelRequest
    • schema.FlightOrderCancelResponse
    • schema.FlightCancelFeeResponse
    • schema.FlightOrderCreateRequest
    • schema.FlightOrderCreateResponse
    • schema.FlightOrderDetailRequest
    • schema.FlightOrderDetailResponse
    • schema.FlightOrderListRequest
    • schema.FlightOrderListResponse
    • schema.FlightOrderPayRequest
    • schema.FlightOrderPayResponse
    • schema.FlightPricingRequest
    • schema.FlightPricingResponse
    • schema.FlightSearchResponse
    • schema.HotelOrderCreateRequest
    • schema.HotelOrderCreateResponse
    • schema.HotelRoomsRequest
    • schema.HotelRoomsResponse
    • schema.HotelSearchRequest
    • schema.HotelSearchResponse
    • schema.AirportItem
    • schema.ContactInfo
    • schema.InvoiceAddress
    • schema.PassengerInfo
    • schema.FlightOrderInfo
    • schema.FlightOrderItem
    • schema.PageInfo
    • schema.PassengerFareItem
    • schema.FlightItem
    • schema.GuestInfo
    • schema.RoomType
    • schema.HotelSearchFilters
    • schema.HotelItem
    • schema.CabinFareItem
    • schema.RoomTypeProduct
  1. AI 接入

Code Mode

Code Mode 在 /open/v1/mcp/code 端点暴露 run_code 工具,Agent 写 JavaScript 在沙箱中编排多步 / 条件查询。


项目值
URLhttps://open.longxiachuxing.com/api/open/v1/mcp/code
方法POST
协议JSON-RPC 2.0(仅暴露 run_code 一个工具)
鉴权HMAC-SHA256 签名或 Bearer Token(与标准 REST 一致)
沙箱goja(Go 实现的 JavaScript 解释器),无网络 / 文件 / require

何时使用

场景MCP 标准模式Code Mode ✅
单步查询✅❌ 过度设计
多步依赖(验价 → 下单)⚠️ 多次往返✅ 一次沙箱搞定
条件判断(价格超 X 就查其他日期)❌ Agent 上下文浪费✅ 逻辑留在沙箱
循环筛选(遍历 20 个航班找最优)❌ 大 JSON 占上下文✅ 中间数据不出沙箱
组合查询(往返航班 + 酒店)⚠️ 多次工具调用✅ 一段脚本编排

原则:简单查询用 MCP 标准模式,复杂编排用 Code Mode。


沙箱能力

可用的 API

// 业务能力(与 MCP 标准模式工具一一对应)
rideclaw.flight.search(args)
rideclaw.flight.airport_search(args)
rideclaw.flight.pricing(args)
rideclaw.flight.order_create(args)
rideclaw.flight.order_pay(args)
rideclaw.flight.order_detail(args)
rideclaw.flight.order_list(args)
rideclaw.flight.order_cancel_fee(args)
rideclaw.flight.order_cancel(args)

rideclaw.hotel.search(args)
rideclaw.hotel.rooms(args)
rideclaw.hotel.order_create(args)

rideclaw.taxi.estimate(args)
rideclaw.train.search(args)
rideclaw.bus.search(args)

// 辅助工具
console.log(...)         // 日志输出(随 result.log 返回)
parallel([fn, fn, ...])  // 并发辅助(同步沙箱下顺序执行)

限制

限制项值超限行为
单次最大能力调用数20抛异常 "超过单次最大能力调用数 20"
执行超时30 秒VM 中断 "执行超时(30s)"
网络 / 文件 / require❌ 不可用编译/运行时错误

顶层 await

脚本自动包裹为 async IIFE,直接写 await:

// ✅ 正确
const result = await rideclaw.flight.search({ ... });
return result.flights[0];

// ❌ 错误(不需要手动 async function)
async function main() {
  const result = await rideclaw.flight.search({ ... });
  return result;
}
main();

调用方式

请求格式

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "run_code",
    "arguments": {
      "code": "const flights = await rideclaw.flight.search({trip_mode:'domestic',trip_type:'oneway',from_code:'SZX',to_code:'PEK',depart_date:'2026-06-12'});\nreturn flights.flights.slice(0,3);"
    }
  },
  "id": 1
}

关键字段:

  • params.name:固定为 "run_code"。
  • params.arguments.code:要执行的 JavaScript 代码(字符串)。

响应格式

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"value\":[...],\"tool_calls\":1,\"log\":[]}"
      }
    ],
    "isError": false
  }
}

result 字段:

  • value:脚本 return 的值(JSON 序列化)。
  • tool_calls:实际调用的能力次数。
  • log:console.log() 输出(数组)。
  • error:执行错误(编译失败 / 运行时异常)。

示例

1. 条件查询

场景:如果明天票价超 2000 元,就查后天的。

const tomorrow = await rideclaw.flight.search({
  trip_mode: "domestic",
  trip_type: "oneway",
  from_code: "SZX",
  to_code: "PEK",
  depart_date: "2026-06-12",
  passengers: { adult: 1 },
  page_size: 5
});

const minPrice = Math.min(...tomorrow.flights.map(f => 
  Math.min(...f.cabins.map(c => c.lowest_price))
));

if (minPrice > 2000) {
  console.log("明天价格超 2000,查后天");
  const dayAfter = await rideclaw.flight.search({
    trip_mode: "domestic",
    trip_type: "oneway",
    from_code: "SZX",
    to_code: "PEK",
    depart_date: "2026-06-13",
    passengers: { adult: 1 },
    page_size: 5
  });
  return {
    recommendation: "后天",
    min_price: Math.min(...dayAfter.flights.flatMap(f => f.cabins.map(c => c.lowest_price))),
    flights: dayAfter.flights.slice(0, 3)
  };
}

return {
  recommendation: "明天",
  min_price: minPrice,
  flights: tomorrow.flights.slice(0, 3)
};

能力调用数:最坏情况 2 次(明天 + 后天),最好 1 次(明天价格合适)。

响应示例:

{
  "value": {
    "recommendation": "后天",
    "min_price": 1850,
    "flights": [...]
  },
  "tool_calls": 2,
  "log": ["明天价格超 2000,查后天"]
}

2. 多步编排:验价 → 下单

场景:搜索后自动验价并下单。

const search = await rideclaw.flight.search({
  trip_mode: "domestic",
  trip_type: "oneway",
  from_code: "SZX",
  to_code: "PEK",
  depart_date: "2026-06-12",
  passengers: { adult: 1 }
});

const cheapest = search.flights[0].cabins[0];
console.log(`最低价舱位: ${cheapest.cabin_name} ${cheapest.lowest_price}元`);

const pricing = await rideclaw.flight.pricing({
  search_offer_id: cheapest.search_offer_id,
  passengers: [{
    type: "adult",
    name: "张三",
    id_type: "ID_CARD",
    id_number: "330106199001011234",
    phone: "13800138000"
  }]
});

const order = await rideclaw.flight.order_create({
  offer_id: pricing.offer_id,
  out_trade_no: `TEST_${Date.now()}`,
  passengers: pricing.passenger_fares.map((_, i) => ({
    type: "adult",
    name: "张三",
    id_type: "ID_CARD",
    id_number: "330106199001011234",
    phone: "13800138000"
  })),
  contact: {
    name: "张三",
    phone: "13800138000"
  }
});

return {
  system_no: order.system_no,
  total_amount: order.total_amount,
  status: order.status
};

能力调用数:3 次(搜索 + 验价 + 下单)。

3. 循环筛选

场景:找出前 20 个航班中起飞时间在 8:00-10:00 的直飞航班。

const search = await rideclaw.flight.search({
  trip_mode: "domestic",
  trip_type: "oneway",
  from_code: "SZX",
  to_code: "PEK",
  depart_date: "2026-06-12",
  passengers: { adult: 1 },
  page_size: 20
});

const filtered = search.flights.filter(f => {
  const depHour = parseInt(f.dep_time.split(" ")[1].split(":")[0]);
  return f.stop_count === 0 && depHour >= 8 && depHour < 10;
});

console.log(`筛选出 ${filtered.length} 个航班`);

return filtered.map(f => ({
  flight_no: f.flight_no,
  dep_time: f.dep_time,
  arr_time: f.arr_time,
  min_price: Math.min(...f.cabins.map(c => c.lowest_price))
}));

能力调用数:1 次(筛选逻辑在沙箱内完成,不占 Agent 上下文)。

4. 组合查询:往返航班 + 酒店

const outbound = await rideclaw.flight.search({
  trip_mode: "domestic",
  trip_type: "oneway",
  from_code: "SZX",
  to_code: "HGH",
  depart_date: "2026-06-12",
  passengers: { adult: 1 },
  page_size: 3
});

const inbound = await rideclaw.flight.search({
  trip_mode: "domestic",
  trip_type: "oneway",
  from_code: "HGH",
  to_code: "SZX",
  depart_date: "2026-06-14",
  passengers: { adult: 1 },
  page_size: 3
});

const hotels = await rideclaw.hotel.search({
  destination: "杭州西湖",
  check_in: "2026-06-12",
  check_out: "2026-06-14",
  page_size: 3
});

return {
  outbound: outbound.flights[0].flight_no,
  inbound: inbound.flights[0].flight_no,
  hotel: hotels.hotels[0].hotel_name,
  total_estimate: 
    Math.min(...outbound.flights[0].cabins.map(c => c.lowest_price)) +
    Math.min(...inbound.flights[0].cabins.map(c => c.lowest_price)) +
    hotels.hotels[0].min_price * 2
};

能力调用数:3 次(去程 + 返程 + 酒店)。


调试

console.log 输出

console.log("开始搜索航班...");
const result = await rideclaw.flight.search({ ... });
console.log(`找到 ${result.total} 个航班`);
return result.flights.slice(0, 3);

响应:

{
  "value": [...],
  "tool_calls": 1,
  "log": [
    "开始搜索航班...",
    "找到 42 个航班"
  ]
}

错误示例

语法错误:

const result = await rideclaw.flight.search({;  // 缺少右花括号

响应:

{
  "error": "SyntaxError: Unexpected token ';' at line 1",
  "tool_calls": 0
}

运行时错误:

const result = await rideclaw.flight.search({
  from_code: "INVALID"
});

响应:

{
  "error": "flight.search 调用失败: from_code 无效",
  "tool_calls": 1
}

Python 调用示例

import requests
import json

MCP_URL = "https://open.longxiachuxing.com/api/open/v1/mcp/code"
BEARER_TOKEN = "rdak_live_xxxxxxxx"

code = """
const tomorrow = await rideclaw.flight.search({
  trip_mode: "domestic",
  trip_type: "oneway",
  from_code: "SZX",
  to_code: "PEK",
  depart_date: "2026-06-12",
  passengers: { adult: 1 },
  page_size: 5
});

const minPrice = Math.min(...tomorrow.flights.map(f => 
  Math.min(...f.cabins.map(c => c.lowest_price))
));

if (minPrice > 2000) {
  const dayAfter = await rideclaw.flight.search({
    trip_mode: "domestic",
    trip_type: "oneway",
    from_code: "SZX",
    to_code: "PEK",
    depart_date: "2026-06-13",
    passengers: { adult: 1 },
    page_size: 5
  });
  return { recommendation: "后天", flights: dayAfter.flights.slice(0, 3) };
}
return { recommendation: "明天", flights: tomorrow.flights.slice(0, 3) };
"""

resp = requests.post(MCP_URL, json={
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
        "name": "run_code",
        "arguments": {"code": code}
    },
    "id": 1
}, headers={
    "Authorization": f"Bearer {BEARER_TOKEN}",
    "Content-Type": "application/json"
})

result = resp.json()
print(json.dumps(result, ensure_ascii=False, indent=2))

最佳实践

1. 提前返回,减少调用

// ✅ 好:找到一个符合条件的就返回
for (const flight of flights) {
  if (flight.cabins[0].lowest_price < 1000) {
    return flight;
  }
}

// ❌ 差:遍历完所有航班再返回
const cheap = flights.filter(f => f.cabins[0].lowest_price < 1000);
return cheap[0];

2. 避免无限循环

// ❌ 错误:沙箱会在 30 秒超时
while (true) {
  await rideclaw.flight.search({ ... });
}

// ✅ 正确:设置最大次数
let attempts = 0;
while (attempts < 5) {
  const result = await rideclaw.flight.search({ ... });
  if (result.flights.length > 0) break;
  attempts++;
}

3. 利用 console.log 调试

console.log("搜索参数:", JSON.stringify(params));
const result = await rideclaw.flight.search(params);
console.log("返回航班数:", result.total);

Agent 可以根据 log 判断脚本执行到哪一步、中间数据是什么。

4. 错误处理

try {
  const result = await rideclaw.flight.search({ ... });
  return result.flights[0];
} catch (e) {
  console.log("搜索失败:", e);
  return { error: "未找到航班" };
}

沙箱内能力调用失败会抛异常,用 try/catch 捕获后可自定义返回值。

5. 分页处理

const page1 = await rideclaw.flight.search({ ..., page: 1, page_size: 20 });
const page2 = await rideclaw.flight.search({ ..., page: 2, page_size: 20 });

const allFlights = [...page1.flights, ...page2.flights];
return allFlights.slice(0, 10);

注意能力调用数限制(20 次),不要无限分页。


常见问题

Q: Code Mode 比 MCP 标准模式慢吗?

A: 略慢(+50~200ms 沙箱启动开销),但多步编排场景下总耗时更短:

  • MCP 标准模式:多次 Agent → 平台往返(每次 100~300ms)
  • Code Mode:一次往返,逻辑在沙箱内编排(本地 JS 执行 <10ms)

Q: 沙箱支持 ES6+ 语法吗?

A: 部分支持。goja 基于 ES5.1,但支持 const/let/箭头函数/模板字符串/解构赋值。不支持 async/await(已由沙箱自动包裹)、class(用普通函数代替)、import/export(无模块系统)。

Q: 能力调用数超过 20 怎么办?

A: 拆分成多次 run_code 调用,或切回 MCP 标准模式单步调用。Code Mode 适合中等复杂度(3~15 次调用)的编排场景。

Q: 沙箱能访问外部 API 吗?

A: 不能。沙箱无网络、无文件,唯一 I/O 是注入的 rideclaw.* 能力。如需调用外部 API,在 Agent 侧完成后把结果传入脚本。

Q: 脚本能持久化变量吗?

A: 不能。每次 run_code 都是全新 VM,状态不保留。需要跨次调用的数据由 Agent 在上下文中维护。


与 MCP 标准模式对比

维度MCP 标准模式Code Mode
工具数量15 个(按业务线拆分)1 个(run_code)
调用次数每个问题可能多次工具调用一次沙箱执行多次内部调用
Agent 上下文每次工具调用占用上下文中间数据留在沙箱
适用场景简单查询、单步操作多步编排、条件判断、循环筛选
延迟单步快(50~200ms)首次慢(+沙箱启动),多步总体快
调试工具调用日志console.log + result.log
错误恢复Agent 自我修正参数脚本 try/catch 或 Agent 修正代码

选择建议:从 MCP 标准模式起步,遇到 3 步以上编排或条件判断时切换到 Code Mode。

修改于 2026-06-12 02:46:36
上一页
MCP
下一页
机票接口说明
Built with