万物皆可MCP,快速开发一个获取天气信息的MCP Server

🧑 博主简介:现任阿里巴巴嵌入式技术专家,15年工作经验,深耕嵌入式+人工智能领域,精通嵌入式领域开发、技术管理、简历招聘面试。CSDN优质创作者,全网11W+粉丝博主,提供产品测评、学习辅导、简历面试辅导、毕设辅导、项目开发、C/C++/Java/Python/Linux/AI等方面的服务,同时还运营着十几个不同主题的技术交流群,如有需要请站内私信或者联系VX(gylzbk),互相学习共同进步。

本文将深入探讨 MCP(Model Context Protocol)开发的方方面面,通过实际案例和详细讲解,帮助开发者快速掌握 MCP 开发的核心要点和技巧。从基础的开发环境搭建,到 MCP Server 的设计与实现,再到与 AI 模型的集成和调优,我们将一一进行实践和解析,助力开发者在 AI 与外部资源集成领域开启新的篇章。

一、开发环境搭建

在开始 MCP 开发之前,需要先搭建好开发环境。以下是一些常见的开发环境要求和推荐的配置:

  • 操作系统 :支持 Windows、macOS 和 Linux 等主流操作系统。
  • 编程语言 :目前有多种编程语言可以用于 MCP 开发,如 Python、.NET 等。Python 因其简洁易懂的语法和丰富的库支持,是许多开发者的首选。
  • 网络环境 :确保开发环境中网络连接稳定,以便能够顺利下载所需的依赖库和工具,以及与外部 API 进行通信。

以 Python 开发环境为例,需要先安装 Python 解释器,推荐使用 Python 3.6 或更高版本。可以通过官方网址 www.python.org/ 下载安装包并进行安装。安装完成后,验证 Python 是否安装成功,可在终端或命令行输入 python --versionpython3 --version,若显示出对应的版本号,则表示安装成功。

接下来,需要安装一些常用的开发工具和库,如代码编辑器 VS Code,以及用于项目依赖管理的 pip 工具等。VS Code 提供了丰富的插件和便捷的功能,能够显著提升开发效率。pip 工具则可以帮助我们方便地安装和管理 Python 的第三方库。

二、开发一个简单的 MCP Server

1. 创建项目结构

首先创建一个项目文件夹,例如 "mcp-weather-server",并在其中创建以下文件和文件夹:

bash 复制代码
mcp-weather-server/
    ├── main.py           # 主程序入口
    ├── requirements.txt  # 项目依赖文件
    └── mcp/              # MCP 相关代码文件夹
        ├── __init__.py
        ├── server.py     # MCP Server 实现代码
        └── tools.py      # 工具函数实现代码

这样的项目结构有助于保持代码的组织性和可维护性,方便后续的开发和扩展。

2. 编写 MCP Server 代码

mcp/server.py 文件中,我们将使用 FastMCP 库来创建一个简单的 MCP Server。FastMCP 是一个基于 Python 的轻量级 MCP Server 框架,它提供了便捷的方式来定义和管理工具函数,使得开发过程更加高效。

python 复制代码
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')

在上述代码中,我们首先导入了所需的库和模块,包括 FastMCP、httpx 等。然后,创建了一个 FastMCP 实例,并定义了两个工具函数 get_alertsget_forecast,分别用于获取美国某个州的天气警报和某个地理位置的天气预报。在工具函数中,我们通过调用 NWS(美国国家气象局)API 来获取相应的天气数据,并将其格式化为可读的字符串返回。

3. 运行 MCP Server

在项目根目录下创建 requirements.txt 文件,添加以下内容:

复制代码
fastmcp
httpx

然后,在终端或命令行中运行以下命令来安装项目依赖:

复制代码
pip install -r requirements.txt

安装完成后,运行 main.py 文件启动 MCP Server:

css 复制代码
python main.py

此时,MCP Server 将开始监听客户端的连接和请求。

三、开发 MCP Client 并与 AI 模型集成

1. 创建 MCP Client

以下是一个使用 Python 编写的简单 MCP Client 示例,它连接到我们刚刚创建的 MCP Server,并调用其提供的工具函数:

python 复制代码
import asyncio
from mcp.client.client import MCPClient

async def main():
    # 创建 MCP Client 实例
    client = MCPClient()

    # 连接到 MCP Server
    await client.connect('stdio')

    # 获取可用的工具列表
    tools = await client.list_tools()
    print("Available tools:", tools)

    # 调用 get_alerts 工具
    result = await client.invoke_tool('get_alerts', state='CA')
    print("Weather alerts in CA:")
    print(result)

    # 调用 get_forecast 工具
    result = await client.invoke_tool('get_forecast', latitude=37.7749, longitude=-122.4194)
    print("Weather forecast for San Francisco:")
    print(result)

    # 断开连接
    await client.disconnect()

# 运行主函数
asyncio.run(main())

在该示例中,我们首先创建了一个 MCPClient 实例,并连接到 MCP Server。然后,获取 Server 提供的工具列表,并调用 get_alertsget_forecast 工具函数,传入相应的参数以获取天气警报和天气预报信息。最后,断开与 Server 的连接。

2. 与 AI 模型集成

为了将 MCP 与 AI 模型集成,我们可以使用一些流行的 AI 框架和库,如 OpenAI 的 Python 库等。以下是一个简单的示例,展示了如何将 MCP Client 与 OpenAI 的 ChatGPT 模型集成:

python 复制代码
import openai
import asyncio
from mcp.client.client import MCPClient

# 初始化 OpenAI API 客户端
openai.api_key = 'your_openai_api_key'

async def main():
    # 创建 MCP Client 实例
    client = MCPClient()

    # 连接到 MCP Server
    await client.connect('stdio')

    # 获取可用的工具列表
    tools = await client.list_tools()
    print("Available tools:", tools)

    # 定义一个函数,用于调用 MCP 工具
    async def call_mcp_tool(tool_name, **kwargs):
        return await client.invoke_tool(tool_name, **kwargs)

    # 使用 OpenAI 的 ChatCompletion API
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant that can use MCP tools to answer questions."},
            {"role": "user", "content": "What's the weather like in San Francisco?"}
        ],
        functions=[
            {
                "name": "get_forecast",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "latitude": {"type": "number"},
                        "longitude": {"type": "number"}
                    },
                    "required": ["latitude", "longitude"]
                }
            }
        ],
        function_call={"name": "get_forecast"}
    )

    # 检查是否需要调用 MCP 工具
    if response.choices[0].finish_reason == "function_call":
        # 调用 MCP 工具
        tool_name = response.choices[0].message.function_call.name
        tool_args = response.choices[0].message.function_call.arguments
        tool_result = await call_mcp_tool(tool_name, **tool_args)

        # 将工具结果作为新的消息发送给模型
        second_response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "system", "content": "You are a helpful assistant that can use MCP tools to answer questions."},
                {"role": "user", "content": "What's the weather like in San Francisco?"},
                {"role": "assistant", "content": None, "function_call": {
                    "name": tool_name,
                    "arguments": tool_args
                }},
                {"role": "function", "name": tool_name, "content": tool_result}
            ]
        )

        # 输出最终回答
        print(second_response.choices[0].message.content)

    # 断开连接
    await client.disconnect()

# 运行主函数
asyncio.run(main())

在这个示例中,我们通过 OpenAI 的 ChatCompletion API 发送消息,并指定了一个函数调用的参数。当模型返回一个函数调用请求时,我们通过 MCP Client 调用相应的 MCP 工具,并将工具结果作为新的消息发送回模型,以获取最终的回答。这样,AI 模型就可以借助 MCP 的能力,访问外部的天气数据,并生成更准确、更有用的回复。

四、调试与测试

在开发 MCP 项目的过程中,调试和测试是非常重要的环节,以确保 MCP Server 和 Client 的正确性和稳定性,以及与 AI 模型的协同工作效果。

1. 调试 MCP Server

可以使用一些专门的调试工具和方法来调试 MCP Server。例如,在 Python 中,可以使用 pdb 模块来进行断点调试,设置断点以检查代码的执行流程和变量的值。此外,还可以通过查看 Server 的日志输出来定位问题和跟踪错误。FastMCP 提供了内置的日志功能,可以通过配置日志级别和输出方式来获取详细的调试信息。

2. 测试 MCP Client

对于 MCP Client,可以编写单元测试和集成测试来验证其功能和性能。可以使用 Python 的 unittest 或 pytest 框架来编写测试用例,模拟不同的场景和输入,检查 Client 是否能够正确地连接到 Server、调用工具函数以及处理返回的结果。同时,还可以测试 Client 在异常情况下的表现,如网络中断、Server 无响应等,以确保 Client 的健壮性和可靠性。

3. 测试与 AI 模型的集成

在将 MCP 与 AI 模型集成后,需要进行全面的测试以评估整个系统的性能和效果。可以使用一些基准测试数据集或自定义的测试用例,向模型发送各种问题和任务,观察其是否能够正确地调用 MCP 工具并生成符合预期的回答。此外,还可以通过调整模型的参数和配置,如温度、最大令牌数等,来优化其性能和回答质量。同时,要注意测试系统的响应时间和吞吐量,以确保其能够满足实际应用的需求。

五、总结

通过本文的详细介绍和实践,我们对 MCP 开发有了一个全面的认识和理解。从开发环境的搭建,到 MCP Server 和 Client 的开发,再到与 AI 模型的集成和实际应用场景的探讨,我们逐步掌握了 MCP 开发的核心技术和方法。在未来的开发实践中,我们可以不断探索和创新,充分利用 MCP 的优势,为 AI 应用的发展和创新做出贡献。

相关推荐
whaosoft-14315 分钟前
51c自动驾驶~合集37
人工智能
小技工丨22 分钟前
详解大语言模型生态系统概念:lama,llama.cpp,HuggingFace 模型 ,GGUF,MLX,lm-studio,ollama这都是什么?
人工智能·语言模型·llama
陈奕昆24 分钟前
大模型微调之LLaMA-Factory 系列教程大纲
人工智能·llama·大模型微调·llama-factory
上海云盾商务经理杨杨1 小时前
AI如何重塑DDoS防护行业?六大变革与未来展望
人工智能·安全·web安全·ddos
一刀到底2111 小时前
ai agent(智能体)开发 python3基础8 网页抓取中 selenium 和 Playwright 区别和联系
人工智能·python
每天都要写算法(努力版)1 小时前
【神经网络与深度学习】改变随机种子可以提升模型性能?
人工智能·深度学习·神经网络
烟锁池塘柳01 小时前
【计算机视觉】三种图像质量评价指标详解:PSNR、SSIM与SAM
人工智能·深度学习·计算机视觉
小森77672 小时前
(六)机器学习---聚类与K-means
人工智能·机器学习·数据挖掘·scikit-learn·kmeans·聚类
Captaincc2 小时前
关于MCP协议的三大常见误区解析
mcp
bytebeats2 小时前
使用 Google ADK, Gemma 3 和 MCP 工具构建 AI 代理
ai编程·mcp