🚀 龙虾新手指南

MCP协议解析:Anthropic如何统一AI工具调用标准

发布时间:2026-05-31 分类: 龙虾新手指南
摘要:MCP协议硬核解析:Anthropic如何用新标准统一Agent工具调用?想让AI查天气、读文件、调API,结果发现要为每个工具写一堆适配代码?不同工具的接口五花八门,LLM像个只会说普通话的外国人,每到一个地方都要配个翻译。这就是当前AI工具调用的碎片化痛点。MCP(Model Context Protocol)是Anthropic推出的“万能转接头”标准——它想让所有工具都说同一种“语言...

封面

MCP协议硬核解析:Anthropic如何用新标准统一Agent工具调用?

想让AI查天气、读文件、调API,结果发现要为每个工具写一堆适配代码?不同工具的接口五花八门,LLM像个只会说普通话的外国人,每到一个地方都要配个翻译。

这就是当前AI工具调用的碎片化痛点。MCP(Model Context Protocol)是Anthropic推出的“万能转接头”标准——它想让所有工具都说同一种“语言”,让LLM能即插即用。

问题:工具调用的碎片化困境

想象一下:你开发了一个AI助手,需要它能:

  • 读取本地文件
  • 查询数据库
  • 调用天气API
  • 操作Git仓库

传统做法是为每个功能写专门的适配层。文件系统有文件系统的接口,数据库有数据库的驱动,每个API都有自己的认证方式...你的代码很快变成一锅粥,而且换一个LLM可能就要重写一遍。

更痛苦的是,当你想用别人开发的工具时,往往要花大量时间理解对方的代码结构。工具之间无法互通,生态是割裂的。

方案:MCP作为“万能转接头”

MCP的核心思想很简单:定义一套标准协议,让所有工具都通过这个协议与LLM对话

就像USB-C接口一样——不管你是充电、传数据还是接显示器,都用同一个接口。MCP就是AI世界的USB-C。

MCP的三层架构

MCP采用经典的客户端-服务器架构,但加了一个关键角色:

  1. MCP Host:运行AI模型的环境(比如Claude Desktop、Cursor)
  2. MCP Client:Host内部的协议处理器,负责与Server通信
  3. MCP Server:提供具体工具的服务端,每个Server可以提供多个工具
你的AI应用 (Host)
    ↓ (MCP协议)
MCP Client
    ↓ (MCP协议)
MCP Server A (文件操作)
MCP Server B (数据库查询)  
MCP Server C (API调用)

关键设计:LLM不需要知道工具的具体实现细节,只需要通过标准协议说“我要读文件”,MCP Client会自动找到对应的Server执行。

协议设计的硬核细节

MCP基于JSON-RPC 2.0,所有通信都是结构化的JSON消息。它定义了三种核心能力:

1. Tools(工具):可执行的函数

{
  "name": "read_file",
  "description": "读取指定路径的文件内容",
  "inputSchema": {
    "type": "object",
    "properties": {
      "path": {"type": "string", "description": "文件路径"}
    },
    "required": ["path"]
  }
}

2. Resources(资源):可读取的数据源

{
  "uri": "file:///home/user/document.txt",
  "name": "document.txt",
  "mimeType": "text/plain"
}

3. Prompts(提示模板):预定义的对话模板

为什么这样设计?因为不同工具需要不同交互方式。有些是“执行动作”(比如创建文件),有些是“获取数据”(比如读文件),有些是“提供上下文”(比如系统信息)。分开定义让协议更清晰。

步骤:用Python SDK接入MCP服务

现在我们来动手实现。假设你有一个简单的文件操作工具,想通过MCP提供给LLM使用。

第一步:安装MCP Python SDK

pip install mcp

第二步:创建MCP Server

# file_server.py
import os
from mcp.server import Server
from mcp.types import Tool, TextContent
import mcp.server.stdio

# 创建Server实例
server = Server("file-server")

# 定义工具
@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="read_file",
            description="读取本地文件内容",
            inputSchema={
                "type": "object",
                "properties": {
                    "path": {
                        "type": "string",
                        "description": "要读取的文件路径"
                    }
                },
                "required": ["path"]
            }
        ),
        Tool(
            name="list_files", 
            description="列出目录下的文件",
            inputSchema={
                "type": "object",
                "properties": {
                    "dir_path": {
                        "type": "string",
                        "description": "目录路径",
                        "default": "."
                    }
                }
            }
        )
    ]

# 实现工具逻辑
@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "read_file":
        path = arguments["path"]
        try:
            with open(path, 'r', encoding='utf-8') as f:
                content = f.read()
            return [TextContent(type="text", text=content)]
        except Exception as e:
            return [TextContent(type="text", text=f"错误: {str(e)}")]
    
    elif name == "list_files":
        dir_path = arguments.get("dir_path", ".")
        try:
            files = os.listdir(dir_path)
            return [TextContent(type="text", text="\n".join(files))]
        except Exception as e:
            return [TextContent(type="text", text=f"错误: {str(e)}")]

# 启动Server
if __name__ == "__main__":
    async def run():
        async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
            await server.run(
                read_stream,
                write_stream,
                server.create_initialization_options()
            )
    
    import asyncio
    asyncio.run(run())

为什么这样写?

  • @server.list_tools() 告诉Client“我有哪些工具可用”
  • @server.call_tool() 处理具体的工具调用请求
  • 使用标准输入输出通信,这是MCP推荐的简单方式
  • 每个工具都有清晰的inputSchema,LLM知道需要提供什么参数

第三步:在Host中使用

以Claude Desktop为例,编辑配置文件:

{
  "mcpServers": {
    "file-server": {

![配图](https://yitb.com/usr/uploads/covers/cover_guides_20260530_201249.jpg)

      "command": "python",
      "args": ["/path/to/file_server.py"]
    }
  }
}

重启Claude Desktop后,你就可以直接说“帮我读取/home/user/notes.txt”,LLM会自动调用你的read_file工具。

验证:看看实际效果

  1. 创建测试文件:

    echo "Hello MCP!" > test.txt
  2. 在Claude中测试:

    用户:读取test.txt文件的内容
    Claude:[调用read_file工具] → 文件内容是:Hello MCP!
  3. 测试错误处理:

    用户:读取不存在的文件
    Claude:[调用read_file工具] → 错误: [Errno 2] No such file or directory: '...'

为什么这很酷? 你不需要写任何HTTP服务器代码,不需要处理认证,不需要担心不同LLM的接口差异。MCP帮你处理了所有底层通信。

实战:将现有工具改造成MCP服务

假设你有一个现成的OpenClaw工具(假设是数据库查询工具),想让它支持MCP。

原始代码(非MCP)

# legacy_db_tool.py
import sqlite3

class DatabaseTool:
    def __init__(self, db_path):
        self.db_path = db_path
    
    def query(self, sql):
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute(sql)
        results = cursor.fetchall()
        conn.close()
        return results
    
    def get_tables(self):
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
        tables = [row[0] for row in cursor.fetchall()]
        conn.close()
        return tables

MCP改造版本

# db_mcp_server.py
from mcp.server import Server
from mcp.types import Tool, TextContent
import mcp.server.stdio
import json
from legacy_db_tool import DatabaseTool

server = Server("database-server")
db_tool = DatabaseTool("app.db")

@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="execute_sql",
            description="执行SQL查询语句",
            inputSchema={
                "type": "object", 
                "properties": {
                    "sql": {
                        "type": "string",
                        "description": "要执行的SQL语句"
                    }
                },
                "required": ["sql"]
            }
        ),
        Tool(
            name="list_tables",
            description="列出数据库中的所有表",
            inputSchema={
                "type": "object",
                "properties": {}
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "execute_sql":
        sql = arguments["sql"]
        try:
            results = db_tool.query(sql)
            return [TextContent(type="text", text=json.dumps(results, ensure_ascii=False))]
        except Exception as e:
            return [TextContent(type="text", text=f"SQL执行错误: {str(e)}")]
    
    elif name == "list_tables":
        try:
            tables = db_tool.get_tables()
            return [TextContent(type="text", text=json.dumps(tables))]
        except Exception as e:
            return [TextContent(type="text", text=f"错误: {str(e)}")]

if __name__ == "__main__":
    import asyncio
    async def run():
        async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
            await server.run(
                read_stream,
                write_stream,
                server.create_initialization_options()
            )
    asyncio.run(run())

改造要点:

  1. 保留原有业务逻辑,只添加MCP适配层
  2. 定义清晰的工具描述和输入模式
  3. 统一错误处理格式
  4. 使用JSON序列化返回结果

现在你的数据库工具可以同时被多个AI应用使用:Claude Desktop、Cursor、或者任何支持MCP的Host。

常见问题

Q:MCP和Function Calling有什么区别?
A:Function Calling是各家LLM厂商自己定义的接口,格式都不一样。MCP是跨厂商的标准协议,写一次到处用。

Q:MCP Server必须用Python写吗?
A:不是!官方支持TypeScript、Python、Java等多种语言。只要遵循协议规范,用什么语言都行。

Q:MCP安全吗?
A:MCP设计时考虑了安全问题。Server运行在隔离环境中,Host可以控制权限。但要注意,不要运行来历不明的Server。

Q:性能怎么样?
A:对于大多数工具调用场景足够。如果是高频调用,可以考虑使用HTTP传输代替标准输入输出。

现成插件生态:别从零开始

MCP最实用的地方在于现成的插件生态。你不需要自己写文件操作、Git操作、数据库查询等常见工具,直接用社区提供的Server就行:

# 安装官方参考实现
npm install @modelcontextprotocol/server-filesystem
npm install @modelcontextprotocol/server-git
npm install @modelcontextprotocol/server-sqlite

这些Server经过充分测试,比自己写的更稳定。你的AI应用瞬间就能获得几十种工具能力。

下一步学习建议

  1. 动手实验:先用现成的Server感受一下,比如filesystem和sqlite
  2. 阅读规范:去modelcontextprotocol.io读官方文档
  3. 改造工具:把你手头的一个小工具改造成MCP Server
  4. 参与生态:看看GitHub上有哪些有趣的MCP Server项目

MCP还在快速发展中,现在正是参与的好时机。想象一下,未来所有AI工具都通过MCP互联,你的AI助手可以无缝调用任何服务——这不再是科幻场景,而是正在发生的技术演进。

相关资源:

记住:好的标准需要社区共同建设。当你开发了一个有用的工具,考虑用MCP包装一下,让更多AI应用能受益。这才是开源生态的魅力所在。

返回首页