news 2026/10/2 20:24:52

MCP实战:3天开发AI旅游规划产品并上线的完整复盘

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MCP实战:3天开发AI旅游规划产品并上线的完整复盘

上个月我干了一件以前得花两周才能搞定的事:一个人,3天,做了一个AI旅游规划产品并上线。不是那种套壳聊天机器人,是真的能根据你输入的目的地、天数、预算和偏好,帮你排出带天气、带交通、带餐厅推荐的每日行程。整个过程的核心支撑就一个东西——MCP(Model Context Protocol,模型上下文协议)。如果你正在做AI应用,或者好奇为什么2025年MCP会被叫成“AI应用的USB-C接口”,这篇文章就是我的完整实战复盘,从产品设计、技术选型,到每一个踩过的坑,都会尽量讲透。

先说结论:MCP让“AI能自己决定什么时候去拿数据”这件事变得极其简单。以前我要写一堆接口、定义一堆JSON Schema、处理多轮工具调用的状态流转;现在,我把工具封装成一个MCP Server,大模型会自动学会怎么用这批工具。下面我把3天里做的事拆开讲,希望能给同样在独立开发AI产品的人一点参考。

1. 我为什么选MCP,以及它到底解决了什么问题

1.1 没有MCP时,做AI应用累在哪

想做一个AI旅游规划产品,最朴素的思路是:前端收集用户输入,后端调用大模型API,让它生成一份行程。但这有个硬伤——大模型的训练知识有截止日期,它不知道峨眉山今天的天气、不知道这周杭州有哪些展览、更不知道从灵隐寺到宋城打车要多久。所以要给它“接上数据”,传统做法很繁琐。

我拆了下,不用MCP时需要干这些事:

  • 为每个数据源写独立的HTTP调用封装,比如天气接口、POI搜索接口、路径规划接口;
  • 为每个接口再写一份Function Calling的JSON Schema,告诉模型这个函数叫什么、参数是什么、返回什么;
  • 在业务代码里手动管理“模型想调用哪个函数、参数是否合法、返回结果怎么塞回上下文”的全过程;
  • 如果换一个模型,比如从GPT换到国产模型,函数定义语法可能还要改一遍;
  • 想复用这套能力到别的场景,比如做个网页版、做个小程序版,又得把工具层再包装一次。

这些不是写不出来,而是太耗时间。一个人做产品,时间是最贵的。对3天这个目标来说,传统做法根本行不通。

1.2 MCP把“接数据”这件事标准化了

MCP是Anthropic在2024年11月底开源的一个开放协议,全称Model Context Protocol,设计目标很明确:让AI模型与外部工具、数据源之间的连接变得标准化。你要是用过USB-C口,就很好理解MCP——以前各种设备充电口五花八门,现在一个口解决所有连接问题。MCP做的事情类似:任何支持MCP的AI客户端,都能通过同一套协议去调用任何支持MCP的Server,不管底层是什么数据源、什么API。

MCP的核心概念其实没几个,第一次接触时不要被“协议”两个字吓住:

  • MCP Server:提供工具、资源、提示词的一方。比如我的旅游规划Server,里面封装了天气查询、POI搜索这些能力;
  • MCP Client:连接Server的一方。Claude Desktop、Codex,以及我自己写的FastAPI后端,都是Client;
  • Tool(工具):最常用的一类能力,给模型“动手”的机会,比如查询天气、查询景点;
  • Resource(资源):给模型“读取”的上下文,比如一份景区介绍文档,一个本地文件;
  • Prompt(提示词模板):在Server端预置了可复用的提示词,调用方一键使用;
  • Transport(传输方式):Server和Client之间的连接通道,本地常用stdio,远程服务用HTTP。

这套分层设计让我省了大量时间。我的Server写一次,Claude Desktop可以连,我自己写的Web应用可以连,后续如果想让Codex也具备这个能力,只要给Codex配一下Server地址就行。之前说过想试一试idea插件通义灵码接MCP,其实也是一样的思路——工具层独立出来以后,接谁都是一行配置的事。

1.3 MCP和Function Calling不是一回事

很多人会把MCP和Function Calling(函数调用)混在一起,我这里纠正一下:Function Calling是模型API提供的一种能力,让模型在生成文本时输出一个结构化的函数调用请求;MCP则是Client与工具之间的通信协议。你可以理解成Function Calling是“模型内部的一种动作表达”,MCP是“模型所在的应用与外部工具之间的标准化管道”。

也就是说,MCP并不替代Function Calling,它是在Function Calling之上的规范。模型做决策(比如“现在该查天气了”),MCP负责把决策变成实际的数据请求,再把结果送回模型的上下文。说得更直白点:没有MCP时,我需要为每个模型手写函数定义;有MCP后,这些定义只在Server里声明一次,模型通过Protocol就能理解这些工具的描述和参数结构。

这也是为什么我在第二天能腾出时间做业务逻辑和前端。底层数据接入被MCP标准化以后,我不需要反复调试“为什么模型不按我定义的参数格式传值”这种蠢问题,而可以把精力放在用户真正会用到的东西上。

2. 产品设计与技术选型:先想清楚3天能做多少事

2.1 需求边界:不做什么比做什么更重要

独立开发最忌讳一开始就铺很大。我第一天上午在纸上写了一句话需求:用户输入目的地、游玩天数、出行偏好和预算档位,系统输出一份包含天气提醒、景点安排、交通耗时和餐厅推荐的行程单。功能就做这三步:表单填写、生成中状态、展示行程。什么注册登录、支付、社区、多语言,全部砍掉,将来再补。

这是3天交付的核心经验:把产品切成一个“看起来完整、用起来顺手”的闭环,但内部只保留最必要的逻辑。对于AI产品来说,行程单页面一定把“下载/分享”做进去,因为用户最自然的动作就是把规划结果发给朋友。我用了一份简单的分享链接页面,后端存SQLite,一URL就完事。

砍掉不重要的功能,不是为了偷懒,而是为了给“生成质量”留出足够的时间。同一个请求,模型第一次可能生成四天行程,第二次可能生成三天,我怎么对齐?这些问题比注册登录难得多,必须留时间。

2.2 技术栈清单与选型理由

定方案那一刻我其实是抄自己的旧作业,但有几处是专门为MCP做的选择。整体技术栈如下:

层级方案选择理由
MCP ServerPython + FastMCP(官方SDK)生态最成熟,FastMCP语法糖写工具效率高
业务后端FastAPI异步天然适合转发大模型请求,和MCP Client在同一进程方便调试
数据源高德开放平台 Web服务API覆盖天气、POI、路径规划,免费配额够个人项目用
存储SQLite单文件、零运维,不需要扛高并发
前端Vue3 + Vite + Element Plus表单和卡片类UI开发最快,我熟
部署一台2C4G云服务器 + Nginx + PM2成本可控,生态稳,重启恢复快

选型逻辑很简单:官方的坑最少,免费的配额最够用,部署最省事。MCP Server本来可以用TypeScript写,但我的核心业务在Python侧,FastAPI调用工具链最自然,所以直接用Python SDK。高德开放平台的API文档虽然老,但它同时提供天气、POI搜索和路径规划,一个Key全搞定,这对个人项目很友好。

数据库方面SQLite是有点寒酸,但一个记录行程的小系统根本不需要MySQL。预算是无限膨胀的,流量是慢慢来的,先把闭环跑通比什么都强。

2.3 我定义的5个MCP工具

MCP Server不是越复杂越好,工具要“少而精”,每一个都有明确用途。我设计的第一版工具集:

工具名输入参数数据来源输出内容
get_destination_overview城市名高德行政区划+POI聚合城市介绍、最佳旅行季节、消费水平标签
get_weather_forecast城市名、天数高德天气API逐日天气现象、温度范围、风力、降水概率
get_poi_list城市名、关键词、POI类型高德POI搜索景点/餐厅/购物点名称、评分、地址、经纬度
get_transport_time起点经纬度、终点经纬度、出行方式高德路径规划2.0预计耗时、距离、方案概要
build_route_suggestion景点列表、游玩天数本地聚类算法按天分割的分区建议、每日动线顺序

设计这些工具有几条原则:职责单一,一个工具只做一件事,别搞“超级工具”;参数少,最好不超过4个,参数越多模型越容易传错;返回精简,每次返回给模型的内容控制在2000字以内,否则会撑爆上下文;失败信息要明确,比如城市查不到就返回“未找到该城市,请检查名称”而不要抛堆栈。

有一件事必须强调:工具的description是写给模型看的,不是写给程序员看的。你得用人话写清楚“什么场景下调用它,参数怎么传”。比如get_transport_time的描述不能只写“计算交通时间”,而要写“当用户希望知道两地之间如何通行、需要估算交通耗时与距离时使用,起点终点请传经纬度”。很多AI应用翻车就翻在描述写得太抽象,模型根本不知道什么时候该用这个工具。

3. 实操记录:从第1天写代码到第3天部署上线

3.1 第1天:把MCP Server跑通,先写两个核心工具

第1天我目标很小:先把MCP Server启动起来,能把天气和POI这两个工具调通就算赢。FastMCP的代码比我想象的简洁,一个工具就是一个函数加一个装饰器:

from mcp.server.fastmcp import FastMCP mcp = FastMCP("travel-planner") @mcp.tool() def get_weather_forecast(city: str, days: int = 7) -> str: """查询指定城市未来N天的天气预报,返回JSON字符串,包含日期、天气现象、最高/最低温度、降水概率。""" import requests params = { "key": WEATHER_API_KEY, "city": city, "extensions": "all", } resp = requests.get("https://restapi.amap.com/v3/weather/weatherInfo", params=params, timeout=10) data = resp.json() # 做数据清洗和截断,再返回给模型 return json.dumps( {"city": data.get("city"), "forecast": data.get("forecasts", [])}, ensure_ascii=False, ) @mcp.tool() def get_poi_list(city: str, keyword: str, poi_type: str = "风景名胜") -> str: """搜索指定城市与关键词相关的POI信息,返回名称、评分、地址、经纬度列表。""" ...

实测下来,FastMCP这个语法糖让工具开发体感接近零门槛。你只要写好函数的类型注解和docstring,组件的注册、参数的JSON Schema生成、返回序列化,SDK全帮你干了。上午写好这两个工具后,我直接用MCP Inspector做了测试——这是官方提供的一个可视化调试工具,能直接连上Server、看到有哪些工具、手动调用工具并检查返回。

下午我开始思考一个细节:模型的工具调用不会每次都按我想象的顺序来。有时候它先调POI搜索,发现需要天气来建议“明天是否适合户外”,又回头调天气。这意味着Server要支持并发调用和快速响应,每个工具都要有超时保护。我给所有外部HTTP请求设置了10秒超时,一旦高德API抽风,工具立刻返回一个友好的错误提示,而不是让模型干等。

第一天的成果是:MCP Server已经能在stdio模式下跑通,Claude Desktop配置一下mcpServers就能用,我在对话框里直接问“杭州明天适合穿什么”,它自动调用了天气工具。这个瞬间让我觉得路子对了。

3.2 第2天:解决LLM与工具的协作问题,把数据“翻译”成行程

第2天是整个过程最烧脑的一天,因为工具能用了是一回事,生成一份像样的行程是另一回事。这里有一个核心设计:底层MCP工具负责拿数据,上层业务负责编排,大模型负责“翻译”。

我用了一个三层架构:

  • 第一层是MCP工具层,就是前一天写好的那些能力,纯数据获取,不做业务判断;
  • 第二层是行程编排服务(FastAPI),负责接收前端参数,维护会话状态,调度MCP工具并把结果整理成结构化中间数据;
  • 第三层是生成层,通过System Prompt告诉大模型“你手里有哪些数据,你要按什么格式输出行程”。

这里的关键问题是:怎么让模型别把工具返回的JSON原样贴出来,而是转化成人类读得懂的行程文案?我给System Prompt写了这样一段话:

你是一名资深旅行规划师。根据下面的实时数据(天气、POI、交通耗时)生成一份每日行程,格式为:日期、天气概述、上午/下午/晚上安排、餐厅推荐、交通提示、当日注意事项。不要直接输出JSON,所有数据须转换为自然语言和建议。若某数据缺失,请明确说明并给出替代建议。

光靠这段还不够,因为模型可能会在生成过程中“自作聪明”地编造一些不存在的景点。我为这事想了个笨办法:先让模型写行程骨架(每天去哪个区域、玩什么类型),再调用工具拿数据,最后拿着真实数据做修正与润色。这不是一次Prompt能解决的,而是分两轮。第一轮生成骨架时我还会顺便拿到POI名单,第二轮把名单交给get_poi_list去查真实评分,再用“这些是真实数据,请根据它们调整行程”的方式发回模型。

这个“数据回流”设计很重要,直接决定产品是否可信。AI旅游产品最怕的就是推荐一个已经倒闭的餐厅、说一个错误开放的景点,有了工具校验这一层,至少能把幻觉压到最低。

同时第2天下午我搭了前端。表单页用了Vue3 + Element Plus,字段只有四个:目的地、天数、偏好标签(美食/人文/自然/亲子)、预算档位。提交后进入生成中状态,后端用SSE(Server-Sent Events)把“当前在查天气”“当前在找景点”等进度推给前端,这比让用户干等30秒体验好得多。进度提示是纯前端营销式的,但确实能显著降低焦虑感。

当天成果是一个能跑通全链路的Demo:用户输入“成都、3天、美食+自然、预算中等”,差不多40秒后看到一份包含每日天气、景点动线、餐厅推荐和交通建议的行程单。第一版仍然有不少问题,比如生成结果不稳定、偶尔会漏掉晚上的安排,但链路通了,后面要修就有方向了。

3.3 第3天:部署上线,远程HTTP Transport切换与真实用户测试

第3天上午做的第一件事,是把MCP Server从stdio模式切成streamable-http模式。本地调试用stdio没有问题,就是直接由父进程拉起子进程通信,但线上部署必须让FastAPI进程通过网络协议去访问MCP Server,所以得让Server监听一个端口。

不同版本SDK的命令略有差异,我用的版本大致是:

python travel_mcp_server.py --transport streamable-http --port 9000

然后在FastAPI侧,不再用本地方便的StdioServerParameters,而是通过MCP的HTTP客户端去连:

from mcp.client.streamable_http import streamablehttp_client async with streamablehttp_client("http://127.0.0.1:9000/mcp") as (read, write): async with ClientSession(read, write) as session: await session.initialize() tools = await session.list_tools() # 后续通过 session.call_tool(...) 调用具体工具

这里有个坑:尽管是“远程序列化”,MCP Server和FastAPI我直接部署在同一台服务器上,走内网HTTP。千万不要把它暴露到公网,除非你做了完整的鉴权。MCP这种能调用工具的接口,一旦裸奔被人扫到,风险极大。我在Nginx层做了IP白名单,同时MCP Server启动时校验一个自定义请求头,只有业务后端知道这个头存在。

部署的整体结构长这样:Nginx监听80/443,把 /api 路径反向代理到FastAPI的8000端口,另外转发静态前端文件。FastAPI里存了一份MCP ClientSession的异步连接池,按会话维度创建,避免多个用户请求共用一个Session导致协议状态冲突。

server { listen 443 ssl; server_name yourdomain.com; location /api/ { proxy_pass http://127.0.0.1:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { root /var/www/plantrip; try_files $uri $uri/ /index.html; } }

HTTPS我用certbot一次性申请,几分钟就搞定。环境变量如高德Key、模型API Key全部写进.env文件,用PM2的--env-file参数加载,绝不能写死进代码。

下午我把链接发给几个朋友试,反馈集中在两个问题:一是“生成时间还是太慢”,二是“偶尔生成的行程里会出现半天空白”。前者主要是模型返回耗时+多轮工具调用叠加导致的,我在业务层加了超时控制和缓存,同一城市同一季节的天气与POI数据缓存一小时,第二次访问明显提速;后者是因为模型两次生成的模板不稳定,我在System Prompt里给了更严格的每日模板和“若某时间段无安排也要输出建议或休息”的约束,基本解决了。

上线那一刻其实没有什么仪式感,只是把域名解析一改,Nginx reload,然后刷新页面真实验证了一遍。当我自己输入数据看到一份完整行程的时候,才确认这个3天极限目标真的完成了。

4. 常见问题排查与独立开发心得

4.1 高频问题速查表

3天里遇到各种问题,我挑几个典型的列出来,方便大家照方抓药:

问题现象根本原因解决办法
模型拿到工具返回结果却不理解工具description写得抽象,模型不知道何时调用重写description,说清“何时用、参数怎么传”,附一个使用示例
工具调用超时外部API响应慢所有HTTP请求设10秒超时;外部返回值在进入上下文前先清洗截断
同一个请求里模型连调了7次工具工具粒度太细,模型需要多次尝试才能攒够数据合并同类型工具,按区域批量返回;减少模型调用次数
返回的JSON在对话里被原样输出缺少“把数据转成自然语言”的约束在System Prompt里强约束输出格式,并用第二轮润色修正
多用户同时使用时偶发状态串线共用了一个MCP ClientSession按请求维度分配独立Session,连接池复用但状态隔离
模型推荐了不存在的景点大模型幻觉+未用工具校正先规划骨架,再查POI,再润色修正,不让模型凭空发挥

这里我想专门提一句Browser Use MCP和Playwright MCP的区别,因为最近问这个的人很多。Browser Use MCP的核心定位是“让AI操作浏览器去完成真实任务”,比如自动刷网页、抓取动态内容,它把浏览器变成了模型的手脚;Playwright MCP则是把Playwright测试框架的能力暴露给模型,重点在“写断言、跑用例、定位网页元素”这类质量保障场景。前者适合做数据采集和网页操作,后者适合做自动化测试。我只能说“工具选型要看你的目标到底是完成业务流程还是证明页面能用”,这两个很容易因为都能控制浏览器而被混淆,但实际上解决的问题不同。

4.2 3天赶工的几条实操心得

如果让我总结这次独立开发的非技术心得,第一条是上午写核心、下午接依赖、晚上记笔记。第一天上午我的MCP Server已经跑通,第二天上午在写最难的数据回流逻辑,第三天上午在做部署切换。每天下午都很痛苦,都在和外部接口、环境配置捉迷藏,这时候不要硬扛,出去走15分钟再回来,问题往往一下就看清了。

第二条心得是给外部API加一层缓存和降级。高德的免费配额是有每日上限的,一旦被刷爆,整个产品就废了。我在POI和天气工具外层包了一层SQLite缓存,命中率其实很高,因为旅游出行场景对同城同季节的数据重复请求非常多。另外,当某个工具连续失败两次时,业务层自动降级——不再调用该工具,而是在最终文案里生成一句“该部分数据暂不可用,建议出行前再次确认”。降级总比卡死强,这也是一个产品成熟度的体现。

第三条是日志要足够多。一个人调试AI应用最大的痛点是模型行为不可预测,我每次请求都记录了完整链路:用户参数、模型工具调用顺序、每个工具返回时间、最终输出长度。这些日志帮我定位了大部分问题。你可以把日志理解成飞机的黑匣子,没有它,你面对的就是一个说不出原因的黑盒。

4.3 后续可以往哪里扩展

这个产品我在上线后没有停,已经列了几个后续方向。首先是接更多MCP Server:酒店比价、机票查询、甚至是“小红书热门机位”这类数据,都可以封装成独立Server,插进来不用大改业务代码。其次是多Agent协作,比如规划师Agent负责行程骨架,美食Agent负责餐厅筛选,交通Agent负责通勤效率,每个Agent共享同一个MCP工具池。第三是把模型层抽成网关,这样用户可以自由切换Claude、GPT、国产大模型,而不是被锁死在单一模型上。

还有一个我很想做的方向,就是让MCP工具接入更多真实设备的实时数据。比如通过MCP读用户本地日历,结合已有的假期安排推荐目的地;或者接地图实时拥堵数据,动态调整当天的动线。这些不是空谈,现在MCP生态里这类Server已经越来越多,装配式开发会成为主流。

写在最后的实操小技巧

如果你打算自己动手做一个MCP应用,最后分享一个小技巧:给MCP工具写一个独立的mock模式。我经常要在不依赖真实外部API的情况下调试整个流程,于是给Server加了一个环境变量开关,当MOCK_MODE=1时,所有工具返回预设的示例数据。这样前端、业务流程、模型Prompt这些环节全都可以脱离网络独立测试,只有最后联调时才切回真实API。我把这个开关写进启动命令里,几乎是零成本,但让调试速度提升了一个档次。

这次项目给我的直接体感是:MCP这条路径已经把“AI应用接入外部数据”的门槛降到了个人开发者也能3天出货的程度。模型负责聪明,MCP负责连接,我负责把两者粘在一起。AI产品的爆发期往往出现在工具链成熟之后,MCP的价值正在于此。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 20:24:42

厂家直售雷腾动力康明斯系列300kw发电机组,低油耗低排放参数优异,物流仓储应急供电方案定制

备用电源市场持续升温,源头厂家成采购近年来,随着数据中心扩容、制造业产能升级、市政工程与矿山项目密集开工,备用电源需求呈现稳定增长态势。停电一次,可能意味着产线停摆、病房失电、矿井险情,越来越多企事业单位开…

作者头像 李华
网站建设 2026/10/2 20:24:17

手提编织袋定做资深厂商,正规源头生产厂家用户力荐

手提编织袋作为商用包装领域的基础品类,看似结构简单,实际上从面料织造到成品交付,每一个环节都藏着影响使用体验的细节。很多企业采购时只对比单价,收货后才发现编织稀疏、提手脱线、印刷发虚等问题频出,反而付出了更…

作者头像 李华
网站建设 2026/10/2 20:23:58

介电毛细流体调控LAMMPS仿真

关键词:介电毛细;非均匀电场;分子动力学;LAMMPS;流体调控 一、文章简要介绍 多孔材料、超级电容器、纳流控器件都靠吸附流体工作,但传统吸附性能由材料本身决定,改不了。这篇Nature Communicati…

作者头像 李华
网站建设 2026/10/2 20:22:02

以太网温湿度采集系统设计:多协议对接、断线重连与断点续传实战解析

直接从事这个项目的朋友应该都有同感:以太网温湿度采集通讯本身不难,难的是现场环境永远不像测试台上那么干净。部署环境里的交换机重启、光电转换器松动、DHCP地址漂移、上位机主动断开连接,随便一个意外就能让设备陷入“数据只采不发”的尴…

作者头像 李华