介绍

MCP 使用 JSON-RPC 2.0 作为其传输格式。传输层负责将 MCP 协议消息转换为 JSON-RPC 格式进行传输,并将接收到的 JSON-RPC 消息转换回 MCP 协议消息。其中SSE被废弃了(Server-Sent Events (SSE) - Deprecated)

SSE as a standalone transport is deprecated as of protocol version 2024-11-05. It has been replaced by Streamable HTTP, which incorporates SSE as an optional streaming mechanism. For backwards compatibility information, see the backwards compatibility section below.

自协议版本 2024-11-05 起,SSE 作为独立传输已被弃用。它已被流式 HTTP 取代,后者将 SSE 作为可选的流式机制。有关向后兼容性信息,请参阅下方的向后兼容性部分。

MCP官网:Transports - Model Context Protocol

实战

1.编写一个py代码

from __future__ import annotations
import argparse
import asyncio
import json
from typing import Any, AsyncIterator
import httpx
from fastapi import FastAPI, Request, Response, status
from fastapi.responses import StreamingResponse
# ---------------------------------------------------------------------------
# Server constants
# ---------------------------------------------------------------------------
SERVER_NAME = "WeatherServer"
SERVER_VERSION = "1.0.0"
PROTOCOL_VERSION = "2024-11-05" # Cherry Studio current
# ---------------------------------------------------------------------------
# Weather helpers
# ---------------------------------------------------------------------------
OPENWEATHER_URL = "https://api.openweathermap.org/data/2.5/weather"
API_KEY: str | None = None
USER_AGENT = "weather-app/1.0"
async def fetch_weather(city: str) -> dict[str, Any]:if not API_KEY:return {"error": "API_KEY 未设置,请提供有效的 OpenWeather API Key。"}params = {"q": city, "appid": API_KEY, "units": "metric", "lang": "zh_cn"}headers = {"User-Agent": USER_AGENT}async with httpx.AsyncClient(timeout=30.0) as client:try:r = await client.get(OPENWEATHER_URL, params=params, headers=headers)r.raise_for_status()return r.json()except httpx.HTTPStatusError as exc:return {"error": f"HTTP 错误: {exc.response.status_code} - {exc.response.text}"}except httpx.RequestError as exc:return {"error": f"网络请求失败: {exc}"}except json.JSONDecodeError:return {"error": "OpenWeather 返回的数据不是有效的 JSON"}def format_weather(data: dict[str, Any]) -> str:if "error" in data:return 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 = data.get("wind", {}).get("speed", "N/A")desc = data.get("weather", [{}])[0].get("description", "未知")return (f"🌍 {city}, {country}\n"f"🌡 温度: {temp}°C\n"f"💧 湿度: {humidity}%\n"f"🌬 风速: {wind} m/s\n"f"🌤 天气: {desc}")async def stream_weather(city: str, req_id: int | str) -> AsyncIterator[bytes]:# 进度提示(不会出错的部分放在try外面)yield json.dumps({"jsonrpc": "2.0","id": req_id,"stream": f"查询{city}天气中…"}).encode() + b"\n"try:await asyncio.sleep(0.3)data = await fetch_weather(city)  # 主要可能出错点if "error" in data:yield json.dumps({"jsonrpc": "2.0","id": req_id,"error": {"code": -32002,  # 保留业务错误码"message": data["error"]}}).encode() + b"\n"return# 正常结果(json.dumps理论上不会出错)yield json.dumps({"jsonrpc": "2.0","id": req_id,"result": {"content": [{"type": "text", "text": format_weather(data)}],"isError": False}}).encode() + b"\n"except Exception as exc:# 系统级错误单独处理yield json.dumps({"jsonrpc": "2.0","id": req_id,"error": {"code": -32003,  # 保留系统错误码"message": f"服务器内部错误: {str(exc)}"}}).encode() + b"\n"# ---------------------------------------------------------------------------# FastAPI app# ---------------------------------------------------------------------------
app = FastAPI(title="WeatherServer HTTP-Stream v8")
TOOLS_REGISTRY = {"tools": [{"name": "get_weather","description": "用于进行天气信息查询的函数,输入城市英文名称,即可获得当前城市天气信息。","inputSchema": {"type": "object","properties": {"city": {"type": "string","description": "City name, e.g. 'Hangzhou'"}},"required": ["city"]}}],"nextCursor": "qinqing"
}
@app.get("/mcp")
async def mcp_initialize_via_get():
# GET 请求也执行了 initialize 方法return {"jsonrpc": "2.0","id": 0,"result": {"protocolVersion": PROTOCOL_VERSION,"capabilities": {"streaming": True,"tools": {"listChanged": True}},"serverInfo": {"name": SERVER_NAME,"version": SERVER_VERSION},"instructions": "Use the get_weather tool to fetch weather by cityname."}
}
@app.post("/mcp")
async def mcp_endpoint(request: Request):try:body = await request.json()# ✅ 打印客户端请求内容print("💡 收到请求:", json.dumps(body, ensure_ascii=False, indent=2))except Exception:return {"jsonrpc": "2.0", "id": None, "error": {"code": -32700,"message": "Parse error"}}req_id = body.get("id", 1)method = body.get("method")# ✅ 打印当前方法类型print(f"🔧 方法: {method}")# 0) Ignore initialized notification (no response required)if method == "notifications/initialized":return Response(status_code=status.HTTP_204_NO_CONTENT)# 1) Activation probe (no method)if method is None:return {"jsonrpc": "2.0", "id": req_id, "result": {"status": "MCP serveronline."}}# 2) initializeif method == "initialize":return {"jsonrpc": "2.0","id": req_id,"result": {"protocolVersion": PROTOCOL_VERSION,"capabilities": {"streaming": True,"tools": {"listChanged": True}},"serverInfo": {"name": SERVER_NAME, "version": SERVER_VERSION},"instructions": "Use the get_weather tool to fetch weather bycity name."}}# 3) tools/listif method == "tools/list":print(json.dumps(TOOLS_REGISTRY, indent=2, ensure_ascii=False))return {"jsonrpc": "2.0", "id": req_id, "result": TOOLS_REGISTRY}# 4) tools/callif method == "tools/call":params = body.get("params", {})tool_name = params.get("name")args = params.get("arguments", {})if tool_name != "get_weather":return {"jsonrpc": "2.0", "id": req_id, "error": {"code": -32602,"message": "Unknown tool"}}city = args.get("city")if not city:return {"jsonrpc": "2.0", "id": req_id, "error": {"code": -32602,"message": "Missing city"}}# return StreamingResponse(stream_weather(city, req_id),media_type="application/json")data = await fetch_weather(city)return {"jsonrpc": "2.0","id": req_id,"result": {"content": [{"type": "text", "text": format_weather(data)}],"isError": False}}# 5) unknown methodreturn {"jsonrpc": "2.0", "id": req_id, "error": {"code": -32601, "message":"Method not found"}}
# ---------------------------------------------------------------------------
# Runner
# ---------------------------------------------------------------------------
def main() -> None:parser = argparse.ArgumentParser(description="Weather MCP HTTP-Stream v8")parser.add_argument("--api_key", required=False,default='xxxx')parser.add_argument("--host", default="127.0.0.1")parser.add_argument("--port", type=int, default=8000)args = parser.parse_args()global API_KEYAPI_KEY = args.api_keyimport uvicornuvicorn.run(app, host=args.host, port=args.port, log_level="info")
if __name__ == "__main__":# npx -y @modelcontextprotocol/inspector uv run weather2.pymain()

其中api_key 需要自己申请即可,可以免费调用大概1000次(测试和学习基本够用了) 

2. 使用mcp的检查器进行测试

npx -y @modelcontextprotocol/inspector uv run xxxx.py

参考官网:Inspector - Model Context Protocol

3. 将py进行启动运行

4. 检查器启动成功之后进行测试

简单的例子Streamable HTTP就成功了 ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/89036.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/89036.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/89036.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

量子计算与AI的融合:开启智能革命的“量子跃迁”新范式

当量子计算的并行算力与人工智能的深度学习能力相遇,一场颠覆传统认知的技术革命正在酝酿。从药物研发到自动驾驶,从金融风控到气候预测,两者的融合不仅突破了经典计算的算力天花板,更催生出全新的算法范式与产业生态。本文将深入解析量子计算与AI融合的技术逻辑、核心突破…

【氮化镓】不同偏压应力下电荷俘获效应导致的P-GaN HEMT阈值电压不稳定性

2022年12月7日,意大利国家研究委员会微电子与微系统研究所的Giuseppe Greco等人在《Applied Physics Letters》期刊发表了题为《Threshold voltage instability by charge trapping effects in the gate region of p-GaN HEMTs》的文章,基于对p-GaN高电子迁移率晶体管(HEMTs…

ONLYOFFICE深度解锁系列.10-如何识别图像和PDF扫描件中的文本?用ONLYOFFICE的AI OCR轻松搞定!

ONLYOFFICE 文档版本 9.0带来多项 AI 关键改进,显著提升您处理电子表格和 PDF 文件的工作效率。本指南将重点介绍新增的 OCR 功能,并讲解如何在 PDF 编辑器中利用 AI 助手将图像转为可编辑文本。什么是 OCR 文字识别?OCR 技术能够扫描各类文档…

单例模式详解:确保一个类只有一个实例

在软件开发中,设计模式是解决常见问题的经典方案。单例模式(Singleton Pattern)作为创建型设计模式中最简单也最常用的一种,确保一个类只有一个实例,并提供一个全局访问点。本文将全面探讨单例模式的概念、多种实现方式…

Appdynamic 配置 PostgreSQL 收集器

配置 PostgreSQL 收集器 您可以使用数据库可见性监控任何版本的 PostgreSQL。 连接详细信息 部分场地描述创建新的收集器数据库类型您想要监控的数据库类型。代理人管理收集器的数据库代理。收藏家姓名您想要用来识别收集器的名称。连接详细信息主机名或 IP 地址运行数据库的机…

其他常见 HTTP 方法

除了最常用的四种方法(GET、POST、PUT、DELETE),HTTP 协议还定义了一些较少使用但非常有用的请求方法,常用于调试、部分更新、跨域预检等场景。1. HEAD 方法:获取响应头 特点: 用途:与 GET 类似…

Web应用防火墙(WAF)技术

目录 一:简介 1.1 Web安全现状 1.2 传统防御的局限性 二:Web应用防火墙技术解析 2.1 WAF核心架构 2.2 关键技术特性 三:WAF必要性 3.1 典型防护场景 3.2 与传统方案对比 四:进阶防护方案 4.1 智能WAF架构 4.2 关键技术…

机器学习之线性回归(七)

机器学习之线性回归(七) 文章目录机器学习之线性回归(七)一、线性回归线性回归超全指南:从“一条直线”到“正则化调参”的完整旅程0. 先对齐语言:标称型 vs 连续型1. 问题形式化2. 损失函数全景3. 求解方法…

基于开源AI大模型、AI智能名片与S2B2C商城小程序源码的用户价值引导与核心用户沉淀策略研究

摘要:在数字化商业生态中,用户留存与核心用户培育是产品成功的关键。本文聚焦开源AI大模型、AI智能名片与S2B2C商城小程序源码的协同应用,探讨如何通过技术赋能实现用户价值引导与核心用户沉淀。研究结合工业品供应链、美妆品牌、健康食品行业…

课题申报书成功率提升85%!借助大模型AI精准选题、搭综述框架及提炼创新点(附实操AI提示词)

大家好,感谢关注。我是七哥,一个在高校里不务正业,折腾用大模型AI实操的学术人。可以添加七哥(qige500)交流学术写作或ChatGPT、Claude等学术大模型AI领域相关问题,多多交流,相互成就,共同进步。 写一份高质量的课题申报书往往面临许多困难,对很多同仁来说,难就难在…

Spring之【写一个简单的IOC容器EasySpring】

目录 EasySpring 注解 EasyAutowired EasyComponent EasyComponentScan EasyLazy EasyPostConstruct EasyProtoType EasyValue Bean定义信息 EasyBeanDefinition 管理Bean定义信息 EasyBeanDefinitionRegister Aware EasyAware EasyBeanFactoryAware EasyBea…

Selenium动态网页爬虫编写与解释

使用Selenium来抓取动态网页。动态网页通常是指那些通过JavaScript动态加载内容的网页,这些内容在初始HTML中并不存在,因此使用传统的requests库无法获取到这些动态生成的内容。Selenium可以模拟浏览器行为,等待JavaScript执行并渲染页面&…

element el-table中使用el-image图片预览被其他表格遮挡

或者::v-deep .el-table__cell {position: static !important;}

MyBatis与Spring整合优化实战指南:从配置到性能调优

一、SqlSessionFactory配置最佳实践 1.1 数据源配置优化 <!-- Spring配置示例 --> <bean id"dataSource" class"com.zaxxer.hikari.HikariDataSource" destroy-method"close"><property name"driverClassName" value&q…

LUA(初学)

条件语句if if then endlocal a 2 if a < 6 thenprint(a) end2条件语句if else if then else endlocal a 2 local b 3 if a > 6 thenprint(a) elseprint(b) end3while循环语句 while do endlocal a 2 while a < 5 doa a 1print(a) end3 4 5for循环语句 for do …

JMeter 连接与配置 ClickHouse 数据库

其他人都需要好几十积分提供jar包&#xff0c;我5积分提供给大家 jar包地址&#xff1a;https://download.csdn.net/download/weixin_41853064/91370401 1、将jar包内的文件放入jmeter/lib/exc目录并重启jmeter 2、配置jmeter JDBC连接 3、复制 click hourse的类名&#xff1…

Kmeams聚类算法详解

文章目录一、聚类任务的简介1.1 聚类的核心特征1.2 聚类的典型应用场景二、Kmeans的思想和数学原理2.1 核心思想2.2 数学原理三、Kmeans计算过程示例3.1 数据集3.2 步骤1&#xff1a;确定K值并初始化簇中心3.3 步骤2&#xff1a;计算样本到簇中心的距离并分配簇3.4 步骤3&#…

平升智慧水务整体解决方案,大数据驱动的智慧水务,让城市供水更智能

平升电子智慧水务整体解决方案 智慧供水整体解决方案&#xff0c;在调度中心搭建智慧水务平台&#xff0c;为供水各环节安装智能测控设备&#xff0c;应用物联网、互联网、大数据、云计算、人工智能等新一代信息技术&#xff0c;构建智慧水务综合管理系统&#xff0c;贯穿从水源…

Samba配置使用

主要作用&#xff1a;将Linux系统中的文件共享给windows配置过程&#xff1a;&#xff08;1&#xff09;打开命令终端&#xff1a;获取超级用户权限后运行以下指令:apt-get install samba&#xff08;2&#xff09;修改samba配置文件&#xff1a;gedit /etc/samba/smb.conf :找…

Datawhale AI数据分析 笔记

Part1&#xff1a;数据分析入门--信息统计知识点&#xff1a;什么是提示词&#xff08;Prompt&#xff09;&#xff1f;在人工智能&#xff08;AI&#xff09;领域&#xff0c;"提示词"是一个关键概念&#xff0c;它指的是输入给AI模型的文本或指令&#xff0c;用于引…