☰
三天上线AI旅游规划产品:MCP协议+Next.js+GPT-4o实战
2026/10/9 0:25:14 网站建设 项目流程

1. 为什么我盯上了MCP这条技术路线

先说清楚背景。我一个人,三天时间,从零开始做了一个AI旅游规划产品,并且把它推上线了。这不是标题党,产品现在能跑,用户输入目的地、天数、预算和偏好,它会自动生成一份带日程、交通建议、住宿区域推荐和预算拆解的完整旅行方案。整个项目的技术底座是MCP协议加Next.js加GPT-4o,开发周期压缩到72小时以内。

很多人第一次听到MCP会问“mcp是什么”。用一句话解释:MCP(Model Context Protocol)是一套让大模型和外部工具、数据源之间标准化对话的协议。你可以把它理解成AI世界的USB-C接口——以前每接一个工具就要写一套适配代码,现在只要工具端实现了MCP Server,AI端实现了MCP Client,两边就能即插即用。这个类比不精确但足够让你理解它的价值所在。

我为什么选MCP而不是传统的Function Calling硬编码?原因很实际。旅游规划这个场景天然需要串联多个数据源:景点信息、天气、地图距离、酒店价格区间、餐厅推荐。如果每个数据源都手写function schema,光是维护参数格式就能把我三天时间吃光。而MCP把这些能力抽象成标准化的工具调用,我只需要关注“调用哪个工具”和“怎么组织结果”,不用关心底层接口长什么样。

这个产品适合谁参考?如果你是独立开发者,想快速验证一个AI Agent产品的可行性,这套方案可以直接抄。如果你是有前端基础但没怎么碰过Agent开发的工程师,MCP的上手曲线比你想的平缓。如果你只是对AI旅游规划这个方向感兴趣,也可以看看我是怎么把一个大而全的需求拆成三天能交付的MVP的。

提示:MCP目前生态还在快速演进,不同客户端对协议版本的支持程度不一样。动手前先确认你用的SDK版本和Server端的兼容性,否则会在调试上浪费大量时间。

2. 三天上线的整体架构与选型逻辑

2.1 为什么是Next.js而不是纯后端方案

时间只有三天,我不可能同时搞前端和后端两套工程。Next.js的App Router模式让我在一个项目里同时写页面和API Route,部署时Vercel一键推上去,省掉了服务器配置、Nginx反向代理、HTTPS证书这些琐事。对于一个人三天上线的目标来说,任何需要额外运维的动作都是奢侈品。

具体来说,我用Next.js 14的App Router组织代码。前端页面负责收集用户输入和展示规划结果,API Route负责跟GPT-4o和MCP Server通信。流式输出用Vercel AI SDK的streamText能力,用户能看到规划内容一个字一个字蹦出来,体验上比等十秒然后一次性刷新好太多。

这里有个选型细节值得展开。Vercel AI SDK原生支持工具调用(tool calling),而MCP的工具发现和调用可以封装成AI SDK的tool定义。也就是说,我不需要自己写一套MCP Client的底层通信逻辑,而是把MCP Server暴露的工具转成AI SDK能识别的格式,剩下的交给SDK处理。这个转换层大概花了半天时间调试,但后面所有工具接入都变得极其顺畅。

2.2 MCP Server的拆分策略

旅游规划涉及的能力我拆成了三个MCP Server:

  • 景点与活动Server:负责根据目的地和偏好返回景点列表、开放时间、建议游玩时长
  • 交通与地理Server:负责计算景点间距离、推荐交通方式、估算通勤时间
  • 预算与住宿Server:负责根据预算档位推荐住宿区域、拆解各项花费占比

为什么拆成三个而不是一个大Server?因为MCP的设计哲学就是每个Server专注一个领域,工具描述清晰、参数边界明确。如果全塞在一起,GPT-4o在选择工具时容易混淆,比如把“计算距离”的参数传给“查景点”的工具。拆开之后,每个Server的工具数量控制在3到5个,模型选择准确率明显提升。

注意:MCP Server的命名和工具描述直接影响模型调用准确率。工具名要用动词开头,描述要写清楚“什么时候该用这个工具”,而不是只写“这个工具能做什么”。

2.3 GPT-4o在链路中的角色定位

GPT-4o在这个产品里承担两个职责:一是理解用户自然语言输入并提取结构化参数(目的地、天数、预算、偏好标签),二是根据MCP工具返回的数据组织成人类可读的旅行方案。它不直接生成景点信息,因为大模型编造景点开放时间和门票价格是出了名的不可靠。所有事实性数据必须来自MCP工具,GPT-4o只负责调度和表达。

这个分工很关键。我见过不少AI旅游产品让模型直接“编”行程,结果用户到了现场发现景点闭馆或者餐厅不存在。MCP的价值就在于把“事实查询”和“语言组织”分开,模型只做它擅长的事。

3. 核心环节的实操细节与参数配置

3.1 MCP Client的初始化与工具发现

在Next.js的API Route里初始化MCP Client,核心代码如下:

import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; const transport = new StdioClientTransport({ command: "node", args: ["./mcp-servers/spots-server/index.js"], }); const client = new Client( { name: "travel-planner", version: "1.0.0" }, { capabilities: {} } ); await client.connect(transport); const { tools } = await client.listTools();

这段代码做了三件事:建立与MCP Server的传输通道、初始化Client实例、拉取Server暴露的工具列表。listTools()返回的tools数组里每个工具都有name、description和inputSchema,这三个字段直接决定了GPT-4o能不能正确调用。

我踩过的一个坑:StdioClientTransport在Serverless环境(比如Vercel的Edge Function)里跑不起来,因为Serverless不允许长期运行的子进程。解决办法是把MCP Server部署成独立的HTTP服务,用SSEClientTransport或者Streamable HTTP Transport连接。这个改动花了我大概两个小时,但换来的是部署后稳定运行。

3.2 把MCP工具转成GPT-4o能识别的格式

MCP的工具定义和OpenAI的function calling格式不完全一样,需要做一层转换。核心映射关系是:MCP的inputSchema直接对应OpenAI的parameters,MCP的description对应OpenAI的description,工具名保持一致。

const openAITools = tools.map((tool) => ({ type: "function" as const, function: { name: tool.name, description: tool.description, parameters: tool.inputSchema, }, }));

转换本身不复杂,但有个细节要注意:MCP的inputSchema是JSON Schema格式,而OpenAI对JSON Schema的支持有一些限制,比如不支持oneOf和anyOf的嵌套。如果你的工具参数用了这些结构,需要在转换时做扁平化处理。我的做法是尽量让工具参数保持简单,用枚举值代替联合类型,用可选字段代替条件分支。

3.3 流式输出与工具调用的协同

流式输出和工具调用同时存在时,处理逻辑会复杂一些。用户看到的是文字在流式生成,但中间模型可能突然决定调用一个工具,这时候流会暂停,等工具返回结果后再继续。Vercel AI SDK的streamText已经处理了这种情况,我只需要在onStepFinish回调里记录每一步的工具调用情况,方便调试。

const result = streamText({ model: openai("gpt-4o"), messages, tools: openAITools, maxSteps: 8, onStepFinish: ({ toolCalls, toolResults }) => { console.log("工具调用:", toolCalls); console.log("工具结果:", toolResults); }, });

maxSteps设成8是一个经验值。旅游规划通常需要调用5到7次工具(查景点、查距离、查住宿、查预算等),设太小会导致规划不完整,设太大又浪费token。实测下来8步能覆盖90%以上的规划请求。

提示:工具调用的顺序会影响最终方案质量。我建议在System Prompt里明确告诉模型“先查景点,再算距离,最后算预算”,这样生成的行程在逻辑上更连贯。

3.4 System Prompt的设计要点

System Prompt是决定输出质量的关键。我改了大概十几版,最终稳定下来的结构是这样的:

你是一个专业的旅行规划师。你的任务是帮用户生成一份可执行的旅行方案。 工作流程: 1. 先从用户输入中提取:目的地、天数、预算档位、偏好标签 2. 调用景点工具获取候选景点列表 3. 调用距离工具计算景点间通勤时间 4. 根据通勤时间把景点分配到每天,每天不超过4个景点 5. 调用住宿工具推荐住宿区域 6. 调用预算工具拆解花费 7. 用中文输出完整方案,包含每日日程、交通建议、住宿推荐、预算表 约束: - 不要编造工具未返回的信息 - 如果工具返回空结果,如实告知用户并建议调整偏好 - 每天的行程要留出用餐和休息时间 - 预算拆解要具体到交通、住宿、餐饮、门票四项

这个Prompt里最重要的是“工作流程”部分。它把模型的思考过程显式地规定下来,减少了模型自由发挥导致的不稳定。另外“约束”部分也很关键,明确禁止编造信息,这是保证产品可信度的底线。

4. 开发过程中踩过的坑与排查实录

4.1 MCP Server启动超时

第一次跑通链路时,API Route调用MCP Server经常超时。排查后发现是StdioClientTransport启动子进程需要时间,而Serverless函数的冷启动叠加子进程启动,总耗时超过了默认超时限制。解决办法有两个:一是把MCP Server改成HTTP服务常驻运行,二是给Client连接设置更长的超时时间并加retry逻辑。我最终选了第一种,因为常驻服务还能复用连接,减少每次请求的握手开销。

4.2 工具调用参数格式错误

GPT-4o有时候会把日期参数写成“2024-01-01”有时候写成“Jan 1, 2024”,导致MCP Server解析失败。这个问题不能靠改Prompt完全解决,因为模型对日期格式的理解本身就不稳定。我的做法是在MCP Server端做参数归一化,用日期解析库把各种格式统一转成ISO 8601。同时在工具描述里明确写“日期格式为YYYY-MM-DD”,双管齐下后错误率降到几乎为零。

4.3 流式输出中断

用户反馈规划生成到一半突然停了。查日志发现是某个MCP工具返回的数据量太大,超过了模型单次处理的token上限。解决办法是在MCP Server端做分页,每次最多返回10条景点信息,如果用户需要更多再调用一次。这个改动同时也提升了响应速度,因为模型不用等一个巨大的JSON返回。

4.4 常见问题速查表

问题现象可能原因排查方向解决方案
工具调用返回空Server未正确注册工具检查listTools返回确认Server启动日志无报错
模型不调用工具工具描述不清晰查看工具description补充“何时使用”说明
流式输出卡住工具返回数据过大检查工具返回体大小分页返回,单次限10条
部署后连接失败Serverless不支持子进程查看部署环境限制改用HTTP Transport
预算计算偏差大模型自行估算检查是否调用了预算工具在Prompt中强制调用

4.5 实操心得:先跑通再优化

三天时间做产品,最大的敌人是完美主义。我第一天的目标是“链路能跑通”,哪怕输出质量很差。第二天才优化Prompt和工具描述。第三天做UI和部署。如果第一天就纠结于输出格式好不好看,大概率三天结束还在调Prompt。先让数据从用户输入流到最终输出,再逐步替换每个环节的质量,这个节奏对独立开发者来说非常重要。

另一个心得是日志要打够。MCP的工具调用是黑盒,模型为什么选这个工具不选那个,只能通过日志推断。我在每个工具调用的入口和出口都打了日志,记录参数和返回摘要。调试阶段这些日志帮我省了至少半天时间。

5. 上线部署与后续扩展方向

5.1 部署清单与检查项

部署到Vercel的流程不复杂,但有几个检查项必须过一遍:

  • 环境变量:OpenAI API Key、MCP Server的HTTP地址,都要在Vercel后台配好
  • MCP Server独立部署:我用的Railway部署三个MCP Server,每个都是轻量Node服务
  • 超时设置:Vercel的Serverless函数默认10秒超时,流式输出需要改成Edge Runtime或者升级Pro计划
  • 域名和HTTPS:Vercel自动处理,不用操心

上线后我监控了两天,主要看两个指标:规划生成成功率和平均生成时长。成功率稳定在95%以上,失败的主要原因是用户输入太模糊(比如只写“帮我规划一下”没写目的地),模型无法提取参数。平均生成时长在12到18秒之间,流式输出让用户感知的等待时间短很多。

5.2 这个架构还能怎么扩展

MCP的插件化特性让扩展变得很容易。如果想加“实时航班查询”,只需要再写一个MCP Server暴露航班查询工具,然后在Client端注册进去,GPT-4o会自动发现新工具并在合适的时候调用。不需要改主流程代码,这是MCP相比硬编码Function Calling最大的优势。

另一个扩展方向是多Agent协作。现在的架构是单Agent串行调用工具,如果规划复杂行程(比如跨国多城市),可以拆成“景点Agent”“交通Agent”“预算Agent”并行工作,最后汇总。MCP协议天然支持这种多Server并行调用的模式,只是需要在Client端做结果聚合。

5.3 给想复现的朋友几个实在建议

如果你打算照着这个思路做,我的建议是先把MCP的官方文档过一遍,理解Client和Server的通信模型。然后从一个最简单的MCP Server开始(比如只提供一个echo工具),跑通“模型调用工具并返回结果”的完整链路。这一步通了,后面加工具只是重复劳动。

工具描述要反复打磨。我每个工具的description至少改了五版,每次都是发现模型调用错误后回去改。工具描述写得好,模型调用准确率能到95%以上;写得模糊,准确率可能只有60%。这个投入产出比非常高。

最后,不要低估部署环节的时间。我原本以为部署半小时搞定,实际花了将近半天,主要卡在Serverless环境和MCP Server的兼容性上。如果你也用Vercel,建议直接上Edge Runtime加HTTP Transport的方案,少走弯路。

我在实际使用中发现,MCP生态的工具链还在快速迭代,今天能跑的方案下个月可能就有更优解。保持关注官方SDK的更新,但不要为了追新而重构已经稳定的链路。产品能跑、用户能用,比技术栈先进一步重要得多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询