手把手教你,动手写一个MCP Server并在 Cline中使用!_cline mcp server
本期内容节选自九天老师的公开课内容,MCP官方技术文档给出了构建天气服务器方案,但其举例是调用美国气象局API进行服务器搭建,为了降低开发门槛,让大家都能够实际上手试一试,九天老师精心研发出更加适合中国宝宝体质的开发教程!让我们直接开始~
先花两分钟,弄明白 模型上下文协议(MCP)!
MCP 是一种 开放协议,用于 标准化应用程序向 LLM 提供上下文的方式。
你可以把 MCP 想象成 AI 应用的 USB-C 接口。正如 USB-C 提供了 标准化的方式 让设备连接到各种外设和配件,
MCP 提供了标准化方式,让 AI 模型 能够连接到 不同的数据源和工具。
🔹 为什么选择 MCP?
MCP 让你能够在 LLM 之上构建智能代理(Agents)和复杂工作流。
LLM 需要与 数据和工具 集成,而 MCP 提供了:
✅ 丰富的预构建集成,LLM 可直接对接
✅ 跨 LLM 供应商的灵活性,支持随时切换
✅ 数据安全的最佳实践,确保数据存储在本地基础设施中
🔹 MCP 的总体架构
MCP 采用 客户端-服务器(Client-Server)架构,其中主机应用可以连接多个 MCP 服务器:
Internet ⬇ Your Computer ⬇ MCP Protocol ↙ ↓ ↘MCP Server A MCP Server B MCP Server C↙ ↓ ↘Local Data A Local Data B Remote Service C
📌 MCP 主要组件:
-
MCP 主机(Hosts):如 Claude 桌面应用、IDE、AI 工具,用于通过 MCP 访问数据
-
MCP 客户端(Clients):负责 与 MCP 服务器建立 1:1 连接
-
MCP 服务器(Servers):轻量级程序,通过 标准化的 MCP 协议 提供特定能力
-
本地数据源(Local Data Sources):你的 计算机文件、数据库和服务,MCP 服务器可以安全访问
-
远程服务(Remote Services):可通过 API 访问的外部系统,MCP 服务器可以连接这些系统
🔹 MCP天气查询服务器server与使用
1. MCP服务器概念介绍
根据MCP协议定义,Server可以提供三种类型的标准能力,Resources、Tools、Prompts,每个Server可同时提供者三种类型能力或其中一种。
-
Resources:资源,类似于文件数据读取,可以是文件资源或是API响应返回的内容。
-
Tools:工具,第三方服务、功能函数,通过此可控制LLM可调用哪些函数。
-
Prompts:提示词,为用户预先定义好的完成特定任务的模板。
2. MCP服务器通讯机制
Model Context Protocol(MCP)是一种由 Anthropic 开源的协议,旨在将大型语言模型直接连接至数据源,实现无缝集成。根据 MCP 的规范,当前支持两种传输方式:标准输入输出(stdio)和基于 HTTP 的服务器推送事件(SSE)。而近期,开发者在 MCP 的 GitHub 仓库中提交了一项提案,建议采用“可流式传输的 HTTP”来替代现有的 HTTP+SSE 方案。此举旨在解决当前远程 MCP 传输方式的关键限制,同时保留其优势。 HTTP 和 SSE(服务器推送事件)在数据传输方式上存在明显区别:
-
通信方式:
-
HTTP:采用请求-响应模式,客户端发送请求,服务器返回响应,每次请求都是独立的。
-
SSE:允许服务器通过单个持久的 HTTP 连接,持续向客户端推送数据,实现实时更新。
-
-
连接特性:
-
HTTP:每次请求通常建立新的连接,虽然在 HTTP/1.1 中引入了持久连接,但默认情况下仍是短连接。
-
SSE:基于长连接,客户端与服务器之间保持持续的连接,服务器可以在任意时间推送数据。
-
-
适用场景:
-
HTTP:适用于传统的请求-响应场景,如网页加载、表单提交等。
-
SSE:适用于需要服务器主动向客户端推送数据的场景,如实时通知、股票行情更新等。
-
需要注意的是,SSE 仅支持服务器向客户端的单向通信,而 WebSocket 则支持双向通信。
具体来说,MCP定义了Client与Server进行通讯的协议与消息格式,其支持两种类型通讯机制:标准输入输出通讯、基于SSE的HTTP通讯,分别对应着本地与远程通讯。Client与Server间使用JSON-RPC 2.0格式进行消息传输。
-
本地通讯:使用了stdio传输数据,具体流程Client启动Server程序作为子进程,其消息通讯是通过stdin/stdout进行的,消息格式为JSON-RPC 2.0。
-
远程通讯:Client与Server可以部署在任何地方,Client使用SSE与Server进行通讯,消息的格式为JSON-RPC 2.0,Server定义了/see与/messages接口用于推送与接收数据。
这里我们尝试一个入门级的示例,那就是创建一个天气查询的服务器。通过使用OpenWeather API,创建一个能够实时查询天气的服务器(server),并使用stdio方式进行通信。
测试查询效果
curl -s \"https://api.openweathermap.org/data/2.5/weather?q=Beijing&appid=\'YOUR_API_KEY\'&units=metric&lang=zh_cn\"
测试无误后,接下来即可进入到创建server的环节中。
3. 天气查询服务器Server创建流程
3.1 服务器依赖安装
由于我们需要使用http请求来查询天气,因此需要在当前虚拟环境中添加如下依赖
uv add mcp httpx
3.2 服务器代码编写
接下来尝试创建服务器代码,此时MCP基本执行流程如下:
对应server服务器代码如下:
import jsonimport httpxfrom typing import Anyfrom mcp.server.fastmcp import FastMCP# 初始化 MCP 服务器mcp = FastMCP(\"WeatherServer\")# OpenWeather API 配置OPENWEATHER_API_BASE = \"https://api.openweathermap.org/data/2.5/weather\"API_KEY = \"YOUR_API_KEY\"# 请替换为你自己的 OpenWeather API KeyUSER_AGENT = \"weather-app/1.0\"asyncdeffetch_weather(city: str) -> dict[str, Any] | None: \"\"\" 从 OpenWeather API 获取天气信息。 :param city: 城市名称(需使用英文,如 Beijing) :return: 天气数据字典;若出错返回包含 error 信息的字典 \"\"\" params = { \"q\": city, \"appid\": API_KEY, \"units\": \"metric\", \"lang\": \"zh_cn\" } headers = {\"User-Agent\": USER_AGENT} asyncwith httpx.AsyncClient() as client: try: response = await client.get(OPENWEATHER_API_BASE, params=params, headers=headers, timeout=30.0) response.raise_for_status() return response.json() # 返回字典类型 except httpx.HTTPStatusError as e: return {\"error\": f\"HTTP 错误: {e.response.status_code}\"} except Exception as e: return {\"error\": f\"请求失败: {str(e)}\"}defformat_weather(data: dict[str, Any] | str) -> str: \"\"\" 将天气数据格式化为易读文本。 :param data: 天气数据(可以是字典或 JSON 字符串) :return: 格式化后的天气信息字符串 \"\"\" # 如果传入的是字符串,则先转换为字典 if isinstance(data, str): try: data = json.loads(data) except Exception as e: returnf\"无法解析天气数据: {e}\" # 如果数据中包含错误信息,直接返回错误提示 if\"error\"in data: returnf\"⚠️ {data[\'error\']}\" # 提取数据时做容错处理 city = data.get(\"name\", \"未知\") country = data.get(\"sys\", {}).get(\"country\", \"未知\") temp = data.get(\"main\", {}).get(\"temp\", \"N/A\") humidity = data.get(\"main\", {}).get(\"humidity\", \"N/A\") wind_speed = data.get(\"wind\", {}).get(\"speed\", \"N/A\") # weather 可能为空列表,因此用 [0] 前先提供默认字典 weather_list = data.get(\"weather\", [{}]) description = weather_list[0].get(\"description\", \"未知\") return ( f\"🌍 {city}, {country}\\n\" f\"🌡 温度: {temp}°C\\n\" f\"💧 湿度: {humidity}%\\n\" f\"🌬 风速: {wind_speed} m/s\\n\" f\"🌤 天气: {description}\\n\" )@mcp.tool()asyncdefquery_weather(city: str) -> str: \"\"\" 输入指定城市的英文名称,返回今日天气查询结果。 :param city: 城市名称(需使用英文) :return: 格式化后的天气信息 \"\"\" data = await fetch_weather(city) return format_weather(data)if __name__ == \"__main__\": # 以标准 I/O 方式运行 MCP 服务器 mcp.run(transport=\'stdio\')
代码解释如下:
Part 1. 异步获取天气数据
-
函数 fetch_weather(city: str)
-
使用 httpx.AsyncClient() 发送异步 GET 请求到 OpenWeather API。
-
如果请求成功,则调用 response.json() 返回一个字典。
-
出现异常时,返回包含错误信息的字典。
-
Part 2. 格式化天气数据
-
函数 format_weather(data: dict | str)
-
首先检查传入的数据是否为字符串,如果是,则使用 json.loads 将其转换为字典。
-
检查数据中是否包含 \"error\" 字段,如果有,直接返回错误提示。
-
使用 .get() 方法提取 name、sys.country、main.temp、main.humidity、wind.speed 和 weather[0].description 等数据,并为可能缺失的字段提供默认值。
-
将提取的信息拼接成一个格式化字符串,方便阅读。
-
Part 3. MCP 工具 query_weather(city: str)
-
函数 query_weather
-
通过 @mcp.tool() 装饰器注册为 MCP 服务器的工具,使其能够被客户端调用。
-
调用 fetch_weather(city) 获取天气数据,然后用 format_weather(data) 将数据格式化为易读文本,最后返回该字符串。
-
Part 4. 运行服务器
-
if __name__ == \"__main__\": 块
-
调用 mcp.run(transport=\'stdio\') 启动 MCP 服务器,采用标准 I/O 通信方式,等待客户端调用。
-
此外,上述代码有两个注意事项,
-
query_weather函数的函数说明至关重要,相当于是此后客户端对函数进行识别的基本依据,因此需要谨慎编写;
-
当指定 transport=\'stdio\' 运行 MCP 服务器时,客户端必须在启动时同时启动当前这个脚本,否则无法顺利通信。这是因为 stdio 模式是一种本地进程间通信(IPC,Inter-Process Communication)方式,它需要服务器作为子进程运行,并通过标准输入输出(stdin/stdout)进行数据交换。
因此,当我们编写完服务器后,并不能直接调用这个服务器,而是需要创建一个对应的能够进行stdio的客户端,才能顺利进行通信。
4. 天气查询客户端client创建流程
4.1 代码编写
import asyncioimport osimport jsonfrom typing import Optionalfrom contextlib import AsyncExitStackfrom openai import OpenAI from dotenv import load_dotenvfrom mcp import ClientSession, StdioServerParametersfrom mcp.client.stdio import stdio_client# 加载 .env 文件,确保 API Key 受到保护load_dotenv()classMCPClient: def__init__(self): \"\"\"初始化 MCP 客户端\"\"\" self.exit_stack = AsyncExitStack() self.openai_api_key = os.getenv(\"OPENAI_API_KEY\") # 读取 OpenAI API Key self.base_url = os.getenv(\"BASE_URL\") # 读取 BASE YRL self.model = os.getenv(\"MODEL\") # 读取 model ifnot self.openai_api_key: raise ValueError(\"❌ 未找到 OpenAI API Key,请在 .env 文件中设置 OPENAI_API_KEY\") self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url) # 创建OpenAI client self.session: Optional[ClientSession] = None self.exit_stack = AsyncExitStack() asyncdefconnect_to_server(self, server_script_path: str): \"\"\"连接到 MCP 服务器并列出可用工具\"\"\" is_python = server_script_path.endswith(\'.py\') is_js = server_script_path.endswith(\'.js\') ifnot (is_python or is_js): raise ValueError(\"服务器脚本必须是 .py 或 .js 文件\") command = \"python\"if is_python else\"node\" server_params = StdioServerParameters( command=command, args=[server_script_path], env=None ) # 启动 MCP 服务器并建立通信 stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params)) self.stdio, self.write = stdio_transport self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write)) await self.session.initialize() # 列出 MCP 服务器上的工具 response = await self.session.list_tools() tools = response.tools print(\"\\n已连接到服务器,支持以下工具:\", [tool.name for tool in tools]) asyncdefprocess_query(self, query: str) -> str: \"\"\" 使用大模型处理查询并调用可用的 MCP 工具 (Function Calling) \"\"\" messages = [{\"role\": \"user\", \"content\": query}] response = await self.session.list_tools() available_tools = [{ \"type\": \"function\", \"function\": { \"name\": tool.name, \"description\": tool.description, \"input_schema\": tool.inputSchema } } for tool in response.tools] # print(available_tools) response = self.client.chat.completions.create( model=self.model, messages=messages, tools=available_tools ) # 处理返回的内容 content = response.choices[0] if content.finish_reason == \"tool_calls\": # 如何是需要使用工具,就解析工具 tool_call = content.message.tool_calls[0] tool_name = tool_call.function.name tool_args = json.loads(tool_call.function.arguments) # 执行工具 result = await self.session.call_tool(tool_name, tool_args) print(f\"\\n\\n[Calling tool {tool_name} with args {tool_args}]\\n\\n\") # 将模型返回的调用哪个工具数据和工具执行完成后的数据都存入messages中 messages.append(content.message.model_dump()) messages.append({ \"role\": \"tool\", \"content\": result.content[0].text, \"tool_call_id\": tool_call.id, }) # 将上面的结果再返回给大模型用于生产最终的结果 response = self.client.chat.completions.create( model=self.model, messages=messages, ) return response.choices[0].message.content return content.message.content asyncdefchat_loop(self): \"\"\"运行交互式聊天循环\"\"\" print(\"\\n🤖 MCP 客户端已启动!输入 \'quit\' 退出\") whileTrue: try: query = input(\"\\n你: \").strip() if query.lower() == \'quit\': break response = await self.process_query(query) # 发送用户输入到 OpenAI API print(f\"\\n🤖 OpenAI: {response}\") except Exception as e: print(f\"\\n⚠️ 发生错误: {str(e)}\") asyncdefcleanup(self): \"\"\"清理资源\"\"\" await self.exit_stack.aclose()asyncdefmain(): if len(sys.argv) < 2: print(\"Usage: python client.py \") sys.exit(1) client = MCPClient() try: await client.connect_to_server(sys.argv[1]) await client.chat_loop() finally: await client.cleanup()if __name__ == \"__main__\": import sys asyncio.run(main())
4.2 测试运行
# 确认进入到项目目录cd /root/autodl-tmp/MCP/mcp-client# 确认激活虚拟环境source .venv/bin/activate
uv run client.py server.py
直接提问请问北京今天天气如何?运行结果如下所示:
QwQ-32B推理类模型问答效果如下:
4.3 代码解释
client代码整个MCP服务的核心,以下是这段代码的详细解释。
导入基本类
import asyncioimport osimport jsonfrom typing import Optionalfrom contextlib import AsyncExitStackfrom openai import OpenAI from dotenv import load_dotenvfrom mcp import ClientSession, StdioServerParametersfrom mcp.client.stdio import stdio_client
-
导入必要库
-
asyncio:支持异步编程
-
os / json:读取环境变量、解析 JSON
-
typing.Optional:类型提示
-
contextlib.AsyncExitStack:用于安全管理异步资源(如 MCP 连接)
-
openai.OpenAI:你的自定义 OpenAI Client 类
-
dotenv.load_dotenv:从 .env 文件加载环境变量(如 API Key)
-
MCP 相关:mcp.ClientSession, mcp.client.stdio, StdioServerParameters
-
load_dotenv()
-
从 .env 文件中加载环境变量,
OPENAI_API_KEY=sk-xxxxxxBASE_URL=...MODEL=...
** MCPClient 类创建过程**
classMCPClient: def__init__(self): \"\"\"初始化 MCP 客户端\"\"\" self.exit_stack = AsyncExitStack() self.openai_api_key = os.getenv(\"OPENAI_API_KEY\") # 读取 OpenAI API Key self.base_url = os.getenv(\"BASE_URL\") # 读取 BASE YRL self.model = os.getenv(\"MODEL\") # 读取 model ifnotself.openai_api_key: raise ValueError(\"❌ 未找到 OpenAI API Key,请在 .env 文件中设置 OPENAI_API_KEY\") self.client = OpenAI(api_key=self.openai_api_key, base_url=self.base_url) # 创建OpenAI client self.session: Optional[ClientSession] = None self.exit_stack = AsyncExitStack()
-
self.exit_stack = AsyncExitStack()
-
用于 统一管理异步上下文(如 MCP 连接)的生命周期。
-
可以在退出(cleanup)时自动关闭。
-
-
读取环境变量
-
openai_api_key:OpenAI API Key
-
base_url:模型请求的 Base URL(如你自建的反代地址)
-
model:OpenAI 模型名称
-
-
初始化 OpenAI 客户端
-
OpenAI(api_key=self.openai_api_key, base_url=self.base_url)
-
你自定义的 OpenAI 客户端,用来与 OpenAI Chat Completion API 通信。
-
-
self.session
-
用于保存 MCP 的客户端会话,默认是 None,稍后通过 connect_to_server 进行连接。
-
-
再次声明 self.exit_stack = AsyncExitStack()
-
这里两次赋值其实有点冗余(前面已赋值过一次)。不过并不影响功能,等同于覆盖掉前面的对象。可能是手误或调试时多写了一次。
-
connect_to_server(self, server_script_path: str)
asyncdefconnect_to_server(self, server_script_path: str): ...
-
负责启动并连接到 MCP 服务器,并列出可用工具。
is_python = server_script_path.endswith(\'.py\')is_js = server_script_path.endswith(\'.js\')ifnot (is_python or is_js): raise ValueError(\"服务器脚本必须是 .py 或 .js 文件\")command = \"python\"if is_python else\"node\"
-
判断服务器脚本是 Python 还是 Node.js,选择对应的运行命令。
server_params = StdioServerParameters( command=command, args=[server_script_path], env=None)
-
StdioServerParameters:告诉 MCP 客户端如何启动服务器。
-
command=command:如 \"python\"
-
args=[server_script_path]:如 [\"weather_server.py\"]
-
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))self.stdio, self.write = stdio_transportself.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))await self.session.initialize()
-
stdio_client(server_params):启动服务器进程,并建立 标准 I/O 通信管道。
-
self.stdio, self.write = stdio_transport:拿到读写流。
-
ClientSession(...):创建 MCP 客户端会话,与服务器交互。
-
await self.session.initialize():发送初始化消息给服务器,等待服务器就绪。
# 列出 MCP 服务器上的工具response = await self.session.list_tools()tools = response.toolsprint(\"\\n已连接到服务器,支持以下工具:\", [tool.name for tool in tools])
-
list_tools():向 MCP 服务器请求所有已注册的工具(用 @mcp.tool() 标记)。
-
打印工具列表,例如 [\"get_forecast\", \"query_db\", ...]。
process_query(self, query: str) -> str
asyncdefprocess_query(self, query: str) -> str: \"\"\" 使用大模型处理查询并调用可用的 MCP 工具 (Function Calling) \"\"\" messages = [{\"role\": \"user\", \"content\": query}]
-
收到用户输入后,先把它组装进一个 messages 列表,目前只包含用户信息({\"role\": \"user\", \"content\": query})。
response = await self.session.list_tools()available_tools = [{ \"type\": \"function\", \"function\": { \"name\": tool.name, \"description\": tool.description, \"input_schema\": tool.inputSchema }} for tool in response.tools]print(available_tools)
-
获取服务器上的工具,再转换成 available_tools 的格式。
-
这里你自定义了一个结构:每个工具对应一个 {\"type\": \"function\", \"function\": {...}} 的字典。
-
方便后面发给 OpenAI,告诉它:可以调用这些工具。
response = self.client.chat.completions.create( model=self.model, messages=messages, tools=available_tools )
-
使用 OpenAI 客户端的
chat.completions.create
-
方法发送请求:
-
model=self.model:比如 \"gpt-4o\" 或 \"deepseek-chat\"
-
messages=messages:聊天上下文
-
tools=available_tools:让模型知道有哪些可调用的「函数」。这是你自定义的**“Function Calling”**协议(非官方 JSON schema)。
-
content = response.choices[0]if content.finish_reason == \"tool_calls\": # 如果模型想调用工具 tool_call = content.message.tool_calls[0] tool_name = tool_call.function.name tool_args = json.loads(tool_call.function.arguments) # 执行工具 result = await self.session.call_tool(tool_name, tool_args) print(f\"\\n\\n[Calling tool {tool_name} with args {tool_args}]\\n\\n\") # 将模型返回的调用哪个工具数据和工具执行完成后的数据都存入messages中 messages.append(content.message.model_dump()) messages.append({ \"role\": \"tool\", \"content\": result.content[0].text, \"tool_call_id\": tool_call.id, }) # 将上面的结果再返回给大模型用于生产最终的结果 response = self.client.chat.completions.create( model=self.model, messages=messages, ) return response.choices[0].message.content return content.message.content
-
if content.finish_reason == \"tool_calls\":
-
如果模型的输出表示「想调用工具」,它会在 content.message.tool_calls 列表中声明要用哪个函数、参数是什么。
-
这是你自定义的一种函数调用机制,和官方 function_call 格式略有不同,但逻辑相似。
-
-
取出工具名 tool_name 和参数 tool_args,再调用 self.session.call_tool(tool_name, tool_args) 执行 MCP 工具。
-
把工具调用结果以「role=tool」的形式写入 messages。这样相当于把“函数调用结果”再喂给模型。
-
再次调用 OpenAI,让模型阅读到这个新上下文,产出最终回答。
-
如果没有要调用工具,直接返回 content.message.content(模型的文本回答)。
chat_loop(self)
asyncdefchat_loop(self): \"\"\"运行交互式聊天循环\"\"\" print(\"\\n🤖 MCP 客户端已启动!输入 \'quit\' 退出\") whileTrue: try: query = input(\"\\n你: \").strip() if query.lower() == \'quit\': break response = await self.process_query(query) # 发送用户输入到 OpenAI API print(f\"\\n🤖 OpenAI: {response}\") except Exception as e: print(f\"\\n⚠️ 发生错误: {str(e)}\")
作用:
-
提供一个简单的 命令行界面,反复让用户输入问题。
-
每个问题交给 process_query,把结果打印出来。
-
输入 \'quit\' 退出循环。
cleanup(self) 与 main()
asyncdefcleanup(self): \"\"\"清理资源\"\"\" await self.exit_stack.aclose()
-
self.exit_stack.aclose():异步地关闭所有在 exit_stack 中注册的资源(包括 MCP 会话)。
asyncdefmain(): if len(sys.argv) < 2: print(\"Usage: python client.py \") sys.exit(1) client = MCPClient() try: await client.connect_to_server(sys.argv[1]) await client.chat_loop() finally: await client.cleanup()if __name__ == \"__main__\": import sys asyncio.run(main())
-
读取命令行参数,获取服务器脚本路径(如 weather_server.py)。
-
创建 MCPClient 实例。
-
调用 connect_to_server,启动并连接服务器。
-
进入 chat_loop 让用户输入多轮对话。
-
退出时调用 client.cleanup() 释放资源。
代码总结如下:
-
MCPClient 的主要职责:
-
启动 MCP 服务器(通过 StdioServerParameters)
-
建立 MCP 会话,列出可用工具
-
处理用户输入,将其发送给 OpenAI 模型
-
如果模型想调用 MCP 工具(Function Calling),就执行 call_tool
-
将结果重新发给模型,并返回最终回答
-
-
Function Calling 逻辑(你的自定义版):
-
tools=available_tools:在 completions.create 时告诉模型有哪些工具可用。
-
模型返回 finish_reason==\"tool_calls\" → 说明它想用工具。
-
解析 tool_calls[0],执行 MCP 工具 → 再次发给模型 → 返回最终答案。
-
-
为什么要两次请求?
-
第一次:模型根据你的指令,决定要不要用工具
-
如果需要用工具 → 返回工具名称和参数 → 执行工具 → 把结果作为新的上下文发给模型
-
第二次:模型基于工具结果给出最终回答
-
-
如何运行:
python client.py weather_server.py
-
这会自动启动 weather_server.py(MCP 服务器)并进行 stdio 通讯。
-
可能需要的改进:
-
多轮对话上下文:把所有消息都存进 messages,让模型能记住以前的对话。
-
错误处理:当工具调用失败时,给用户提示。
-
5.MCP Inspector功能介绍
在实际开发MCP服务器的过程中,Anthropic提供了一个非常便捷的debug工具:Inspector。借助Inspector,我们能够非常快捷的调用各类server,并测试其功能。Inspector具体功能实现流程如下。
-
安装nodejs
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo bash -sudo apt install -y nodejs
npx -v
-
运行Inspector
npx-y @modelcontextprotocol/inspector uv run server.py
然后即可在本地浏览器查看当前工具运行情况:http://127.0.0.1:5173/#resources
此时浏览器内容如下:
然后即可查看当前服务器运行状况:
以上就是构建MCP天气服务器的教学内容。
如果对于一些开发先决条件、客户端开发流程以及MCP更多进阶使用感兴趣的小伙伴,请扫描下方二维码进入「赋范大模型技术社区」内含MCP完整学习课件,每周不定期公开课硬核干货直播~