MCP Server 开发实战指南(Python版)
原文链接:MCP Server 开发实战指南(Python版)
资料
MCP 官方文档
https://modelcontextprotocol.io/introduction
各个 clients 对 MCP 的支持情况
https://modelcontextprotocol.io/clients
MCP Python SDK:MCP Client 和 Server 官方 SDK
https://github.com/modelcontextprotocol/python-sdk
前言
MCP(Model Context Protocol,模型上下文协议) ,2024年11月底,由 Anthropic 推出的一种开放标准,旨在统一大型语言模型(LLM)与外部数据源和工具之间的通信协议。MCP 的主要目的在于解决当前 AI 模型因数据孤岛限制而无法充分发挥潜力的难题,MCP 使得 AI 应用能够安全地访问和操作本地及远程数据,为 AI 应用提供了连接万物的接口。
Function Calling是AI模型调用函数的机制,MCP是一个标准协议,使AI模型与API无缝交互,而AI Agent是一个自主运行的智能系统,利用Function Calling和MCP来分析和执行任务,实现特定目标。
MCP 核心架构
- MCP 主机(MCP Hosts):发起请求的 LLM 应用程序(例如 Claude Desktop、IDE 或 AI 工具)。
- MCP 客户端(MCP Clients):在主机程序内部,与 MCP server 保持 1:1 的连接。
- MCP 服务器(MCP Servers):为 MCP client 提供上下文、工具和 prompt 信息。
- 本地资源(Local Resources):本地计算机中可供 MCP server 安全访问的资源(例如文件、数据库)。
- 远程资源(Remote Resources):MCP server 可以连接到的远程资源(例如通过 API)。

MCP client 充当 LLM 和 MCP server 之间的桥梁,MCP client 的工作流程如下:
- MCP client 首先从 MCP server 获取可用的工具列表。
- 将用户的查询连同工具描述通过 function calling 一起发送给 LLM。
- LLM 决定是否需要使用工具以及使用哪些工具。
- 如果需要使用工具,MCP client 会通过 MCP server 执行相应的工具调用。
- 工具调用的结果会被发送回 LLM。
- LLM 基于所有信息生成自然语言响应。
- 最后将响应展示给用户。
MCP 通信机制
MCP 协议支持两种主要的通信机制:基于标准输入输出 stdio 的本地通信和基于SSE(Server-Sent Events)的远程通信。这两种机制都使用 JSON-RPC 2.0 格式进行消息传输,确保了通信的标准化和可扩展性。
- 本地通信:通过 stdio 传输数据,适用于在同一台机器上运行的客户端和服务器之间的通信。
- 远程通信:利用 SSE 与 HTTP 结合,实现跨网络的实时数据传输,适用于需要访问远程资源或分布式部署的场景。
MCP Server
MCP Server 是 MCP 架构中的关键组件,它可以提供 3 种主要类型的功能:
- 资源(Resources):类似文件的数据,可以被客户端读取,如 API 响应或文件内容。
- 工具(Tools):可以被 LLM 调用的函数(需要用户批准)。
- 提示(Prompts):预先编写的模板,帮助用户完成特定任务。
这些功能使 MCP server 能够为 AI 应用提供丰富的上下文信息和操作能力,从而增强 LLM 的实用性和灵活性。
MCP Server Demo 开发
开发语言:Python 3.13.2
环境:MacOS
MCP 客户端:Cursor、Cline、Claude Desktop
一、环境配置
安装 uv 命令
curl -LsSf https://astral.sh/uv/install.sh | sh
初始化项目
# 给项目创建一个文件夹
uv init weather
cd weather # 创建一个虚拟环境并激活
uv venv
source .venv/bin/activate # 安装依赖
uv add "mcp[cli]" httpx # 创建 server 文件
touch weather.py
二、编写Server 代码
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP # Initialize FastMCP server
mcp = FastMCP("weather") # Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0" async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {
"User-Agent": USER_AGENT,
"Accept": "application/geo+json"
}
async with httpx.AsyncClient() as client:
try:
response = await client.get(url, headers=headers, timeout=30.0)
response.raise_for_status()
return response.json()
except Exception:
return None def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
props = feature["properties"]
return f"""
Event: {props.get('event', 'Unknown')}
Area: {props.get('areaDesc', 'Unknown')}
Severity: {props.get('severity', 'Unknown')}
Description: {props.get('description', 'No description available')}
Instructions: {props.get('instruction', 'No specific instructions provided')}
""" @mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state. Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url) if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found." if not data["features"]:
return "No active alerts for this state." alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts) @mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location. Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url) if not points_data:
return "Unable to fetch forecast data for this location." # Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url) if not forecast_data:
return "Unable to fetch detailed forecast." # Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period['name']}:
Temperature: {period['temperature']}°{period['temperatureUnit']}
Wind: {period['windSpeed']} {period['windDirection']}
Forecast: {period['detailedForecast']}
"""
forecasts.append(forecast) return "\n---\n".join(forecasts) if __name__ == "__main__":
# Initialize and run the server
mcp.run(transport='stdio')
三、运行服务
MCP Inspector
mcp dev weather.py
当看到以下界面,说明服务运行成功。打开 http://localhost:5173/ 即可进行功能测试


Cursor
也可以通过一些支持 MCP Server 的客户端进行调试
设置 -> MCP → Add new MCP server
类型选择 command,名称可以自定义,执行的命令如下,需要指定路径
uv --directory /Users/ryanjhzheng/Documents/my_mcp/weather run weather.py





Cline
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}

调试
https://modelcontextprotocol.io/docs/tools/debugging
调试工具
MCP Inspector https://modelcontextprotocol.io/docs/tools/inspector
Claude Desktop Developer Tools
Server Logging
MCP Python SDK
创建 Tools
提供清晰、描述性的名称和说明
使用详细的 JSON Schema 定义参数
在工具描述中包含示例,告诉模型应如何使用它们
实施适当的错误处理和验证
对长时间操作使用进度报告
保持工具操作集中且原子化
记录预期返回结果
实施适当的超时
考虑对资源密集型操作进行速率限制
用于调试和监控的日志工具使用情况
常见问题
版本不兼容
ERROR: npm v11.2.0 is known not to run on Node.js v14.21.3. This version of npm supports the following node versions: `^20.17.0 || >=22.9.0`. You can find the latest version at https://nodejs.org/.
遇到的错误表明当前使用的 npm 版本(v11.2.0)与 Node.js 版本(v14.21.3)不兼容。当前的 npm 版本仅支持 Node.js 版本 ^20.17.0 || >=22.9.0。将 Node.js 版本更新到支持的版本,如 ^20.17.0 || >=22.9.0
# 安装最新的 Node.js 版本
nvm install node # 或者安装指定的 Node.js 版本
nvm install 20.17.0 # 使用已安装的 Node.js 版本
nvm use 20.17.0
最后给如果需要购买服务器的,可以使用这里的优惠码,可以享受8折优惠
关于 MCP 的具体场景和玩法,可以查看这篇文章
https://www.cnblogs.com/ryanzheng/p/18879488
https://zhuanlan.zhihu.com/p/1895815215712547750
MCP Server 开发实战指南(Python版)的更多相关文章
- 推荐一本书:清华出版的《Modbus软件开发实战指南》
前言: 最近在研究Modbus开发,如果只是简单的了解了一些modbus基础知识,但是不够系统和全面. 其实,modbus虽然比较简单,但是如果不注意有很多坑,特别是寄存器的位数,大小端处理,浮点数, ...
- HTML5 Canvas游戏开发实战 PDF扫描版
HTML5 Canvas游戏开发实战主要讲解使用HTML5 Canvas来开发和设计各类常见游戏的思路和技巧,在介绍HTML5 Canvas相关特性的同时,还通过游戏开发实例深入剖析了其内在原理,让读 ...
- HTML5移动Web开发实战 PDF扫描版
<HTML5移动Web开发实战>提供了应对这一挑战的解决方案.通过阅读本书,你将了解如何有效地利用最新的HTML5的那些针对移动网站的功能,横跨多个移动平台.全书共分10章,从移动Web. ...
- 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章
从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章 如何使用本书 1.1 本书的参考资料 本书参考资料为:<STM32 ...
- 《Django企业开发实战 高效Python Web框架指南》胡阳
链接:https://pan.baidu.com/s/1NmN_IT5RvevCMt9bZCW1-g提取码:2ki9
- 【深入浅出Seata原理及实战】「入门基础专题」探索Seata服务的AT模式下的分布式开发实战指南(2)
承接上文 上一篇文章说到了Seata 为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案.那么接下来我们将要针对于AT模式下进行分布式事务开发的原理进行介绍以及 ...
- (六)Spark-Eclipse开发环境WordCount-Java&Python版Spark
Spark-Eclipse开发环境WordCount 视频教程: 1.优酷 2.YouTube 安装eclipse 解压eclipse-jee-mars-2-win32-x86_64.zip Java ...
- 【Python开发实战】Python环境的配置
1. 安装Pythonsudo aptitude -y install python-dev 安装Distribute:支撑模块构建与导入的包sudo chmod -R 0775 /usr/local ...
- Modbus软件开发实战指南 之 开发自己的Modbus Poll工具 - 1
在开发Modbus程序的过程中,也可以发现经常需要使用诸如Modbus Poll和Modbus Slave等辅助调试工具, 用于验证MODBUS通讯消息是否正确.但是,Modbus Poll和Modb ...
- Modbus软件开发实战指南 之 开发自己的Modbus Poll工具 - 2
接上一篇文章的内容. 看了前面需求提到的复杂的命令行解析功能,很多人立马开始发怵,其实大可不必. 我们都知道,Linux下的程序往往都提供了复杂的命令行参数处理机制,因为这是与 其他程序或用户进行交互 ...
随机推荐
- 数据分析必备:GPS轨迹、软件签到、手机信令数据获取方式合集
本文对目前主要的出租车.公交车.行人GPS轨迹.社交软件签到.手机信令等数据产品的获取网站加以整理与介绍. 目录 6 GPS轨迹与签到数据 6.1 个人GPS轨迹数据 6.1.1 GeoLife ...
- python学习课后练习
此次爬虫学习的资源是B站所找,具体如下:Python课程天花板,Python入门+Python爬虫+Python数据分析5天项目实操/Python基础,该课程留了课后练习,我把自己的代码和想法单独整成 ...
- 关于学习率-----linearLR
1. lr_scheduler综述 torch.optim.lr_scheduler模块提供了一些根据epoch训练次数来调整学习率(learning rate)的方法.一般情况下我们会设置随着epo ...
- SRM合同更新行项目(组件/SAPSRM/WDC_CTR_DOTC_IT)
* Get the selected elements of the item table > lt_elem_set = lon_ctr_item->get_selected_eleme ...
- 物无弃材 —— 混闪机型部署 OceanBase 集群的探索
本文作者:联通研究院 邱永刚 首先为大家推荐这个 OceanBase 开源负责人老纪的公众号 "老纪的技术唠嗑局",会持续更新和 #数据库.#AI.#技术架构 相关的各种技术内容. ...
- solana杂谈(1)
solana杂谈(1) 本文适用于"只需大致了解 Solana"的读者,部分说法可能不够准确或不够深入.如需详细了解,建议阅读 Solana 的官方文档:https://solan ...
- pont生成api涉及泛型问题
背景 pont是一款很好用的api生成工具. 我最近在用其生成swagger3的前端接口文件时,发现了个问题. 就是当我后端接口返回的是复杂类型的泛型的时候,生成的def类型有问题: 会直接写死泛型! ...
- 从Linux系统SSH到Windows系统。
以管理员身份运行powershell. PS C:\Windows\system32> Get-WindowsCapability -Online | ? Name -like 'OpenSSH ...
- C++ linux 共享内存的学习
简介 我经常被 无知所惊吓, 我的无知包含很多东西,或许是一段未开始已经结束的爱情,或许是掩盖不了对自己想去的公司的眼神, 或许就是共享内存这个名字.哈哈哈哈. 共享内存 简而言之就是 共享内存(sh ...
- printf \r \n
简介 \r 回到这一行的开始处 \n 换下一行 参考链接 csdn