MCP概念

MCP(Model Context Protocol,模型上下文协议 )介绍了一种规范:应用如何为LLM提供上下文。官网称MCP为AI应用的USB-C端口,提供一种将AI模型连接到不同数据源、工具的标准化方法。

定位

MCP可以帮助我们在LLM之上构建Agent或者复杂的工作流,对于一些经常需要与数据和工具集成的场景,MCP协议提供以下功能:

  1. 基于协议实现的集成数据集或工具可以以插件方式快速连接到LLM。

  2. 解耦工具和LLM,使得应用可以在多个LLM提供商切换。

  3. 数据和工具不需要上传远端,保护数据隐私。

架构

在这里插入图片描述

通信机制

Standard Input/Output (stdio)

进程间通信,适用于命令行或脚本工具执行,本地调试

Server-Sent Events (SSE)

基于http服务器实现事件推送,适合web应用、实时推送等场景(mcp服务通过http的方式提供服务)

构建MCP server(以天气服务为例)

搭建环境(conda 环境)

# 创建虚拟环境
conda create -n mcp python=3.10

使用pycharm 新建项目mcp,python解释器选择上面创建的mcp虚拟环境

在pycharm Terminal下 安装以下依赖

pip install "mcp[cli]"
pip install httpx

安装uv工具

官方推荐的是使用uv工具来管理和解析包.在conda 虚拟环境下安装uv

pip install uv

新建天气MCP服务(sse)

使用了官网的天气服务代码。先把框架跑通,再研究自己服务。

新建weather.py文件

from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP

# 初始化天气服务
mcp = FastMCP("weather")

# 定义天气请求接口
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='sse')
    # mcp.run(transport="stdio")

transport=‘sse’ 即mcp通信方式sse,会以web服务方式启动MCP服务,让客户端可以通过http地址去访问。

运行该文件,即启动了一个本地开发的MCP服务。

在这里插入图片描述

在客户端可以使用 http://127.0.0.1:8000/sse去连接。

打开mcp inspector

mcp dev .\weather.py

使用该方式,会提示安装mcp inspector,输入y,等待安装。

在这里插入图片描述

由于安装比较慢,若中断后再次执行,会报错

Error: Cannot find module ‘rxjs’

mcp inspector 相关内容参考下面MCP Inspector章节。

下面使用一个客户端去调用上面定义的MCP服务。

客户端使用

按照官网推荐的是Claude for Desktop 工具。其实就是一个AI聊天工具,支持了MCP服务的配置和调用。

但是安装时需要注册账号,注册新账号却不能使用。果断换个工具。

考虑使用基于vscode的cline 插件。该插件支持mcp服务配置。cline插件安装和vscode其他插件安装一样。

安装完成后配置一个大模型,保存后即可打开聊天窗口。这里配置的是Deepseek-V3的模型。

在这里插入图片描述

点击+号右边的MCP server 配置按钮,配置上面新建的MCP 服务。

在这里插入图片描述

服务配置文件如下:(这里是以SSE的通信方式来连接的)

{
  "mcpServers": {
    "weather": {
      "url": "http://127.0.0.1:8000/sse",
      "disabled": false,
      "autoApprove": []
    }
  }
}

autoApprove 是指,cline在调用该mcp时,是否需要确认,还是直接不需要确认就能执行。

如果配置正确,可以正常连接,在installed tab项会以列表形式列出来,同时有绿色的状态标识。

下面测试mcp 服务调用;

输入问题:查询纽约天气

在这里插入图片描述

可以看到顺利调用了MCP的服务。

stdio通信机制尝试

将天气MCP服务,通信机制改成stdio模式。

if __name__ == "__main__":
    # Initialize and run the server
    #mcp.run(transport='sse')
    mcp.run(transport="stdio")

以下命令启动

uv run weather.py

cline 配置,weather1

{
  "mcpServers": {
    "weather": {
      "url": "http://127.0.0.1:8000/sse",
      "disabled": false,
      "autoApprove": []
    },
    "weather1": {
            "command": "uv",
            "args": [
                "--directory",
                "D:\\source\\mcp",
                "run",
                "weather.py"
            ]
        }

  }
}

连接报错:

MCP error -32000: Connection closed

原因是,依赖于uv 命令连接的MCP服务项目文件得使用uv init 来生成,具体操作如下:

基于pycharm ,在mcp项目下,Command Prompt 终端工具下,执行:

uv init weather-stdio

在这里插入图片描述

之所以上图中会有一个(mcp),是由于使用conda 创建了一个mcp虚拟环境,python版本是3.10。这里由于本机安装的python是3.12版本,但mcp服务要使用的python版本是3.10,为了不影响本机python的全局环境,所以虚拟了一个mcp的环境和python解释器。

uv 初始化项目,创建激活虚拟环境,是不指定python版本的,只依赖于所处环境的python,也是为了不影响本机全局的python,让其使用conda虚拟的mcp环境的python版本。

进入项目

cd weather-stdio
# 创建mcp服务虚拟环境
uv venv
# 激活该环境
.venv\Scripts\activate

目录层级变成 (weather-stdio) (mcp),如下:

在这里插入图片描述

到这里,相当于使用uv 在weather-stdio目录下又虚拟了一套python环境,所以这套环境是全新的,需要安装以下依赖包:

uv add "mcp[cli]" httpx

其中,mcp 是一个python 包,实现了MCP协议相关的通信机制,该包提供MCP相关的服务。地址如下:

https://pypi.org/project/mcp/

安装完成后,执行以下命令启动服务:

uv run weather.py

若没报错,则mcp服务开发正常。

然后再通过cline配置(只看weather-stdio的服务配置):

{
  "mcpServers": {
    "weather": {
      "url": "http://127.0.0.1:8000/sse",
      "disabled": false,
      "autoApprove": []
    },
    "weather-stdio": {
            "command": "uv",
            "args": [
                "--directory",
                "D:\\source\\mcp\\weather-stdio",
                "run",
                "weather.py"
            ]
        }
  }
}

这里记录下:

通过stdio方式配置的mcp,可以不使用 uv run 跑起来,也可以连通。

但是使用sse方式启动的mcp必须得跑起来才能与客户端联通。

MCP Inspector

探测mcp的状态,使用下述命令:

mcp dev weather.py

但报错Error: Cannot find module ‘rxjs’

安装rxjs

npm  install rxjs

但还是报一样的错误。

经过检索,通义千问,反馈 :有时全局安装的 CLI 工具找不到本地依赖,可以尝试:

npx mcp dev weather.py

但是一直处于安装中,

在这里插入图片描述

最终也无法解决问题。

尝试清空缓存:

#清除 npm 缓存
npm cache clean --force
# 清除npx缓存
npx clear-npx-cache

即可。这个问题是由于一开始执行mcp dev xx.py时,加载太慢,就取消了,对npx缓存写入了不完整文件。清理掉,重新执行即可。

在这里插入图片描述

重新执行加载还是很慢。

该过程是通过npm 下载inspector的前端包,若npm源无法下载,会报错,需要切换到其他的源,我就是使用了淘宝镜像源,结果报无权限,于是切换回官方源,更新成功.

npm config set registry https://registry.npmjs.org/

在执行mcp dev weather.py时,会报’mcp-inspector’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

解决方案是参考https://github.com/modelcontextprotocol/inspector

需要保证nodejs版本大于22.7.5,但我的版本是22.5.0,于是升级版本。

执行

npx @modelcontextprotocol/inspector

会下载@modelcontextprotocol/inspector,成功后即可。

执行mcp dev ./weather.py,如下:

在这里插入图片描述

浏览器访问

http://127.0.0.1:6274/

在这里插入图片描述

按下图所示配置参加,连接weather.py 服务,如下:

在这里插入图片描述

连接时需要填入启动控制台输出的session token.

可以把mcp inspector 理解为,一个浏览器端的mcp服务连接调试工具(是没有大模型参与的)。在开发mcp server中,可以使用该工具去测试mcp server.

可以点击工具,输入参数,测试工具功能是否正常。

MCP服务调用流程

在问题框输入问题后,客户端会将mcp服务配置文件和当前其他环境参数,提交给配置的大语言模型(Deepseek)

在这里插入图片描述

大模型给出解决方案

在这里插入图片描述

cline 按照大模型解决方案提示,输入纽约经纬度参数,去调用mcp服务

在这里插入图片描述

mcp服务返回结果

在这里插入图片描述

cline 汇总最终结果呈现给用户

在这里插入图片描述

经验总结

1 conda 环境提供python解释器,uv工具虚拟化mcp服务环境,两者搭配是个不错的组合;

2 MCP服务被用来定义,扩展大模型能力的,有些可以在网络上找,直接安装使用,有些需要自己开发,但无论哪种,都得考虑数据安全问题;

3 MCP Inspector 是本地开发MCP服务调试工具,直接提供web端界面去调试提供的服务,这个过程是没有LLM参与的。

更多推荐