MCP开发一

113 阅读5分钟

概述

模型上下文协议(Model Context Protocol,简称 MCP)允许应用程序以标准化的方式为大型语言模型(LLMs)提供上下文,将提供上下文的过程与实际的 LLM 交互分离开来。此 Python SDK 实现了完整的 MCP 规范,使以下任务变得简单:

  • 构建能够连接到任何 MCP 服务器的 MCP 客户端
  • 创建公开资源、提示(prompts)和工具的 MCP 服务器
  • 使用标准传输方式,例如标准输入输出(stdio)和服务器发送事件(SSE)
  • 处理所有 MCP 协议消息和生命周期事件

安装

推荐使用 uv 管理 Python 项目:

uv add "mcp[cli]"

或使用 pip 安装:

pip install mcp

运行独立 MCP 开发工具:

uv run mcp

快速开始

创建一个简单 MCP 服务器示例:

# server.py
from mcp.server.fastmcp import FastMCP

# 创建一个 MCP 服务器
mcp = FastMCP("Demo")


# 添加一个加法工具
@mcp.tool()
def add(a: int, b: int) -> int:
    """两个数字相加"""
    return a + b


# 添加一个动态问候资源
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """获取个性化问候语"""
    return f"Hello, {name}!"

快速测试:

mcp dev server.py

什么是 MCP?

模型上下文协议(Model Context Protocol,简称 MCP)允许您构建服务器,以一种安全、标准化的方式向 LLM 应用程序公开数据和功能。可以将其视为一种专为 LLM 交互设计的 Web API。MCP 服务器可以:

  • 通过资源(Resources)公开数据(类似于 GET 端点,用于将信息加载到 LLM 的上下文中)
  • 通过工具(Tools)提供功能(类似于 POST 端点,用于执行代码或产生其他副作用)
  • 通过提示(Prompts)定义交互模式(可重用的 LLM 交互模板)

核心概念

服务器(Server)

核心接口,处理连接、协议合规和消息路由:

# Add lifespan support for startup/shutdown with strong typing
from contextlib import asynccontextmanager
from collections.abc import AsyncIterator
from dataclasses import dataclass

from fake_database import Database  # Replace with your actual DB type

from mcp.server.fastmcp import Context, FastMCP

# 创建服务器
mcp = FastMCP("My App")

# 添加依赖项
mcp = FastMCP("My App", dependencies=["pandas", "numpy"])


@dataclass
class AppContext:
    db: Database


@asynccontextmanager
async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
    """Manage application lifecycle with type-safe context"""
    # Initialize on startup
    db = await Database.connect()
    try:
        yield AppContext(db=db)
    finally:
        # Cleanup on shutdown
        await db.disconnect()


# 传lifespan给服务器
mcp = FastMCP("My App", lifespan=app_lifespan)


# 在工具中访问类型安全的生命周期上下文
@mcp.tool()
def query_db(ctx: Context) -> str:
    """Tool that uses initialized resources"""
    db = ctx.request_context.lifespan_context["db"]
    return db.query()

资源(Resources)

在 MCP(Model Context Protocol)中,Resources 是一种用来向 LLM(大型语言模型)暴露数据的机制。它们的作用类似于 REST API 中的 GET 端点,主要用于提供数据,而不是执行复杂的计算或产生副作用(如更改状态、写数据库等)。

  • 通过静态或动态路径,Resources 可以灵活地提供各种数据:
    • 静态数据(如配置信息)。
    • 动态数据(如用户信息,根据请求中的参数生成)。
  • MCP 通过 @mcp.resource 装饰器轻松实现资源的注册和管理,使得 LLM 可以通过标准化的方式访问这些数据。
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("My App")

# 定义静态 Resource
@mcp.resource("config://app")
def get_config() -> str:
    """Static configuration data"""
    return "App configuration here"

#  定义动态 Resource
@mcp.resource("users://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    """Dynamic user data"""
    return f"Profile data for user {user_id}"

工具(Tools)

在 MCP(Model Context Protocol)中,Tools 是一种让 LLM(大型语言模型)通过服务器执行操作的机制。与 Resources 不同,Tools 的设计目标是执行计算任务或产生副作用(如访问外部 API、写入数据库等)。

import httpx
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("My App")


@mcp.tool()
def calculate_bmi(weight_kg: float, height_m: float) -> float:
    """Calculate BMI given weight in kg and height in meters"""
    return weight_kg / (height_m**2)


# 定义一个异步函数 async def
@mcp.tool()
async def fetch_weather(city: str) -> str:
    """Fetch current weather for a city"""
    async with httpx.AsyncClient() as client:
        response = await client.get(f"https://api.weather.com/{city}")
        return response.text

提示模板(Prompts)

Prompts 是一种可重用的模板,用于帮助 LLM(大型语言模型)与服务器进行更高效的交互。Prompts 的主要功能是生成结构化的消息或文本,作为与 LLM 交互的输入内容。

from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.prompts import base

mcp = FastMCP("My App")


@mcp.prompt()
def review_code(code: str) -> str:
    return f"Please review this code:\n\n{code}"


@mcp.prompt()
def debug_error(error: str) -> list[base.Message]:
    return [
        base.UserMessage("I'm seeing this error:"),
        base.UserMessage(error),
        base.AssistantMessage("I'll help debug that. What have you tried so far?"),
    ]

图片(Images)

FastMCP 提供的 Image 类来处理图像数据。它通过创建一个 MCP 工具(Tool),实现了从给定的图像路径生成缩略图的功能。

from mcp.server.fastmcp import FastMCP, Image
from PIL import Image as PILImage

mcp = FastMCP("My App")


@mcp.tool()
def create_thumbnail(image_path: str) -> Image:
    """Create a thumbnail from an image"""
    img = PILImage.open(image_path)
    img.thumbnail((100, 100))
    return Image(data=img.tobytes(), format="png")

上下文(Context)

FastMCP 中的 Context 对象,为工具(Tool)和资源提供访问 MCP 功能的能力。Context 对象主要用于管理任务的上下文信息,例如进度跟踪、日志记录以及对资源的读取。

 

from mcp.server.fastmcp import FastMCP, Context

mcp = FastMCP("My App")


@mcp.tool()
async def long_task(files: list[str], ctx: Context) -> str:
    """Process multiple files with progress tracking"""
    for i, file in enumerate(files):
        ctx.info(f"Processing {file}")
        await ctx.report_progress(i, len(files))
        data, mime_type = await ctx.read_resource(f"file://{file}")
    return "Processing complete"

运行服务器

开发模式 MCP Inspector

并通过 开发模式(Development Mode)  快速测试和调试服务器的功能。

mcp dev server.py

Claude桌面集成

mcp install server.py

直接执行

python server.py

挂载到现有ASGI服务器

app = Starlette(routes=[Mount('/', app=mcp.sse_app())])

示例

回声服务器

@mcp.resource("echo://{message}")
def echo_resource(message: str) -> str:
    return f"资源回声: {message}"

SQLite浏览器

@mcp.tool()
def query_data(sql: str) -> str:
    conn = sqlite3.connect("database.db")
    result = conn.execute(sql).fetchall()
    return "\n".join(str(row) for row in result)

高级用法

低级服务器接口

更底层、更灵活的服务器实现,适合高级用户定制。

编写 MCP 客户端

提供客户端接口,连接 MCP 服务器进行交互。

MCP 基本元素

元素控制方描述示例
提示用户交互模板菜单
资源应用上下文数据文件
工具模型执行操作API

服务器能力

服务器启动时声明自身支持的能力,例如 prompts、resources、tools 等。