MCP基础知识一
概念
MCP ( Model Context Protocol )是一种为了统一大规模模型和工具间通信而设计的协议,它定义
了消息格式和通信方式。 MCP 协议支持多种传输机制,其中包括 stdio 、 Server-Sent Events
( SSE ) 和 Streamable HTTP 。每种通信方法在不同的应用场景中具有不同的优劣势,适用于不同的需 求。
通信方式
1 Stdio 传输(Standard Input/Output)
stdio 传输方式是最简单的通信方式,通常在本地工具之间进行消息传递时使用。它利用标准输入
输出( stdin/stdout )作为数据传输通道,适用于本地进程间的交互。
工作方式 :客户端和服务器通过标准输入输出流( stdin/stdout )进行通信。客户端向服务器发送
命令和数据,服务器执行并通过标准输出返回结果。
应用场景 :适用于本地开发、命令行工具、调试环境,或者模型和工具服务在同一进程内运行的情
况。
2 Server-Sent Events(SSE)
SSE 是基于 HTTP 协议的流式传输机制,它允许服务器通过 HTTP 单向推送事件到客户端。 SSE 适用 于客户端需要接收服务器推送的场景,通常用于实时数据更新。
工作方式 :客户端通过 HTTP GET 请求建立与服务器的连接,服务器以流式方式持续向客户端发送 数据,客户端通过解析流数据来获取实时信息。
应用场景 :适用于需要服务器主动推送数据的场景,如实时聊天、天气预报、新闻更新等
3 Streamable HTTP
Streamable HTTP 是 MCP 协议中新引入的一种传输方式,它基于 HTTP 协议支持双向流式传输。 与传统的 HTTP 请求响应模型不同, Streamable HTTP 允许服务器在一个长连接中实时向客户端推送数 据,并且可以支持多个请求和响应的流式传输。
工作方式 :客户端通过 HTTP POST 向服务器发送请求,并可以接收流式响应(如 JSON-RPC 响应 或 SSE 流)。当请求数据较多或需要多次交互时,服务器可以通过长连接和分批推送的方式进行数 据传输。
应用场景 :适用于需要支持高并发、低延迟通信的分布式系统,尤其是跨服务或跨网络的应用。适
合高并发的场景,如实时流媒体、在线游戏、金融交易系统等。
MCP服务器类型介绍
根据 MCP 协议定义, Server 可以提供三种类型的标准能力, Resources 、 Tools 、 Prompts ,每个
Server 可同时提供者三种类型能力或其中一种。
Resources : 资源,类似于文件数据读取,可以是文件资源或是 API 响应返回的内容。
Tools : 工具,第三方服务、功能函数,通过此可控制 LLM 可调用哪些函数。
Prompts : 提示词,为用户预先定义好的完成特定任务的模板。
总结
Stdio 传输 :适合本地进程之间的简单通信,适合命令行工具或调试阶段,但不支持分布式。 SSE 传输 :适合实时推送和客户端 / 浏览器的单向通知,但无法满足双向复杂交互需求。
Streamable HTTP 传输 :最灵活、最强大的选项,适用于大规模并发、高度交互的分布式应用系
统,虽然实现较复杂,但能够处理更复杂的场景。
实战通讯协议之 Stdio
安装UV
pip install uv
初始化项目
uv init mcp-demo-stdio
创建虚拟环境
uv venv
激活虚拟环境
source .venv/bin/activate
安装 MCPSDK
uv add mcp
weather.py 的代码
import os
import json
import httpx
from typing import Any
from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP# 初始化 MCP 服务器
mcp = FastMCP("WeatherServer")
# OpenWeather API 配置
OPENWEATHER_API_BASE = "https://api.openweathermap.org/data/2.5/weather"
API_KEY = "xxxxxx"
USER_AGENT = "weather-app/1.0"async def fetch_weather(city: str) -> dict[str, Any] | None:print(city)"""从 OpenWeather API 获取天气信息。:param city: 城市名称(需使用英文,如 Beijing):return: 天气数据字典;若出错返回包含 error 信息的字典"""params = {"q": city,"appid": API_KEY,"units": "metric","lang": "zh_cn"}headers = {"User-Agent": USER_AGENT}async with 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)}"}def format_weather(data: dict[str, Any] | str) -> str:"""将天气数据格式化为易读文本。:param data: 天气数据(可以是字典或 JSON 字符串):return: 格式化后的天气信息字符串"""# 如果传入的是字符串,则先转换为字典if isinstance(data, str):try:data = json.loads(data)except Exception as e:return f"无法解析天气数据: {e}"# 如果数据中包含错误信息,直接返回错误提示if "error" in data:return f"⚠️ {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()
async def query_weather(city: str) -> str:"""输入指定城市的英文名称,返回今日天气查询结果。:param city: 城市名称(需使用英文):return: 格式化后的天气信息"""data = await fetch_weather(city)return format_weather(data)if __name__ == "__main__":# 以标准 I/O 方式运行 MCP 服务器# npx -y @modelcontextprotocol/inspector uv run weather.pymcp.run(transport='stdio')
利用inspector工具进行调试
npx -y @modelcontextprotocol/inspector uv run weather.py
在浏览器上运行该地址
http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=64bac71785ee900a35a92b3837e98d6d077457ad91c5c8f238c3366fb1f74cd9

debug自己的方法,运行结果如下:
