前言

2025年,AI Agent 从概念走向落地,但一个尴尬的问题浮出水面:大模型再聪明,也只是一个"大脑",没有手、没有眼、没有连接外部世界的能力。

你让 ChatGPT 帮你查一下今天的日程、读一个 PDF 文件、操作一下数据库——它做不到。因为它被困在自己的对话框里,和外部工具之间隔着一堵墙。

MCP(Model Context Protocol) 就是来拆这堵墙的。

Anthropic 在 2024 年底开源了这个协议,目标很简单:给 AI Agent 一个标准化的方式来连接外部工具和数据源。 到了 2025 年,MCP 已经成为 AI 开发圈最热的基础设施之一——OpenAI、Google、各大框架纷纷跟进支持。

MCP架构概览

今天这篇文章,不讲概念废话,直接从零开始,带你用 Python 搭一个 MCP Server,让你的 AI Agent 能真正"动手干活"。


MCP 到底解决了什么问题?

在 MCP 之前,你想让大模型调用外部工具,大概经历了这几个阶段:

阶段一:Function Calling

OpenAI 率先推出 function calling,让模型可以输出结构化的函数调用请求。问题在于:每个模型的 function calling 格式不一样,换个模型就得改代码。

阶段二:LangChain Tools

LangChain 封装了一层工具抽象,但本质上还是框架内的私有协议。你用 LangChain 写的工具,换个框架就用不了。

阶段三:MCP

MCP 的思路是:定义一套开放协议,任何工具只要实现这个协议,就能被任何支持 MCP 的 AI 客户端调用。

这就像 USB 接口——不管你插的是键盘、鼠标还是U盘,只要遵循 USB 协议,就能即插即用。

方案 优势 痛点
Function Calling 原生支持,简单直接 各模型格式不统一
LangChain Tools 生态丰富 框架绑定,迁移成本高
MCP 开放协议,即插即用 生态还在建设中

MCP 的核心架构

MCP 采用的是 Client-Server 架构,但和传统的 HTTP 服务不太一样:

MCP通信流程

┌──────────────┐     JSON-RPC      ┌──────────────┐
│  MCP Client  │ ◄──────────────► │  MCP Server  │
│  (AI 应用)    │    stdio/SSE      │  (工具提供者) │
└──────────────┘                   └──────────────┘

三个核心概念:

  1. Tools(工具):Server 暴露给 Client 调用的函数。比如"读取文件"、“查询数据库”、“发送邮件”
  2. Resources(资源):Server 提供的数据源。比如文件内容、数据库表结构
  3. Prompts(提示模板):Server 提供的预设提示词,帮助模型更好地使用工具

通信方式有两种:

  • stdio:通过标准输入输出通信,适合本地工具
  • SSE(Server-Sent Events):通过 HTTP 通信,适合远程服务

实战:从零搭建一个 MCP Server

说了这么多,不如动手。我们来写一个实用的 MCP Server——系统信息查询工具,能查 CPU、内存、磁盘信息。

环境准备

# 创建项目目录
mkdir mcp-sysinfo && cd mcp-sysinfo

# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# 安装依赖
pip install mcp psutil

编写 Server 代码

创建文件 server.py

import json
import psutil
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

# 创建 MCP Server 实例
server = Server("sysinfo")

# 定义工具列表
@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="get_cpu_info",
            description="获取 CPU 使用率和核心数信息",
            inputSchema={
                "type": "object",
                "properties": {},
                "required": []
            }
        ),
        Tool(
            name="get_memory_info",
            description="获取系统内存使用情况",
            inputSchema={
                "type": "object",
                "properties": {},
                "required": []
            }
        ),
        Tool(
            name="get_disk_info",
            description="获取磁盘分区和使用情况",
            inputSchema={
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "磁盘路径,默认为 /",
                        "default": "/"
                    }
                },
                "required": []
            }
        )
    ]

# 实现工具调用逻辑
@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "get_cpu_info":
        cpu_percent = psutil.cpu_percent(interval=1)
        cpu_count = psutil.cpu_count()
        cpu_freq = psutil.cpu_freq()
        result = {
            "cpu_percent": cpu_percent,
            "cpu_count_logical": cpu_count,
            "cpu_freq_current": cpu_freq.current if cpu_freq else None,
        }
    elif name == "get_memory_info":
        mem = psutil.virtual_memory()
        result = {
            "total_gb": round(mem.total / (1024**3), 2),
            "available_gb": round(mem.available / (1024**3), 2),
            "percent": mem.percent,
        }
    elif name == "get_disk_info":
        path = arguments.get("path", "/")
        disk = psutil.disk_usage(path)
        result = {
            "total_gb": round(disk.total / (1024**3), 2),
            "used_gb": round(disk.used / (1024**3), 2),
            "free_gb": round(disk.free / (1024**3), 2),
            "percent": disk.percent,
        }
    else:
        result = {"error": f"未知工具: {name}"}

    return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False, indent=2))]

# 启动 Server
async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream, server.create_initialization_options())

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

测试运行

python server.py

如果没有任何报错输出,说明 Server 启动成功了。它会通过 stdin/stdout 等待 Client 的 JSON-RPC 请求。


配置 Claude Desktop 连接 MCP Server

写好了 Server,接下来让 Claude Desktop 能调用它。

编辑 Claude Desktop 配置文件:

{
  "mcpServers": {
    "sysinfo": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

配置文件位置:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

重启 Claude Desktop,你会看到工具图标旁边多了一个锤子标志——说明 MCP Server 连接成功了。

现在你可以直接问 Claude:“我的电脑 CPU 和内存使用情况怎么样?” 它会自动调用你的 Server 获取实时数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


进阶:添加更多实用工具

一个 Server 当然不止三个工具。下面是几个实用的扩展方向:

文件搜索工具

Tool(
    name="search_files",
    description="在指定目录下搜索文件",
    inputSchema={
        "type": "object",
        "properties": {
            "directory": {"type": "string", "description": "搜索目录"},
            "pattern": {"type": "string", "description": "文件名匹配模式,如 *.py"}
        },
        "required": ["directory", "pattern"]
    }
)

HTTP 请求工具

Tool(
    name="http_request",
    description="发送 HTTP 请求并返回响应",
    inputSchema={
        "type": "object",
        "properties": {
            "url": {"type": "string"},
            "method": {"type": "string", "enum": ["GET", "POST"], "default": "GET"}
        },
        "required": ["url"]
    }
)

数据库查询工具

Tool(
    name="query_database",
    description="执行 SQL 查询(只读)",
    inputSchema={
        "type": "object",
        "properties": {
            "sql": {"type": "string", "description": "SELECT 查询语句"},
            "database": {"type": "string", "description": "数据库名"}
        },
        "required": ["sql"]
    }
)

MCP 生态现状:2025 年已不是玩具

截至 2025 年 5 月,MCP 生态已经相当成熟:

客户端支持:

  • Claude Desktop(原生支持)
  • Cursor / Windsurf(代码编辑器)
  • OpenClaw(全功能 AI Agent 框架)
  • Continue.dev(VS Code 插件)
  • Cline(终端 AI 助手)

社区 Server:

  • GitHub MCP Server:操作仓库、PR、Issue
  • Slack MCP Server:读写频道消息
  • PostgreSQL MCP Server:数据库查询
  • Puppeteer MCP Server:浏览器自动化
  • 文件系统 MCP Server:本地文件操作

企业级应用:

  • 部分公司已将 MCP 用于内部 DevOps 流水线
  • 数据分析团队用 MCP 让 AI 直接查询数据仓库
  • 客服系统通过 MCP 对接 CRM 和工单系统

安全注意事项

MCP 虽好,但安全问题不能忽视:

  1. 权限控制:不要给 MCP Server 过高的系统权限。查 CPU 信息没问题,但删除文件、执行任意命令就要三思了
  2. 输入校验:所有来自 Client 的参数都要校验,防止 SQL 注入、路径遍历等攻击
  3. 沙箱运行:生产环境建议在沙箱中运行 MCP Server,限制其系统调用
  4. 审计日志:记录所有工具调用,便于事后追溯
# 简单的输入校验示例
def validate_sql(sql: str) -> bool:
    """只允许 SELECT 查询,禁止修改操作"""
    forbidden = ["DROP", "DELETE", "UPDATE", "INSERT", "ALTER", "EXEC"]
    sql_upper = sql.upper()
    return not any(keyword in sql_upper for keyword in forbidden)

写在最后

MCP 不是什么黑科技,它就是一层协议。但正是这层协议,让 AI Agent 从"能聊天"变成了"能干活"。

2025 年的 AI 开发,已经不是在比谁的 prompt 写得好了——而是在比谁的 Agent 能连接更多、更可靠的外部能力。 MCP 就是这场竞赛的基础设施。

如果你还在用硬编码的方式让大模型调用工具,是时候切换到 MCP 了。协议统一了,生态建起来了,你的工具就能被所有支持 MCP 的客户端即插即用。

这不是未来,这是现在。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐