MCP协议超详细教程,从入门到实战

MCP协议超详细教程,从入门到实战

身份:AI工具探索者 | 写作日期:2026年5月10日


一、场景:为什么我需要MCP?

上周我遇到了一个很尴尬的场景。

我想让Claude帮我分析本地项目的依赖关系,然后自动生成一份升级建议。我打开Claude Desktop,问它"帮我看看这个项目的package.json有什么可以升级的"。

它给了我一堆建议。但问题是------它根本看不到我本地文件!我只能手动把package.json复制粘贴给它,它再给我建议,我再手动改代码。来回折腾了十几分钟,最后发现它连node_modules里的版本冲突都没看出来。

那一刻我突然意识到:AI模型再聪明,也只是一个"文本处理器"。它看不到你的文件,连不到你的数据库,更没法帮你执行命令。

直到我发现了MCP。


二、MCP到底是什么?

MCP(Model Context Protocol)是Anthropic在2024年底推出的一个开源协议。

用一句话概括:MCP就是AI应用的"USB-C接口"

就像USB-C让你能用一根线连接各种设备一样,MCP让你能用一个标准方式,让AI模型连接到:

  • 本地文件(比如你的项目代码)
  • 数据库(PostgreSQL、MySQL、SQLite)
  • 外部工具(搜索引擎、计算器、日历)
  • 自定义工作流(你写的一堆Python脚本)

核心思想就一个:别让每个AI应用都单独写一套集成代码。写一个MCP服务器,所有支持MCP的AI客户端都能用。


三、环境准备

需要的东西

项目 版本 说明
Python 3.10+ 我用的是3.12
uv 最新版 包管理器,比pip快很多
Claude Desktop 最新版 或者Cursor、VS Code Copilot

安装MCP SDK

bash 复制代码
# 用uv创建项目
uv init mcp-tutorial
cd mcp-tutorial
uv venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# 安装MCP SDK(带CLI工具)
uv add "mcp[cli]" httpx

踩坑1 :直接用pip install mcp会装到旧版本,一定要用mcp[cli]这个extra,不然没有mcp命令行工具,调试会很麻烦。


四、动手:写一个任务追踪MCP服务器

我写了一个简单的任务追踪服务器,让Claude能帮我管理本地任务清单。

4.1 项目结构

bash 复制代码
mcp-tutorial/
├── tasks.json          # 任务数据文件
├── server.py           # MCP服务器代码
└── pyproject.toml      # 项目配置

4.2 任务数据文件(tasks.json)

json 复制代码
{
  "tasks": [
    {
      "id": 1,
      "title": "学习MCP协议",
      "status": "completed",
      "priority": "high",
      "created_at": "2026-05-08"
    },
    {
      "id": 2,
      "title": "写这篇教程",
      "status": "in_progress",
      "priority": "high",
      "created_at": "2026-05-10"
    },
    {
      "id": 3,
      "title": "部署服务器到生产环境",
      "status": "pending",
      "priority": "medium",
      "created_at": "2026-05-11"
    }
  ]
}

4.3 核心代码(server.py

python 复制代码
"""
一个简单的任务追踪MCP服务器
让Claude能帮我管理本地任务清单
"""

import json
from pathlib import Path
from typing import Any
from mcp.server.fastmcp import FastMCP

# 初始化FastMCP服务器
# 名字会显示在Claude Desktop的MCP服务器列表里
mcp = FastMCP("TaskTracker")

# 数据文件路径
TASKS_FILE = Path(__file__).parent / "tasks.json"


def load_tasks() -> dict:
    """加载任务数据"""
    if not TASKS_FILE.exists():
        return {"tasks": []}
    with open(TASKS_FILE, "r", encoding="utf-8") as f:
        return json.load(f)


def save_tasks(data: dict) -> None:
    """保存任务数据"""
    with open(TASKS_FILE, "w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)


# ==================== 工具(Tools) ====================
# 工具是AI可以主动调用的函数,AI决定什么时候用

@mcp.tool()
def add_task(title: str, priority: str = "medium") -> str:
    """添加一个新任务"""
    data = load_tasks()
    new_id = max((t["id"] for t in data["tasks"]), default=0) + 1
    
    task = {
        "id": new_id,
        "title": title,
        "status": "pending",
        "priority": priority,
        "created_at": "2026-05-10"
    }
    data["tasks"].append(task)
    save_tasks(data)
    
    return f"✅ 已添加任务 #{new_id}: {title}"


@mcp.tool()
def list_tasks(status: str | None = None) -> str:
    """列出所有任务,可选按状态过滤"""
    data = load_tasks()
    tasks = data["tasks"]
    
    if status:
        tasks = [t for t in tasks if t["status"] == status]
    
    if not tasks:
        return "📭 没有找到任务"
    
    lines = ["📋 任务列表:"]
    for t in tasks:
        icon = {"pending": "⏳", "in_progress": "🔄", "completed": "✅"}.get(t["status"], "❓")
        lines.append(f"  {icon} #{t['id']} [{t['priority']}] {t['title']}")
    
    return "\n".join(lines)


@mcp.tool()
def complete_task(task_id: int) -> str:
    """标记任务为已完成"""
    data = load_tasks()
    
    for task in data["tasks"]:
        if task["id"] == task_id:
            task["status"] = "completed"
            save_tasks(data)
            return f"✅ 任务 #{task_id} 已完成!"
    
    return f"❌ 没找到任务 #{task_id}"


@mcp.tool()
def delete_task(task_id: int) -> str:
    """删除一个任务"""
    data = load_tasks()
    original_count = len(data["tasks"])
    data["tasks"] = [t for t in data["tasks"] if t["id"] != task_id]
    
    if len(data["tasks"]) == original_count:
        return f"❌ 没找到任务 #{task_id}"
    
    save_tasks(data)
    return f"🗑️ 已删除任务 #{task_id}"


# ==================== 资源(Resources) ====================
# 资源是只读数据源,AI可以读取但不能修改

@mcp.resource("tasks://all")
def get_all_tasks() -> str:
    """获取所有任务的原始JSON数据"""
    data = load_tasks()
    return json.dumps(data, ensure_ascii=False, indent=2)


@mcp.resource("tasks://pending")
def get_pending_tasks() -> str:
    """获取待办任务"""
    data = load_tasks()
    pending = [t for t in data["tasks"] if t["status"] == "pending"]
    return json.dumps(pending, ensure_ascii=False, indent=2)


# ==================== 提示(Prompts) ====================
# 提示是预定义的指令模板,用户手动触发

@mcp.prompt()
def daily_planner() -> str:
    """每日计划助手"""
    return """请帮我规划今天的工作:

1. 先列出所有待办任务(pending状态)
2. 根据优先级排序
3. 帮我制定一个合理的时间安排

如果任务太多,建议我优先做哪些。"""


# ==================== 启动服务器 ====================

def main():
    # 重要:STDIO传输模式下,日志必须写到stderr,不能写stdout
    # 写stdout会破坏JSON-RPC协议通信
    import sys
    print("🚀 TaskTracker MCP服务器已启动", file=sys.stderr)
    print("   连接方式: stdio", file=sys.stderr)
    
    mcp.run(transport="stdio")


if __name__ == "__main__":
    main()

五、连接Claude Desktop

5.1 配置Claude Desktop

打开Claude Desktop的配置文件(路径因系统而异):

系统 路径
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json
Linux ~/.config/Claude/claude_desktop_config.json

添加MCP服务器配置:

json 复制代码
{
  "mcpServers": {
    "task-tracker": {
      "command": "uv",
      "args": [
        "--directory",
        "/Users/yourname/mcp-tutorial",
        "run",
        "server.py"
      ]
    }
  }
}

踩坑2:路径一定要用绝对路径!我用相对路径试了三次都连不上,最后才发现是这个问题。

5.2 重启Claude Desktop

保存配置后,必须完全关闭再打开Claude Desktop。不是最小化,是彻底退出。

打开后,在Claude的输入框旁边会看到一个插头图标🔌,点击就能看到已连接的MCP服务器。


六、效果演示

连接成功后,你可以这样跟Claude对话:

用户:帮我看看今天有哪些任务要做

Claude (调用list_tasks工具):

less 复制代码
📋 任务列表:
  ⏳ #3 [medium] 部署服务器到生产环境

用户:把任务3标记为已完成

Claude (调用complete_task工具):

bash 复制代码
✅ 任务 #3 已完成!

用户:添加一个新任务"学习MCP资源API",优先级高

Claude (调用add_task工具):

bash 复制代码
✅ 已添加任务 #4: 学习MCP资源API

用户:显示所有待办任务

Claude (读取tasks://pending资源):

json 复制代码
[
  {
    "id": 4,
    "title": "学习MCP资源API",
    "status": "pending",
    "priority": "high",
    "created_at": "2026-05-10"
  }
]

七、常见问题FAQ

Q1: 为什么我的Claude Desktop看不到MCP服务器?

A: 三个最常见原因:

  1. 配置文件路径不对(检查是不是写到了正确的claude_desktop_config.json
  2. 路径用了相对路径(必须用绝对路径)
  3. 没重启Claude Desktop(保存后必须完全退出再打开)

Q2: 日志看不到,怎么调试?

A : MCP服务器用STDIO传输时,stdout被协议占用了。所有日志必须写stderr

python 复制代码
# ❌ 错误
print("Debug info")

# ✅ 正确
import sys
print("Debug info", file=sys.stderr)

# 或者用logging
import logging
logging.info("Debug info")

Q3: 能用Python以外的语言写MCP服务器吗?

A: 当然可以!官方支持:

  • TypeScript/JavaScript@modelcontextprotocol/sdk
  • Pythonmcp SDK(本文用的)
  • RustGoJava也有官方SDK

Q4: MCP服务器一定要本地运行吗?

A : 不一定。除了stdio(本地进程),还支持:

  • SSE(Server-Sent Events):HTTP长连接,适合远程服务器
  • WebSocket:双向通信

但新手建议先用stdio,最简单。


八、总结

MCP的核心就三件事:

概念 谁控制 作用
Tools AI模型 AI主动调用的函数(写文件、调API)
Resources AI应用 只读数据源(文件、数据库)
Prompts 用户 预定义的工作流模板

写一个MCP服务器,所有支持MCP的AI客户端都能用------这就是它的价值。

我现在已经用它连接了:

  • 本地项目文件(让Claude能直接读代码)
  • SQLite数据库(让Claude能查数据)
  • 自定义Python脚本(让Claude能执行我写的工具)

说实话,刚开始觉得有点复杂,但写通一个服务器后,后面都是复制粘贴改改而已。

如果你也想让AI真正"动手"做事而不是光动嘴,MCP值得试试。


如果觉得有帮助,欢迎点赞收藏 ❤️ 更多AI工具实战教程,关注我第一时间获取~

相关推荐
小星AI3 小时前
Kimi Code CLI 超详细教程,附源码
人工智能·agent
牧艺4 小时前
Cursor Rules / Skills 分层设计:让 Agent 像「团队新同事」
前端·人工智能·cursor
shepherd1114 小时前
一文带你掌握 LLM、Token、Context、Prompt、RAG、MCP、Skill、Agent 等 AI 核心概念
人工智能·后端·ai编程
小林ixn4 小时前
MCP 保姆级入门指南:AI 的“万能充电口”到底怎么玩?
人工智能
转转技术团队6 小时前
没有测试的核心代码,怎么交给 AI 重构
人工智能
爱读源码的大都督7 小时前
Claude Code源码分析(三):为什么系统提示词中需要有tools呢?
前端·人工智能·后端
半个落月8 小时前
LLM如何预测下一个Token?一文拆解Transformer核心流程
人工智能
触底反弹8 小时前
🔥 2026 年爆火的 Harness Engineering 到底是什么?从原理到实战一文讲透
javascript·人工智能·程序员