小睿AI导航

ARTICLE DETAIL

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

本教程使用独立FastMCP项目,将内部产品编号查询函数封装成只读MCP工具,并给出服务端代码和客户端测试方法。你可以依次验证工具发现、参数传入、正常返回与错误处理,同时了解stdio与HTTP的配置

🧠 大模型与开发 浏览 1 2026-11-10 作者 小睿AI
📝

文章正文

样式 7 内容详情排版

阅读提示当前文章有1126字,阅读完大概需要3分钟。

先确认使用哪一个FastMCP

独立项目与 Python SDK都提供名为FastMCP的实现,但安装包、导入路径和API不能随意混用。本文统一采用独立FastMCP项目:安装fastmcp,从fastmcp导入FastMCP和Client;不使用MCP Python SDK的mcp.server.fastmcp导入路径。后续查阅资料也应对应独立项目的官方文档。

在支持该包的Python环境中创建虚拟环境,激活后安装依赖:

python -m venv .venv

python -m pip install fastmcp

第二条命令应在虚拟环境激活后执行。首次验证成功后,记录依赖版本,便于复现。

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

把产品查询函数封装成只读工具

新建server.py,逐行写入以下代码。代码行以段落分隔,函数体和条件块需保留缩进。示例使用内存数据,不连接真实业务系统,也不修改产品状态。

import logging

from fastmcp import FastMCP

from fastmcp.exceptions import ToolError

logging.basicConfig(level=logging.INFO)

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

mcp = FastMCP("ProductLookup")

PRODUCTS = {"P1001": {"name": "演示产品", "status": "active"}}

def lookup_product(product_id: str) -> dict[str, str]:

    """按产品编号只读查询,返回product_id、name和status。"""

    key = product_id.strip().upper()

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

    if not key:

        raise ToolError("产品编号不能为空")

    if key not in PRODUCTS:

        raise ToolError("未找到该产品编号")

    return {"product_id": key, **PRODUCTS[key]}

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

mcp.tool()(lookup_product)

if __name__ == "__main__":

    mcp.run(transport="stdio")

mcp.tool()(lookup_product)负责注册工具,与装饰器写法作用相同。参数类型让客户端获得输入约束,函数说明用于工具发现,返回类型描述结果结构。未知编号和空字符串会产生明确的工具错误;接入真实数据库后,还应捕获查询异常,记录服务端日志,避免把连接信息或完整堆栈返回给客户端。

stdio和HTTP怎样对应客户端配置

stdio:由客户端启动本地进程

支持stdio的客户端需要配置启动命令和参数。例如command填写虚拟环境中Python解释器的绝对路径,args填写server.py的绝对路径。客户端通过进程的标准输入、标准输出交换MCP消息,通常不需要提前手动启动服务。

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

不要用print输出调试日志。stdio的标准输出用于协议通信,普通日志应写入标准错误或文件。上面的logging默认使用标准错误;也要检查第三方库是否向标准输出打印内容。

HTTP:先启动服务,再连接地址

在server.py所在目录运行:

python -c "from server import mcp; mcp.run(transport='http', host='127.0.0.1', port=8000)"

客户端改为连接http://127.0.0.1:8000/mcp,不再配置启动该服务的本地命令。这里的HTTP使用Streamable HTTP传输;客户端是否支持这种传输及其配置字段,需要查对应客户端文档。127.0.0.1仅供本机连接。

检查工具发现、输入和返回结果

新建test_client.py,放在同一目录并使用同一环境运行。下面的Client是支持MCP的程序化客户端,适合先排除桌面客户端配置因素。

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

import asyncio

from fastmcp import Client

async def main():

    async with Client("server.py") as client:

        print(await client.list_tools())

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

        for args in [{"product_id": "P1001"}, {"product_id": "P9999"}, {}]:

            try:

                result = await client.call_tool("lookup_product", args)

                print(result.content)

            except Exception as exc:

FastMCP怎么用?从定义工具到本地连接与调用测试的入门指南

                print(type(exc).__name__, str(exc))

asyncio.run(main())

执行python test_client.py。工具列表应包含lookup_product;P1001应返回包含product_id、name、status的数据;P9999应报告未找到;空参数对象应触发必填参数校验。测试客户端不承载stdio服务端协议,因此这里可以print结果。宽泛捕获异常仅用于让测试继续执行。

验证HTTP时,先保持HTTP服务运行,再把Client("server.py")替换为Client("http://127.0.0.1:8000/mcp"),重复相同测试。

接入真实数据前补齐边界

若查询依赖外部API,密钥由服务端通过os.environ["PRODUCT_API_KEY"]等方式读取,不放入工具参数、源码或返回结果。stdio子进程是否继承环境变量取决于客户端配置,需要实际确认。

远程部署还需处理认证、TLS、网络访问范围和工具权限。只读查询同样可能暴露内部数据,应在服务端按调用者身份限制可查询范围。连接成功只说明通信链路可用,不能证明权限与数据安全已得到保障。