30分钟搭建MCP Server:AI Agent的“USB-C接口“实战指南

64 阅读6分钟

2026年,MCP(Model Context Protocol)已成为AI Agent工具集成的标准协议。本文从零搭建一个完整的MCP Server(文件系统操作+Web搜索),并集成到Claude Code和Cursor中,全程实战,代码可运行。

关键词:MCP协议、AI Agent、MCP Server、Python、Claude Code、Cursor、Model Context Protocol


一、为什么AI Agent需要MCP?

1.1 从"笼中大脑"说起

AI Agent的"智能"被困在LLM内部——LLM再聪明,也无法直接读取你的文件、搜索网页、操作数据库。要让AI真正"动手干活",必须给它接上外部世界的接口。

1.2 碎片化的工具集成方案

在MCP出现之前,AI工具集成的方案是碎片化的:

| 方案 | 问题 | | --- | --- | | OpenAI Function Calling | 每家模型各一套,不通用 | | LangChain Tools | 框架锁定,不支持跨平台 | | IDE私有插件系统 | 各有各的插件格式 |

核心痛点:AI工具每对接一个外部能力,就要写一套适配代码。

1.3 MCP的"USB-C"隐喻

2024年11月,Anthropic提出了MCP(Model Context Protocol),定位为"AI应用的USB-C接口"——就像USB-C统一了各种充电口,MCP统一了AI工具的能力接口。

核心理念:一次开发,到处可用。同一个MCP Server,可以即插即用地接入Claude Code、Cursor以及任何支持MCP的AI工具。


二、MCP协议核心原理

2.1 三大原语

MCP采用客户端-服务器架构,Server通过三大原语暴露能力:

| 原语 | 作用 | 类比到HTTP | | --- | --- | --- | | Tool | 暴露可执行的操作(读文件、搜索、查DB) | POST请求 | | Resource | 提供结构化数据读取(文件内容、系统状态) | GET请求 | | Prompt | 可复用的交互模板 | 预定义请求体 |

2.2 传输层

MCP支持三种传输方式:

| 传输方式 | 适用场景 | | --- | --- | | stdio | 本地子进程,低延迟,适合CLI工具集成 | | SSE | 远程服务,适合跨网络调用 | | Streamable HTTP | v1.2新增,支持长时间运行任务 |

2.3 生命周期

  1. 初始化:Client与Server能力协商(capabilities交换)

  2. 操作:Client调用Tool、读取Resource、使用Prompt

  3. 关闭:优雅关闭,释放资源


三、MCP Server架构设计

Python SDK提供两种构建方式:

  • Server类(底层API):直接操作Request/Response,精细控制

  • FastMCP封装(高阶API):基于Python decorator,一行代码注册一个Tool

推荐:大部分场景用FastMCP,自动处理Schema生成、消息路由、JSON-RPC序列化。


四、Python实战:从零搭建MCP Server

4.1 环境准备

# 创建项目
mkdir mcp-server-demo
cd mcp-server-demo
python -m venv venv
source venv/bin/activate  # Windows: venv\Scripts\activate

# 安装依赖
pip install mcp httpx

4.2 基础Server骨架

from mcp.server.fastmcp import FastMCP

server = FastMCP("MyAssistant")

@server.on_startup()
async def startup():
    print("Server started!")

@server.on_shutdown()
async def shutdown():
    print("Server shutting down...")

if __name__ == "__main__":
    server.run(transport="stdio")

4.3 实现Tool:文件系统操作

import os
from pathlib import Path
from mcp.types import TextContent

@server.tool()
async def read_file(path: str) -> list[TextContent]:
    """读取指定文件的内容。"""
    try:
        content = Path(path).read_text(encoding="utf-8")
        return [TextContent(type="text", text=content)]
    except FileNotFoundError:
        raise McpError(f"文件不存在: {path}")
    except Exception as e:
        raise McpError(f"读取文件失败: {str(e)}")

@server.tool()
async def write_file(path: str, content: str) -> list[TextContent]:
    """将内容写入指定文件。"""
    try:
        Path(path).write_text(content, encoding="utf-8")
        return [TextContent(type="text", text=f"成功写入文件: {path}")]
    except Exception as e:
        raise McpError(f"写入文件失败: {str(e)}")

@server.tool()
async def list_directory(path: str = ".") -> list[TextContent]:
    """列出指定目录的内容。"""
    try:
        items = os.listdir(path)
        return [TextContent(type="text", text="\n".join(items))]
    except FileNotFoundError:
        raise McpError(f"目录不存在: {path}")

4.4 实现Tool:Web搜索

import httpx

@server.tool()
async def web_search(query: str, max_results: int = 5) -> list[TextContent]:
    """搜索网页内容,返回搜索结果摘要。"""
    search_url = "https://api.duckduckgo.com/"
    params = {
        "q": query,
        "format": "json",
        "no_html": 1,
        "skip_disambig": 1,
    }
    async with httpx.AsyncClient(timeout=10.0) as client:
        try:
            response = await client.get(search_url, params=params)
            response.raise_for_status()
            data = response.json()
            results = []
            for item in data.get("RelatedTopics", [])[:max_results]:
                if "Text" in item and "FirstURL" in item:
                    results.append(f"- {item['Text']}\n  {item['FirstURL']}")
            if not results:
                return [TextContent(type="text", text=f"未找到相关结果")]
            return [TextContent(type="text", text="\n\n".join(results))]
        except httpx.TimeoutException:
            raise McpError("搜索请求超时")

4.5 实现Resource:系统状态

import platform

@server.resource("system://status")
async def system_status() -> str:
    """获取系统运行状态信息。"""
    info = [
        f"系统: {platform.system()} {platform.release()}",
        f"架构: {platform.machine()}",
        f"Python: {platform.python_version()}",
    ]
    return "\n".join(info)

4.6 实现Prompt:操作模板

@server.prompt()
def search_analysis(query: str) -> str:
    """搜索分析模板:先搜索再分析结果。"""
    return f"""
请按照以下步骤进行分析:
1. 使用 web_search 工具搜索关键词: "{query}"
2. 阅读搜索结果,提取关键信息
3. 对搜索结果进行综合分析
4. 给出结论和建议
"""

4.7 测试与调试

使用MCP Inspector图形化调试:

npx @modelcontextprotocol/inspector

在Inspector中加载Server(stdio模式,命令:python server.py),即可交互测试所有Tool、Resource和Prompt。


五、集成到Claude Code和Cursor

5.1 Claude Code配置

创建 claude.json:

{
  "mcpServers": {
    "my-assistant": {
      "command": "python",
      "args": ["path/to/server.py"],
      "env": { "PYTHONUNBUFFERED": "1" }
    }
  }
}

启动Claude Code后,自动发现Server的所有工具,在对话中自然触发调用。

5.2 Cursor配置

创建 .cursor/mcp.json:

{
  "mcpServers": {
    "my-assistant": {
      "command": "python",
      "args": ["path/to/server.py"],
      "env": { "PYTHONUNBUFFERED": "1" }
    }
  }
}

在Cursor的Settings → Features → MCP中查看已配置的Server和工具列表。

5.3 多Server组合

{
  "mcpServers": {
    "my-filesystem": { "command": "python", "args": ["fs-server.py"] },
    "my-search": { "command": "python", "args": ["search-server.py"] },
    "my-database": { "command": "python", "args": ["db-server.py"] }
  }
}

同一个对话中,AI Agent可组合调用多个Server的能力——这就是MCP的"即插即用"体验。


六、MCP vs 插件 vs A2A

6.1 MCP vs 传统插件

| 维度 | MCP | 传统插件 | | --- | --- | --- | | 协议 | 开放标准 | 私有格式,厂商锁定 | | 能力发现 | 动态协商,自动暴露 | 静态注册,需预配置 | | 通信模式 | 双向(Server可推送) | 单向(Client调用) | | 多语言 | Python/TS/Java/Kotlin | 通常单语言 |

6.2 MCP vs Google A2A

互补而非竞争:MCP解决"Agent如何用工具",A2A解决"Agent之间如何通信"。

Anthropic与Google已宣布MCP + A2A合作,形成完整Agent生态栈。

6.3 生态展望

  • CNCF沙箱项目(2026-03):进入云原生基金会

  • Streamable HTTP(v1.2):支持长时间运行任务

  • Roots权限声明:Server声明资源访问范围,增强安全

  • 工具市场:类似VS Code扩展市场,MCP Server Marketplace正在形成


七、总结

30分钟,你从零搭建了一个完整的MCP Server,它:

  • 能读文件、写文件、列目录

  • 能搜索网页,获取实时信息

  • 能暴露系统状态资源

  • 能提供标准化的操作模板

  • 能即插即用地集成到Claude Code和Cursor

下一步可以做什么?

  • 添加数据库查询能力(SQLite/PostgreSQL)

  • 实现文件监听(Watchdog)+ Notification推送

  • 以SSE模式部署为远程服务

  • 参与MCP社区,贡献Server


参考资料

  1. MCP官方规范(一级)

  2. MCP Python SDK(一级)

  3. MCP官方示例仓库(一级)

  4. Anthropic MCP总览博客(二级)

  5. Claude Code MCP集成文档(二级)

  6. Cursor MCP集成文档(二级)