上周有个活特别无聊:每天要从公司内网系统拉销售数据,整理成表格,再发邮件给老板。

干了三天我就烦了。能不能让AI帮我干?

说实话,我之前一直觉得所谓的"AI操作电脑"就是个营销噱头。直到我花了两个晚上把MCP协议跑通,看着它自动打开浏览器、查询数据库、生成报表,那一刻的感觉——真香。

今天把整个过程记录下来,踩过的坑、写过的代码,都在这了。

MCP是个什么东西

先别着急看代码,咱先把概念理清楚。

MCP(Model Context Protocol)是Anthropic搞出来的一套协议,本质上就是给大模型装了一套"手和脚"。

以前你跟AI聊天,它能做的只有:接收文字输入、输出文字回复。让它查个数据库?不行。让它发个邮件?别想。

MCP做的事很简单:定义了一套标准,让AI能够调用外部工具。

打个比方:你家的智能音箱能放音乐但不能开灯,因为它和灯之间没有协议。一旦有了协议(比如Matter),音箱就能控制灯了。MCP对AI来说,就是这个"智能家居协议"。

它和Function Calling有什么区别

很多人会问:OpenAI的Function Calling不也能让模型调工具吗?MCP有啥不一样?

关键区别在两个字:标准化

Function Calling是你自己写代码定义工具、解析参数、处理返回。每换个模型都要重新适配。你写的工具只能在你的应用里用。

MCP不一样。它分了三层角色:

  • MCP Host:使用AI的应用(比如你的聊天界面)
  • MCP Client:和Server通信的客户端
  • MCP Server:暴露具体工具的服务端

这个分层意味着:你写一个MCP Server提供"查询销售数据"的能力,任何一个支持MCP的客户端都能直接用它。不用重复造轮子。

说人话:Function Calling是你自己搭乐高,MCP是乐高给了你标准接口,随便哪个套件都能插。

动手搭一个MCP Server

理论说完了,直接上代码。

我用的是Python的mcp包,搭一个最简单的Server大概30行代码:

from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
from mcp.server.stdio import stdio_server
import httpx

server = Server("sales-data-server")

@server.list_tools()
async def list_tools():
    return [
        {
            "name": "get_daily_sales",
            "description": "获取指定日期的销售数据",
            "inputSchema": {
                "type": "object",
                "properties": {
                    "date": {"type": "string", "description": "日期,格式YYYY-MM-DD"}
                },
                "required": ["date"]
            }
        }
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "get_daily_sales":
        date = arguments["date"]
        async with httpx.AsyncClient() as client:
            resp = await client.get(f"http://内网API/sales?date={date}")
            return {"content": [{"type": "text", "text": resp.text}]}

async def main():
    async with stdio_server() as (read, write):
        await server.run(read, write, InitializationCapabilities())

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

跑起来之后,Claude Desktop或者其他支持MCP的客户端就能直接调用get_daily_sales这个工具了。

我踩过的坑

坑1:stdio通信搞了半天

MCP Server默认走stdio(标准输入输出),不是HTTP。我一开始按HTTP的思路去调,各种404。

后来才搞明白:MCP Client启动Server进程,通过stdin发JSON-RPC请求,从stdout读响应。跟你用subprocess.Popen通信一个原理。

坑2:工具描述写得太烂

这是让我最崩溃的点。

我第一次写工具描述的时候偷懒,就写了句"查询销售数据"。结果AI完全不知道什么时候该调用这个工具,该传什么参数。

后来我把描述改成了:

"查询指定日期的销售数据,返回包含销售额、订单数、客单价的结构化JSON。
当用户询问'今天的销售情况'或'本周业绩'时应该调用此工具。"

准确率直接从40%飙到接近100%。

这里有个经验:工具描述是AI理解你的工具的唯一途径。写工具描述要像写prompt一样认真,说清楚"什么时候用"和"怎么用"。

坑3:权限控制没做好

MCP Server默认可以访问本地文件系统。如果你的Server能读文件,AI就能读任何文件——包括.env和私钥。

我的做法是:把工具的范围限制在特定目录,禁止访问上级目录。代码里加个路径检查:

import os

SAFE_DIR = "/data/sales"

def safe_path(path: str) -> str:
    full = os.path.abspath(os.path.join(SAFE_DIR, path))
    if not full.startswith(os.path.abspath(SAFE_DIR)):
        raise ValueError("路径越界了,你是不是想偷看我的私钥?")
    return full

MCP的生态到底怎么样了

我调研了一下,目前情况是这样的:

已经比较成熟的:

  • 文件系统操作(读、写、搜索文件)
  • 数据库查询(SQLite、PostgreSQL)
  • Web搜索和抓取
  • GitHub操作(读代码、创建Issue)

还在早期的:

  • 浏览器自动化(不如Puppeteer稳定)
  • 复杂的GUI操作
  • 实时协作场景

整体感觉:基础的工具调用已经很稳了,复杂场景还需要时间。

社区里最火的一个MCP Server叫filesystem,允许AI读文件、写文件、创建目录、搜索文件。我第一次用的时候,对着AI说"找一下项目里所有包含TODO的Python文件",它真的一个一个给我列出来了。那一刻真的很惊艳。

MCP vs A2A,别搞混了

很多人把MCP和A2A搞混,其实它们分工很明确:

  • MCP:AI和工具之间的协议(一个人用工具)
  • A2A:AI和AI之间的协议(多个人协作)

举例子:你要做一份行业分析报告。MCP让一个AI帮你查数据库、搜网页、生成图表。A2A让一个AI写分析文案、另一个AI做配图、第三个AI排成PPT。

现在MCP和A2A都在快速发展,看得出来这两套协议最终会融合——一个AI Agent既能调用工具,也能和其他Agent协作。

写在最后

折腾了两天MCP,我的感受是:这东西不是银弹,但确实是让AI落地的关键一步。

以前我们说"AI能做什么",答案基本是"能聊天、能写代码、能翻译"。有了MCP之后,答案变成了"能帮你干任何有API的事"。

如果你也在做AI应用,强烈建议花一个周末把MCP跑通。那种看着AI帮你干活的爽感,值得。

不过话说回来,MCP现在还比较新,文档不太全,踩坑是免不了的。建议从最简单的文件系统Server开始,跑通了再加复杂的功能。

下篇打算聊聊怎么把MCP和RAG结合起来,让AI既能查资料也能执行操作。感兴趣的可以关注一下。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐