Python技术迷

Python 神器 FastMCP:构建你的第一个 MCP 服务器

装个大而全的 AI 框架,最后只想暴露两个工具。这个事,我现在基本不干了。

MCP 这波起来之后,很多人第一反应是“我要不要自己实现协议”。真到手写 JSON-RPC、握手、工具描述、输入 schema,你很快就没耐心了。FastMCP 讨巧的地方就在这儿:它把这些脏活收掉,你只管把 Python 函数写明白,工具就能挂出去。官方文档里也是这个路子,FastMCP 实例起来之后,直接用装饰器暴露 tool,类型标注和 docstring 会参与生成定义;运行方式也很直接,核心就是 mcp.run()。另外,FastMCP 2.0 跟早期 MCP Python SDK 的 FastMCP 1.0 基本兼容,很多老代码甚至只改一行 import 就能迁过去。

先别上复杂例子,第一个 MCP 服务我建议就做“文件摘要 + 目录查看”。这种东西最适合拿来验证链路:参数解析对不对,客户端能不能发现工具,返回结果是不是你想要的。

from pathlib import Path
from fastmcp import FastMCP

mcp = FastMCP("dev-helper")

@mcp.tool()
deflist_logs(base_dir: str = "./logs") -> list[str]:
"""列出日志目录下的文件名"""
    root = Path(base_dir)
ifnot root.exists():
return []
return [p.name for p in root.iterdir() if p.is_file()]

@mcp.tool()
deftail_text(file_path: str, max_lines: int = 20) -> str:
"""读取文本文件最后几行,适合排查日志"""
    path = Path(file_path)
ifnot path.exists():
returnf"file not found: {file_path}"

    lines = path.read_text(encoding="utf-8", errors="ignore").splitlines()
    chunk = lines[-max_lines:]
return"\n".join(chunk)

if __name__ == "__main__":
    mcp.run()

这段代码没什么花活,但已经够用了。一个服务名,两个工具。你把它跑起来,客户端连上之后,就能直接调用 list_logs 和 tail_text。这里我比较在意两件事。

第一,tool 不要一上来就写成“万能工具”。比如很多人喜欢搞一个 run_anything(cmd: str),看着很强,其实后面最先出事的就是它。MCP 暴露出去的能力,越清晰越好,最好一眼看出边界。

第二,返回值别太随意。能返回字符串就别混着字典、列表、异常堆栈一锅端。你自己调两次可能无所谓,给模型用时,结构一乱,后面效果就开始飘。

再往前走一步,你大概率会想把业务逻辑接进来。比如查订单状态,很多人会直接在 tool 里糊数据库查询。我一般会先收一层,别让工具函数直接碰太多底层细节。

from fastmcp import FastMCP

mcp = FastMCP("order-service")

_FAKE_DB = {
"A1001": {"status": "PAID", "amount": 99.8},
"A1002": {"status": "CLOSED", "amount": 12.5},
}

def_query_order(order_no: str) -> dict:
    data = _FAKE_DB.get(order_no)
ifnot data:
return {"found": False, "message": "order not found"}
return {"found": True, **data}

@mcp.tool()
defget_order_status(order_no: str) -> dict:
"""根据订单号查询订单状态"""
return _query_order(order_no)

if __name__ == "__main__":
    mcp.run()

为什么多绕一层?因为你后面八成要改。今天是查内存字典,明天可能查 Redis,后天可能又得补数据库兜底。tool 只负责对外暴露能力,真正的脏逻辑单独放,后面才好收拾。

还有个地方新手特别容易忽略:docstring 不是写给自己看的,它会直接影响工具被客户端理解的效果。官方文档提到 FastMCP 会利用 Python 类型标注和函数说明来生成工具定义,所以别偷懒写成“测试接口”“查询数据”这种废话。说明越具体,模型越不容易乱调。

安装也不复杂。现在主流写法是直接用独立包里的导入方式:

# pip install fastmcp
from fastmcp import FastMCP

如果你看到老文章里还是:

from mcp.server.fastmcp import FastMCP

那多半是旧版 SDK 时代的写法,不是不能看,但照着新项目抄就有点别扭了。官方迁移说明里已经把这个变化写得很明白

所以第一个 FastMCP 服务器,别上来就卷“智能代理”“自动编排”。先把一个小工具挂出去,连通,调用,返回稳定,再考虑加资源、加鉴权、加真实业务。很多东西不是做不出来,是第一步走太大,最后连自己都不知道错在哪。