原文链接: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 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版)的更多相关文章

  1. 推荐一本书:清华出版的《Modbus软件开发实战指南》

    前言: 最近在研究Modbus开发,如果只是简单的了解了一些modbus基础知识,但是不够系统和全面. 其实,modbus虽然比较简单,但是如果不注意有很多坑,特别是寄存器的位数,大小端处理,浮点数, ...

  2. HTML5 Canvas游戏开发实战 PDF扫描版

    HTML5 Canvas游戏开发实战主要讲解使用HTML5 Canvas来开发和设计各类常见游戏的思路和技巧,在介绍HTML5 Canvas相关特性的同时,还通过游戏开发实例深入剖析了其内在原理,让读 ...

  3. HTML5移动Web开发实战 PDF扫描版​

    <HTML5移动Web开发实战>提供了应对这一挑战的解决方案.通过阅读本书,你将了解如何有效地利用最新的HTML5的那些针对移动网站的功能,横跨多个移动平台.全书共分10章,从移动Web. ...

  4. 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章

    从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章  如何使用本书 1.1  本书的参考资料 本书参考资料为:<STM32 ...

  5. 《Django企业开发实战 高效Python Web框架指南》胡阳

    链接:https://pan.baidu.com/s/1NmN_IT5RvevCMt9bZCW1-g提取码:2ki9

  6. 【深入浅出Seata原理及实战】「入门基础专题」探索Seata服务的AT模式下的分布式开发实战指南(2)

    承接上文 上一篇文章说到了Seata 为用户提供了 AT.TCC.SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案.那么接下来我们将要针对于AT模式下进行分布式事务开发的原理进行介绍以及 ...

  7. (六)Spark-Eclipse开发环境WordCount-Java&Python版Spark

    Spark-Eclipse开发环境WordCount 视频教程: 1.优酷 2.YouTube 安装eclipse 解压eclipse-jee-mars-2-win32-x86_64.zip Java ...

  8. 【Python开发实战】Python环境的配置

    1. 安装Pythonsudo aptitude -y install python-dev 安装Distribute:支撑模块构建与导入的包sudo chmod -R 0775 /usr/local ...

  9. Modbus软件开发实战指南 之 开发自己的Modbus Poll工具 - 1

    在开发Modbus程序的过程中,也可以发现经常需要使用诸如Modbus Poll和Modbus Slave等辅助调试工具, 用于验证MODBUS通讯消息是否正确.但是,Modbus Poll和Modb ...

  10. Modbus软件开发实战指南 之 开发自己的Modbus Poll工具 - 2

    接上一篇文章的内容. 看了前面需求提到的复杂的命令行解析功能,很多人立马开始发怵,其实大可不必. 我们都知道,Linux下的程序往往都提供了复杂的命令行参数处理机制,因为这是与 其他程序或用户进行交互 ...

随机推荐

  1. LLaMA (以LLaMA2为例,文末附加对比1 2 3 三个版本的变化)

    补充背景: 关于Transformer和Llama架构的演进 一.背景 LLaMA 2 和 LLaMA2-Chat 参数规模:70亿.130亿和700亿 数据和训练规模: 上下文长度 训练资源 性能表 ...

  2. 获取Harbor镜像仓库指定Project的容量使用并进行企业微信告警

    简单说明 在镜像仓库的维护中,有时我们需要根据镜像仓库的使用情况进行及时的告警和扩容,避免镜像仓库容量满载时再进行扩容,这样会造成业务的阻塞. 这里我们使用Python简单写一个实现获取镜像仓库指定项 ...

  3. linux系统磁盘快速创建多个分区

    # 创建分区 [root@centos7 ~]# cat parted.sh parted --script /dev/sdb \ mklabel gpt \ mkpart primary 1MiB ...

  4. 能看病的AI你见过吗:ChatMoney

    本文由 ChatMoney团队出品 在当今这个科技飞速发展的时代,人工智能技术正在以惊人的速度改变着我们的生活,人工智能已经深入到各个领域,医疗行业也不例外. 而今天我要和大家聊一聊利用ChatMon ...

  5. jenkins的搭建及问题处理

    Jenkins搭建第一步 本文讲述的本人搭建Jenkins的流程及遇到的坑及处理方法 1.搭建 Linux操作系统为Centos Jenkins版本为24稳定版 操作命令: sudo wget -O ...

  6. 【语义分割专栏】4:deeplab系列原理篇

    目录 前言 背景介绍 Deeplab系列讲解 Deeplabv1 去池化和全连接层 空洞卷积(Atrous Convolution) 全连接条件随机场(Fully - connected Condit ...

  7. 超赞!本地程序调用云知识库实现RAG功能

    在 Spring AI Alibaba 程序中,我们可以直接使用本地程序调用百炼平台的云知识库,实现知识库文档解析.分块.向量化存储等一条龙服务. 这样,开发者就不用本地部署搭建向量数据库.不用进行复 ...

  8. UFT issue

  9. CMD 命令启动管理员模式代码

    ::==========================================:: 获取管理员权限set _Args=%*if "%~1" NEQ "" ...

  10. 解决Dify的Ollama插件添加模型时保存成功但模型为空的问题

    最近组里安排了点调研Dify任务.我跟着基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程一步一步走,前面都挺顺利,但在Dify的Ollama中引入大模型这一步卡住了 ...