搭建MCP服务:写一个最简易的MCP服务了解其运行流程
很多朋友在用AI助手时可能都遇到过这样的场景:想让ChatGPT查个天气、查个快递,或者读一下本地文件,它往往只能回一句“抱歉,我无法联网”。问题倒不是模型不够聪明,而是它压根碰不到外部世界的数据——就像一个被关在房间里的人,没法出门获取信息。过去想让AI调用外部工具,要么写一堆适配代码,要么每个工具单独对接,既混乱又低效。

这时候就该MCP上场了。它不是什么高深的底层协议,更像是一个AI与外部工具之间的“万能转接器”。不管是天气接口、数据库、本地脚本,还是第三方平台,只要接上MCP,AI就能像点外卖一样轻松调用这些能力,完全不用关心底层是怎么通信的。简单来说,MCP解决的核心问题就是“AI如何安全、规范、省心地调用外部能力”——让AI从“只会聊天”变成“真正能帮你办事的助手”。
这篇文章会带你从零开始,一步一步搭建一个基于高德地图API的天气查询MCP服务。整个过程会覆盖MCP服务开发、Cursor编辑器集成、LangChain Agent调用全流程,代码直接可复用,兼顾理论深度和实操性,新手也能轻松上手。
一、先搞懂:MCP到底是什么?
先看两个日常场景:
- 场景1:你在Cursor编辑器里说“帮我查北京天气并写到代码注释里”,编辑器自带的AI本身查不了天气,但通过MCP,它能一键调用咱们写的天气工具,拿到结果直接回填,全程不用你手动调接口。
- 场景2:你做了一个智能问答Agent,希望它既能聊天又能查快递、查天气。不用给每个接口写适配代码,只要把这些能力打包成MCP工具,Agent就能自动识别并调用,后续改工具、加工具都不需要动Agent核心代码。
说白了,MCP就是一套通用的“工具调用协议”——AI按这个规矩发请求,工具按这个规矩返回结果,双方各司其职,再也不用点对点适配。MCP的核心能力是解耦,让AI专心做决策,工具专心做执行。
MCP的核心优势
- 标准化通信:统一了工具调用的格式,不用再针对每个模型单独写适配接口
- 低耦合易扩展:工具逻辑与模型调用分离,新增、修改工具都不会影响主流程
- 跨平台兼容:支持Stdio、WebSocket等多种传输方式,适配编辑器、Agent框架等多种场景
- 轻量级无侵入:不需要复杂部署,本地脚本就能启动MCP服务,开发成本极低
有对比才看得更清楚。没有MCP的时候,想让AI调用高德天气,得写接口调用、参数解析、异常捕获,再把这些逻辑嵌进AI代码里。后期想换百度天气,就得改一大段代码。有了MCP之后,把天气查询单独做成一个工具模块,AI只需要通过MCP喊一句“查北京天气”,工具就返回结果。后期换接口、加功能,只改工具本身,AI代码完全不用动。
这次选择用FastMCP框架开发,就是看中它足够轻量。几行代码就能把普通的Python函数变成AI能调用的MCP工具,对小白极其友好——不用学复杂的协议细节,会写Python函数就能上手。
二、环境准备:前置依赖安装
正式开发之前,建议先搭建一个Python虚拟环境,把核心依赖包装好,省得后面出现版本冲突:
# 创建虚拟环境(可选,推荐)
python3 -m venv mcp-env
# 激活环境(macOS/Linux)
source mcp-env/bin/activate
# Windows激活
# mcp-env\Scripts\activate
# 安装核心依赖
pip3 install requests fastmcp pydantic langchain langchain-openai langchain-mcp-adapters langgraph
同时需要提前准备好高德地图开放平台的API Key:前往高德开放平台注册账号,创建应用后获取Web服务类型的Key,后续天气接口调用需要用到它。
三、核心实战:开发天气查询MCP服务
就用查天气这个最刚需的场景来练手——这个例子足够典型。平时AI没法直接联网查天气,我们把高德天气API封装成MCP工具后,不管是Cursor里的AI,还是自己搭的LangChain Agent,都能随时调用这个能力。后续想做查快递、查股价、读本地文件,都是一模一样的思路,换个接口逻辑就行。
3.1 编写MCP服务代码
新建一个 shell_tools.py 文件,这是我们的MCP服务核心文件。通过FastMCP注册天气查询工具,实现高德地图API的封装与标准化输出:
import requests
from typing import Annotated
from mcp.server.fastmcp import FastMCP
from pydantic import Field
# 初始化FastMCP实例
mcp = FastMCP()
# 注册MCP工具:定义工具名称、描述、入参规则
@mcp.tool(name="city_weather", description="查询指定城市的实时天气状况,支持国内大部分地级市")
def get_weather(
city: Annotated[str, Field(
description="目标城市名称(中文全称)",
examples=["北京", "上海", "广州", "深圳"]
)]
) -> str:
"""封装高德地图天气查询API,标准化返回天气数据
接口文档:https://lbs.amap.com/api/webservice/api/weather/weather-info
"""
# 替换为自己的高德地图API Key
AMAP_KEY = "your_amap_api_key"
# 高德天气基础查询接口
url = f"https://restapi.amap.com/v3/weather/weatherInfo?city={city}&key={AMAP_KEY}&extensions=base"
try:
# 发送请求,设置超时避免阻塞
resp = requests.get(url, timeout=10)
resp.raise_for_status()
data = resp.json()
# 校验接口返回状态
if data.get("status") != "1" or not data.get("lives"):
return f"❌ 查询{city}天气失败:接口返回异常或城市不支持"
# 解析实时天气数据
live_data = data["lives"][0]
# 格式化返回结果,提升可读性
return (
f"?️ {live_data['city']} 实时天气\n"
f"?️当前温度:{live_data['temperature']}℃\n"
f"☁️天气状况:{live_data['weather']}\n"
f"?风向风力:{live_data['winddirection']}风 {live_data['windpower']}级\n"
f"?空气湿度:{live_data['humidity']}%"
)
except requests.exceptions.Timeout:
return "❌ 查询天气超时:请检查网络或稍后重试"
except Exception as e:
return f"❌ 查询天气出错:{str(e)}"
if __name__ == "__main__":
# 启动MCP服务,采用stdio传输协议(最常用,适配编辑器、Agent)
mcp.run(transport="stdio")
3.2 代码核心要点解析
- 工具注册:通过
@mcp.tool装饰器定义工具名称和功能描述,大模型通过这些描述来理解工具的用途 - 参数校验:借助Pydantic的Field注解规范入参,明确参数含义和示例,降低模型调用出错的概率
- 异常处理:对超时、接口异常、参数错误等场景做了兜底处理,保证服务的稳定性
- 传输协议:选用stdio标准输入输出,轻量级不需要额外端口,适配绝大多数集成场景
启动测试很简单:直接运行 python shell_tools.py,如果控制台没有报错,说明MCP服务启动成功,等待客户端调用即可。
四、实战集成1:Cursor编辑器接入MCP
Cursor作为主打AI协作的编辑器,原生就支持MCP协议。这意味着一件事:我们不用改Cursor的任何设置,只需要写一段配置,把本地的天气MCP工具“挂载”到Cursor上,编辑器里的AI就能直接使用这个工具。
举个实际例子:以前你在Cursor里问“北京今天多少度”,AI只会回复没法联网查询;现在接入MCP后,你发同样的问题,AI会自动调用我们写的 city_weather 工具,秒回温度、湿度、风力这些详细信息,甚至能帮你把天气数据插入到代码注释里——效率直接拉满。
4.1 配置MCP服务
- 打开Cursor编辑器,按下
Cmd + Shift + P(Windows:Ctrl + Shift + P),输入MCP: Open Settings打开配置文件 - 在
mcpServers节点下添加自定义MCP服务配置,替换为你的shell_tools.py绝对路径
{
"mcpServers": {
"my_mcp_shell": {
"type": "stdio",
"command": "python3",
"args": [
"/Users/xxx/你的项目路径/shell_tools.py"
]
}
}
}
4.2 验证调用
保存配置后,Cursor会自动加载MCP服务。在编辑器对话窗口直接输入:帮我查一下今天北京的天气,大模型会自动调用我们开发的 city_weather 工具,返回格式化的天气结果。无需额外配置,开箱即用。
这里有个细节值得留意:Windows系统需要将 command 改为 python,并确保Python环境已加入系统环境变量;路径建议使用绝对路径,避免相对路径加载失败。
五、集成2:LangChain Agent调用MCP
如果说Cursor是AI编辑器,那LangChain就是搭建自定义AI Agent的框架。比如我们想做一个专属的天气助理Agent,它能听懂自然语言、自动判断是否需要查天气、调用工具后整理结果——MCP就是Agent和天气工具之间的桥梁。
举个例子:用户问Agent“明天去北京要不要带伞”,Agent会先分析需求,知道需要查天气,然后通过MCP调用我们的工具,拿到天气和降水概率后,再给出“带伞/不用带伞”的结论。整个过程全自动,不需要人工干预。
5.1 编写Agent调用代码
import asyncio
import os
import uuid
from langchain_core.messages import HumanMessage
from langchain_core.runnables import RunnableConfig
from langchain_mcp_adapters.sessions import StdioConnection
from langgraph.prebuilt import create_react_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_mcp_adapters.client import MultiServerMCPClient
from pydantic import SecretStr
# 初始化大模型:适配主流大模型API,这里以Doubao为例
llm = ChatOpenAI(
base_url="https://api.302.ai/v1",
api_key=SecretStr(os.getenv("DASHSCOPE_API_KEY")), # 从环境变量读取密钥,更安全
model="Doubao-1.5-lite-32k",
timeout=None,
)
# 定义Agent系统提示词,明确角色定位
prompt = ChatPromptTemplate.from_messages([
("system", "你是专业的私人助理,可调用外部工具精准解答问题,回答简洁易懂、信息准确"),
("human", "{messages}"),
])
async def run_mcp_agent():
"""连接MCP服务,创建ReAct Agent并调用天气查询工具"""
async def get_mcp_tools():
# 配置MCP连接:Stdio方式对接本地MCP服务
mcp_config = {
"my_mcp": StdioConnection(
transport="stdio",
command="python3",
args=["/Users/xxx/你的项目路径/shell_tools.py"], # 替换为MCP文件绝对路径
encoding="utf-8",
)
}
# 初始化MCP客户端,加载工具
client = MultiServerMCPClient(mcp_config)
return await client.get_tools() # 获取MCP工具列表
tools = await get_mcp_tools()
# 创建ReAct智能Agent
agent = create_react_agent(model=llm, prompt=prompt, tools=tools)
# 执行查询:自然语言指令
response = await agent.ainvoke(
input=HumanMessage(content="今天北京天气怎么样?"),
config=RunnableConfig(configurable={"session_id": str(uuid.uuid4())})
)
# 打印最终结果
print(response["messages"][-1].content)
if __name__ == '__main__':
# 运行异步Agent
asyncio.run(run_mcp_agent())
5.2 运行与调试
- 提前在环境变量中配置API密钥,避免硬编码泄露
- 确保MCP服务已启动(或者直接运行Agent代码,它会自动拉起MCP服务)
- 运行脚本,Agent会自动判断是否需要调用MCP工具,完成天气查询并返回结果
六、MCP开发与集成避坑总结
- API密钥安全:千万别硬编码密钥在代码里,建议通过环境变量或配置文件读取
- 路径问题:在Cursor和LangChain集成时,务必使用绝对路径指向MCP脚本
- 传输协议:本地开发优先用stdio,远程服务可以切换为websocket
- 工具描述规范:工具和参数的描述要精准,大模型依赖这些描述来理解工具用途,描述模糊容易导致调用失败
- 异常兜底:完善异常处理,避免MCP服务崩溃影响主流程
七、写在最后
MCP作为大模型工具调用的标准化方案,正在逐渐成为AI Agent开发的基础设施。它彻底解决了工具集成的碎片化问题,让开发者可以专注于工具逻辑本身,而不是把时间花在适配工作上。本文的天气查询MCP服务只是一个入门案例,你可以基于这套框架,快速开发数据库查询、文件操作、第三方API调用等各类MCP工具,轻松拓展大模型的能力边界。
目前社区和各大厂商已经提供了大量可直接调用的MCP服务,这些工具正在大大增强AI的实际应用能力。不妨从这个小例子开始,亲手体验一下MCP带来的开发效率提升。
