AI风向

MCP协议实战:手把手教你给Claude Code装"外挂",编程效率翻倍

MCP协议实战:手把手教你给Claude Code装"外挂",编程效率翻倍

Model Context Protocol(MCP)是2026年AI Agent领域最重要的基础设施协议。今天带你从零构建第一个MCP工具服务器,让Claude Code直接操控你的本地文件系统、数据库和API。


为什么你需要关心MCP?

2026年5月,两个数字值得关注:


  • OpenClaw(37万+ GitHub Stars)已内置MCP支持,连接WhatsApp/Telegram/Slack等20+渠道
  • Claude Code 原生支持MCP,一条配置就能让AI操控本地工具
  • Hermes Agent v0.13(14.8万Stars)也通过MCP协议与外部工具通信

MCP正在成为AI Agent的"USB-C接口"——统一的工具连接标准。掌握它,意味着你能让任何AI Agent调用你自定义的工具。


今天这篇教程,30分钟内带你走完「从零到可用」的全流程。


第一步:理解MCP的核心架构

MCP采用经典的客户端-服务器模型:


Claude Code (MCP Client)
    │
    ├── MCP Server A (文件系统工具)
    ├── MCP Server B (数据库查询工具)
    └── MCP Server C (自定义API工具)


每个MCP Server通过标准JSON-RPC协议暴露「工具列表」。Claude Code在需要时自动选择并调用对应工具。


关键概念:


  • Tool:一个可以被AI调用的函数(有名称、描述、参数schema)
  • Resource:可以被AI读取的数据源(文件、数据库记录等)
  • Prompt:预定义的提示词模板

第二步:搭建你的第一个MCP服务器(Python版)

我们用Python的官方mcp SDK,构建一个「文件信息查询」工具。


2.1 安装依赖

pip install mcp


2.2 编写服务器代码

# file_tools_server.py
import os
import json
from datetime import datetime
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent

# 创建MCP服务器实例
server = Server("file-tools")

@server.list_tools()
async def handle_list_tools() -> list[Tool]:
    """定义AI可以调用的工具列表"""
    return [
        Tool(
            name="get_file_info",
            description="获取文件/目录的详细信息:大小、修改时间、权限等",
            inputSchema={
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "文件或目录的绝对路径"
                    }
                },
                "required": ["path"]
            }
        ),
        Tool(
            name="list_directory",
            description="列出目录内容,支持过滤文件类型",
            inputSchema={
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "目录路径"
                    },
                    "pattern": {
                        "type": "string",
                        "description": "可选的文件名匹配模式,如 *.py"
                    }
                },
                "required": ["path"]
            }
        ),
    ]

@server.call_tool()
async def handle_call_tool(name: str, arguments: dict) -> list[TextContent]:
    """处理AI的工具调用请求"""
    
    if name == "get_file_info":
        path = arguments["path"]
        stat = os.stat(path)
        info = {
            "路径": path,
            "大小(bytes)": stat.st_size,
            "最后修改": datetime.fromtimestamp(stat.st_mtime).isoformat(),
            "权限": oct(stat.st_mode)[-3:],
            "是目录": os.path.isdir(path),
        }
        return [TextContent(type="text", text=json.dumps(info, ensure_ascii=False, indent=2))]
    
    elif name == "list_directory":
        path = arguments["path"]
        pattern = arguments.get("pattern", "*")
        import fnmatch
        items = []
        for entry in os.listdir(path):
            if fnmatch.fnmatch(entry, pattern):
                full_path = os.path.join(path, entry)
                items.append({
                    "名称": entry,
                    "类型": "目录" if os.path.isdir(full_path) else "文件",
                    "大小": os.path.getsize(full_path) if os.path.isfile(full_path) else "-"
                })
        return [TextContent(type="text", text=json.dumps(items, ensure_ascii=False, indent=2))]
    
    raise ValueError(f"未知工具: {name}")

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationCapabilities(
                sampling={},
                experimental={},
            ),
        )

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


2.3 配置Claude Code连接MCP服务器

在项目根目录创建 .mcp.json


{
  "mcpServers": {
    "file-tools": {
      "command": "python3",
      "args": ["/path/to/file_tools_server.py"],
      "env": {}
    }
  }
}


重启Claude Code后,在对话中输入:


帮我查一下 /home/user/projects 目录下有哪些 Python 文件,列出每个文件的大小。


Claude Code会自动识别并调用 list_directory 工具。


第三步:进阶 — 构建一个网络搜索MCP工具

现在我们来构建一个更有用的工具:让Claude Code能联网搜索。


3.1 Node.js版本(推荐,生态更好)

// web_search_server.js
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  { name: "web-search", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

// 注册工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "web_search",
      description: "搜索互联网获取最新信息。适合查询实时数据、新闻、技术文档。",
      inputSchema: {
        type: "object",
        properties: {
          query: {
            type: "string",
            description: "搜索关键词"
          },
          max_results: {
            type: "number",
            description: "返回结果数量,默认5",
            default: 5
          }
        },
        required: ["query"]
      }
    }
  ]
}));

// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  if (request.params.name === "web_search") {
    const { query, max_results = 5 } = request.params.arguments;
    
    // 使用 DuckDuckGo Instant Answer API(免费,无需API Key)
    const response = await fetch(
      `https://api.duckduckgo.com/?q=${encodeURIComponent(query)}&format=json&no_html=1`
    );
    const data = await response.json();
    
    // 格式化结果
    const results = [];
    if (data.Abstract) {
      results.push(`📌 ${data.Abstract}\n来源: ${data.AbstractURL}`);
    }
    for (const topic of (data.RelatedTopics || []).slice(0, max_results - 1)) {
      if (topic.Text) {
        results.push(`🔹 ${topic.Text}\n   ${topic.FirstURL || ''}`);
      }
    }
    
    return {
      content: [{
        type: "text",
        text: results.join("\n\n") || "未找到相关结果"
      }]
    };
  }
  throw new Error(`Unknown tool: ${request.params.name}`);
});

// 启动服务器
const transport = new StdioServerTransport();
await server.connect(transport);


3.2 配置到Claude Code

{
  "mcpServers": {
    "web-search": {
      "command": "node",
      "args": ["/path/to/web_search_server.js"]
    }
  }
}


现在你可以对Claude Code说:


搜索一下2026年5月AI Agent领域的最新融资消息


Claude Code会自动调用你的MCP工具获取实时数据。


MCP开发的三个常见坑(及解决方案)

坑1:工具描述不清晰导致AI调用错误

问题:AI不知道什么时候该用你的工具,或者传错参数。


解决方案:工具描述要像给实习生写SOP一样详细:


❌ description: "获取文件信息"
✅ description: "当需要查看文件大小、修改时间、权限信息时使用此工具。path参数必须是绝对路径,如 /home/user/document.txt。不支持通配符。"


坑2:STDIO通信的调试困难

问题:MCP Server通过标准输入/输出通信,print()会破坏协议。


解决方案:使用 sys.stderr 输出日志:


import sys
print("🔍 收到工具调用:", name, file=sys.stderr)  # 不会干扰MCP协议


坑3:工具返回格式不统一

问题:有的返回JSON,有的返回纯文本,AI解析困难。


解决方案:统一用结构化文本 + 关键信息前置:


# 好的返回格式
result = """
✅ 操作成功
文件: /home/user/data.csv
大小: 2.4 MB
行数: 15,230
建议: 数据量较大,建议先采样查看前100行
"""


实战建议:MCP工具开发优先级

根据AI创业者的实际需求,推荐按以下顺序构建MCP工具:


优先级工具类型典型场景开发时间
P0文件系统工具代码生成后自动定位文件15分钟
P0网络搜索工具获取实时信息替代训练数据30分钟
P1数据库查询工具让AI分析业务数据1小时
P1Git操作工具自动提交、创建分支45分钟
P2项目管理工具Jira/Linear任务查询2小时
P2通知工具任务完成后Slack/微信通知30分钟

下一步:从单工具到Agent流水线

掌握了单个MCP工具后,下一个跃迁是「工具组合」:


用户需求:「分析上周的用户数据,生成周报,发到Slack」

Claude Code自动编排:

  1. 调用 database-query MCP → 查数据
  2. 调用 data-analysis MCP → 生成图表
  3. 调用 file-tools MCP → 保存报告
  4. 调用 slack-notify MCP → 发送通知


这正是Manufact(MCP工具平台,刚完成A轮融资)正在做的事情——他们上周刚发布了MCP开发工具链,让Agent能在ChatGPT和Claude Code之间无缝运行同一个MCP工具。


总结

MCP不是又一个框架,它是AI Agent生态的标准协议。今天你学会了:


  1. ✅ MCP的客户端-服务器架构
  2. ✅ 用Python构建文件系统MCP工具
  3. ✅ 用Node.js构建网络搜索MCP工具
  4. ✅ 三个常见坑及避坑方案
  5. ✅ 工具开发优先级规划

现在就动手:花15分钟搭建一个文件系统MCP工具,你会惊讶地发现Claude Code突然变得"无所不能"。


#AI创业 #MCP协议 #ClaudeCode #Agent开发 #一人公司


本文由AI辅助创作,经人工审核编辑发布