如何将 MCP Server (FastMCP) 配置为公网访问(监听 0.0.0.0)
- 引言
- 常见错误尝试
- 根本原因:从源码解析
- 正确的解决方案
- 总结
引言
在使用 Model Context Protocol(MCP) 框架开发自定义工具服务器时,我们经常使用 FastMCP
来快速构建服务。当选择 streamable-http
作为传输模式时,一个常见的需求是将服务暴露在 0.0.0.0
上,以便可以从局域网或公网进行访问,而不仅仅是本地的 127.0.0.1
。然而,很多开发者在尝试配置 host
时会遇到 TypeError
的问题。本文将详细解析这个问题的根本原因,并提供正确的解决方案。
常见错误尝试
当你启动一个基础的 FastMCP
服务器时,它默认监听在 http://127.0.0.1:8000
。
# oci-compute-mcp-server.py
from mcp.server.fastmcp import FastMCP# 初始化 FastMCP 服务器
mcp = FastMCP("oci-compute")# ... 其他工具定义 ...if __name__ == "__main__":mcp.run(transport="streamable-http")
输出:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
为了让它监听在 0.0.0.0
,很多开发者会自然地尝试在 run()
方法中添加 host
参数:
# 错误尝试 1
mcp.run(transport="streamable-http", host="0.0.0.0")
这会导致一个直接的错误:
TypeError: FastMCP.run() got an unexpected keyword argument 'host'
另一个常见的尝试是查阅文档或猜测 API,可能会使用类似 transport_options
的参数:
# 错误尝试 2
mcp.run(transport="streamable-http", transport_options={"host": "0.0.0.0", "port": 8000})
不幸的是,这同样会失败:
TypeError: FastMCP.run() got an unexpected keyword argument 'transport_options'
那么,正确的配置方式究竟是什么呢?
根本原因:从源码解析
遇到这种 “unexpected keyword argument” 的问题时,最好的方法是直接查看 FastMCP
类的源代码。
通过分析 mcp/server/fastmcp/server.py
文件,我们可以发现两个关键点:
-
run()
方法的签名:def run(self,transport: Literal["stdio", "sse", "streamable-http"] = "stdio",mount_path: str | None = None, ) -> None:# ...
从签名中可以明确看到,
run()
方法只接受transport
和mount_path
两个参数。这解释了为什么我们传递host
或transport_options
会报错。 -
__init__()
构造函数的签名:class FastMCP(Generic[LifespanResultT]):def __init__(self,name: str | None = None,# ... 其他参数 ...host: str = "127.0.0.1",port: int = 8000,# ... 其他参数 ...):self.settings = Settings(# ...host=host,port=port,# ...)# ...
真正的玄机在这里!
host
和port
参数实际上是在FastMCP
类的 构造函数 中定义的。这些配置项在服务器实例化时被读取,并存储在内部的settings
对象中,run()
方法在启动 uvicorn 服务器时会使用这些预先配置好的设置。
正确的解决方案
基于源码的分析,正确的做法是在创建 FastMCP
实例时就传入 host
和 port
。
下面是正确的代码示例:
# oci-compute-mcp-server.py
from mcp.server.fastmcp import FastMCP# 正确做法:在实例化时传入 host 和 port
mcp = FastMCP("oci-compute", host="0.0.0.0", port=8000)# ... 其他工具定义 ...if __name__ == "__main__":# run() 方法保持不变mcp.run(transport="streamable-http")
现在,当你再次运行服务器时,将会看到期望的输出:
INFO: Started server process [xxxxx]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
服务器现在已经成功监听在所有网络接口上,可以从外部设备进行访问了。
总结
将 FastMCP
服务器配置为公网访问的关键在于:网络配置(如 host
和 port
)必须在 FastMCP
类的构造函数中指定,而不是在 run()
方法中。
希望这篇文章能帮助你避免在配置 MCP Server 时走弯路。当遇到类似的 API 使用问题时,深入阅读源代码往往是找到答案最直接、最有效的方法。