Skip to content

Model Context Protocol

什么是 MCP?

MCP (Model Context Protocol,模型上下文协议) 是一个连接 AI 应用与外部系统的开源协议标准。

mcp-simple-diagram

MCP 架构中的关键参与者包括:

  • MCP 宿主 (Host):协调和管理一个或多个 MCP 客户端的 AI 应用
  • MCP 客户端 (Client):维持与 MCP 服务端连接并获取上下文供 MCP 宿主使用的组件
  • MCP 服务端 (Server):为 MCP 客户端提供上下文的程序

例如:Visual Studio Code 充当 MCP 宿主。当 Visual Studio Code 建立与 MCP 服务端(如 Sentry MCP 服务端)的连接时,Visual Studio Code 运行时会实例化一个 MCP 客户端对象来维持该连接。当 Visual Studio Code 随后连接到另一个 MCP 服务端(如本地文件系统服务端)时,它会实例化另一个 MCP 客户端对象来维持此连接。

注意,MCP 服务端是指提供上下文数据的程序,无论其运行在何处。MCP 服务端可以在本地或远程执行。例如,当 Claude Desktop 启动文件系统服务端时,该服务端由于使用 STDIO 传输而在同一台机器上本地运行,这通常被称为“本地”MCP 服务端。官方的 Sentry MCP 服务端运行在 Sentry 平台上,并使用可流式 HTTP 传输,这通常被称为“远程”MCP 服务端。

使用 Python 构建一个简单的 MCP(Model Context Protocol)服务。

环境准备

安装 Python 环境

确保你的系统已安装 Python 3.10 或更高版本。可以通过以下命令检查:

bash
python --version

如果没有安装,请从 https://www.python.org/ 下载并安装。

安装 MCP Python SDK

使用官方 MCP Python SDK,它提供了构建服务端和客户端的基础组件。

bash
pip install mcp

或者,如果你希望安装包含开发依赖的完整版本:

bash
pip install "mcp[cli]"

安装完成后,可以验证安装:

bash
pip show mcp

创建 MCP 服务

我们将编写一个基础的 MCP 服务,它能够:

  • 提供一个简单的工具:add,接收两个整数并返回它们的和。
  • 提供一个静态资源:greeting://{name},返回一条个性化的问候语。

创建一个新的目录(例如 simple-mcp-server),并在其中创建 Python 文件 server.py。项目结构如下:

txt
simple-mcp-server/
├── server.py
└── README.md (可选)

server.py 中的内容如下:

python
# 1. 导入必要模块
import asyncio
import mcp.server.stdio
import mcp.types as types
from typing import Any
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions


# 2. 创建服务实例
server = Server("simple-mcp-server")

# 3. 添加工具
# 工具是可以被客户端调用的函数。我们将实现一个简单的加法工具

@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
    """列出所有工具"""
    return [
        types.Tool(
            name="add",
            description="Add two numbers together",
            inputSchema={
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "First number"},
                    "b": {"type": "number", "description": "Second number"},
                },
                "required": ["a", "b"],
            },
        )
    ]

@server.call_tool()
async def handle_call_tool(
    name: str, arguments: dict
) -> list[types.TextContent]:
    """处理工具调用"""
    if name == "add":
        a = arguments.get("a")
        b = arguments.get("b")
        if a is None or b is None:
            raise ValueError("Missing arguments a or b")
        result = a + b
        return [types.TextContent(type="text", text=str(result))]
    else:
        raise ValueError(f"Unknown tool: {name}")

# 4. 添加资源
# 资源是可以被客户端读取的数据项,可以是静态的或动态生成的
# 我们将实现一个动态资源模板 greeting://{name},当客户端读取时返回 Hello, {name}!

@server.list_resources()
async def handle_list_resources() -> list[types.Resource]:
    """列出静态资源(本服务没有静态资源)"""
    return []

@server.list_resource_templates()
async def handle_list_resource_templates() -> list[types.ResourceTemplate]:
    """列出资源模板"""
    return [
        types.ResourceTemplate(
            uriTemplate="greeting://{name}",
            name="Personalized greeting",
            description="A greeting message for a specific name",
            mimeType="text/plain",
        )
    ]

@server.read_resource()
async def handle_read_resource(uri: Any) -> str:
    """读取资源内容"""
    # 将 AnyUrl 对象转换为字符串
    uri_str = str(uri)
    if uri_str.startswith("greeting://"):
        name = uri_str.split("://")[1]
        return f"Hello, {name}!"
    else:
        raise ValueError(f"Unknown resource: {uri}")

# 5. 运行服务
# MCP 服务端通常通过标准输入/输出(stdio)与客户端通信
# 我们需要使用 mcp.server.stdio 提供的辅助函数来启动服务。

async def main():
    """主函数:启动服务"""
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name="simple-mcp-server",
                server_version="0.1.0",
                capabilities=server.get_capabilities(
                    notification_options=NotificationOptions(),
                    experimental_capabilities={},
                ),
            ),
        )

if __name__ == "__main__":
    asyncio.run(main())

运行和测试

完成代码编写后,我们需要测试这个 MCP 服务是否正常工作。

MCP 官方提供了一个图形化调试工具:MCP Inspector,可以用来连接你的服务并测试其功能。

安装并运行 Inspector:

bash
npm install -g @modelcontextprotocol/inspector
mcp-inspector python server.py

Inspector 会启动一个 Web 界面,在浏览器中打开该地址。

inspector

在实际应用中集成 MCP

在实际应用(如:Cursor)的设置中找到 MCP 模块,并添加 MCP:

json
{
  "mcpServers": {
    "simple-mcp-server": {
      "command": "python",
      "args": ["/absolute/path/to/your/server.py"]
    }
  }
}

点击保存后,如果配置正确,服务状态会显示为绿色的 Running 或 Connected。

参考

https://modelcontextprotocol.io/

https://mcp-docs.cn/