一、HTTP 部署
通过 HTTP 部署您的 FastMCP 服务器以实现远程访问
新版本:2.13.0 功能
提示:
STDIO 传输非常适合本地开发和桌面应用程序。但要充分发挥 MCP 的全部潜力------集中式服务、多客户端访问和网络可用性------您需要远程 HTTP 部署。
本指南将引导您将 FastMCP 服务器部署为可通过 URL 访问的远程 MCP 服务。部署完成后,您的 MCP 服务器将可通过网络访问,允许多个客户端同时连接,并实现与基于云的 LLM 应用程序的集成。本指南专门关注远程 MCP 部署,而非本地 STDIO 服务器。
二、选择部署方式
FastMCP 提供两种将服务器部署为 HTTP 服务的方法。了解各自的优缺点有助于您根据需求选择合适的方式。
直接 HTTP 服务器方法更简单,适合快速入门。您修改服务器的 run() 方法以使用 HTTP 传输,FastMCP 会处理所有 Web 服务器配置。这种方法适用于独立部署,即您希望 MCP 服务器成为端口上运行的唯一服务。
ASGI 应用程序方法提供更多控制和灵活性。您不是直接运行服务器,而是创建一个可由 Uvicorn 服务的 ASGI 应用程序。当您需要高级服务器功能(如多工作进程、自定义中间件)或与现有 Web 应用程序集成时,这种方法更合适。
2.1 直接 HTTP 服务器
让 MCP 服务器上线的最简单方法是使用内置的 run() 方法和 HTTP 传输。这种方法为您处理所有服务器配置,当您需要一个独立 MCP 服务器而无需额外复杂性时,这是理想选择。
示例代码(server.py):
python
from fastmcp import FastMCP
mcp = FastMCP("我的服务器")
@mcp.tool
def process_data(input: str) -> str:
"""在服务器上处理数据"""
return f"已处理:{input}"
if name == "main":
mcp.run(transport="http", host="0.0.0.0", port=8000)
使用简单的 Python 命令运行服务器:
python
python server.py
您的服务器现在可通过 http://localhost:8000/mcp 访问(或使用服务器的实际 IP 地址进行远程访问)。
这种方法非常适合希望以最少的配置快速上线的场景。它适用于内部工具、开发环境或不需要高级服务器功能的简单部署。内置服务器处理所有 HTTP 细节,让您可以专注于 MCP 实现。
2.2 ASGI 应用程序
对于生产部署,您通常需要更多控制服务器的运行方式。FastMCP 可以创建标准的 ASGI 应用程序,可与任何 ASGI 服务器(如 Uvicorn、Gunicorn 或 Hypercorn)配合使用。当您需要配置高级服务器选项、运行多个工作进程或与现有基础设施集成时,这种方法特别有用。
示例代码(app.py):
python
from fastmcp import FastMCP
mcp = FastMCP("我的服务器")
@mcp.tool
def process_data(input: str) -> str:
"""在服务器上处理数据"""
return f"已处理:{input}"
# 创建 ASGI 应用程序
app = mcp.http_app()
使用任何 ASGI 服务器运行 - 以下是使用 Uvicorn 的示例:
python
uvicorn app:app --host 0.0.0.0 --port 8000
您的服务器可通过相同的 URL 访问:http://localhost:8000/mcp(或使用服务器的实际 IP 地址进行远程访问)。
ASGI 方法在生产环境中表现出色,因为您需要可靠性和性能。您可以运行多个工作进程来处理并发请求,添加自定义中间件进行日志记录或监控,与现有部署管道集成,或将 MCP 服务器作为大型应用程序的一部分挂载。
三、配置服务器
3.1 自定义路径
默认情况下,您的 MCP 服务器可在域名的 /mcp/ 路径下访问。您可以自定义此路径以适应您的 URL 结构或避免与现有端点冲突。这在将 MCP 集成到现有应用程序中或遵循特定 API 约定时特别有用。
python
# 选项 1:使用 mcp.run()
mcp.run(transport="http", host="0.0.0.0", port=8000, path="/api/mcp/")
# 选项 2:使用 ASGI 应用程序
app = mcp.http_app(path="/api/mcp/")
现在您的服务器可通过 http://localhost:8000/api/mcp/ 访问。
3.2 身份验证
警告:强烈建议为远程 MCP 服务器配置身份验证。某些 LLM 客户端要求远程服务器进行身份验证,没有身份验证将拒绝连接。
FastMCP 支持多种身份验证方法来保护您的远程服务器。有关完整配置选项(包括 Bearer 令牌、JWT 和 OAuth),请参阅身份验证概述。
如果您要在路径前缀下挂载经过身份验证的服务器,请参阅下面的挂载经过身份验证的服务器了解重要的路由注意事项。
3.3 健康检查
健康检查端点对于监控已部署的服务器并确保其正确响应至关重要。FastMCP 允许您在 MCP 端点旁边添加自定义路由,使得在两种部署方法中都能轻松实现健康检查。
python
from starlette.responses import JSONResponse
@mcp.custom_route("/health", methods=["GET"])
async def health_check(request):
return JSONResponse({"status": "healthy", "service": "mcp-server"})
此健康端点将在 http://localhost:8000/health 可用,可由负载均衡器、监控系统或部署平台用于验证服务器是否正在运行。
3.4 自定义中间件
新版本:2.3.2 功能
向 FastMCP ASGI 应用程序添加自定义 Starlette 中间件:
python
from fastmcp import FastMCP
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
# 创建 FastMCP 服务器
mcp = FastMCP("我的服务器")
# 定义中间件
middleware = [
Middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
]
# 使用中间件创建 ASGI 应用程序
http_app = mcp.http_app(middleware=middleware)
3.5 基于浏览器的客户端的 CORS 配置
提示:大多数 MCP 客户端(包括通过浏览器访问的客户端,如 ChatGPT 或 Claude)不需要 CORS 配置。仅当您使用直接从浏览器连接的 MCP 客户端(如调试工具或检查器)时,才需要启用 CORS。
当在 Web 浏览器中运行的 JavaScript 直接连接到您的 MCP 服务器时,需要 CORS(跨源资源共享)。这与通过浏览器使用 LLM 不同------在那种情况下,浏览器连接到 LLM 服务,而 LLM 服务连接到您的 MCP 服务器(不需要 CORS)。
需要 CORS 的基于浏览器的 MCP 客户端包括:
-
MCP 检查器 - 基于浏览器的调试工具,用于测试 MCP 服务器
-
自定义基于浏览器的 MCP 客户端 - 如果您正在构建直接连接到 MCP 服务器的 Web 应用程序
对于这些场景,添加具有 MCP 协议所需特定标头的 CORS 中间件:
python
from fastmcp import FastMCP
from starlette.middleware import Middleware
from starlette.middleware.cors import CORSMiddleware
mcp = FastMCP("我的服务器")
# 为基于浏览器的客户端配置 CORS
middleware = [
Middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有来源;出于安全考虑请使用特定来源
allow_methods=["GET", "POST", "DELETE", "OPTIONS"],
allow_headers=[
"mcp-protocol-version",
"mcp-session-id",
"Authorization",
"Content-Type",
],
expose_headers=["mcp-session-id"],
)
]
app = mcp.http_app(middleware=middleware)
关键配置细节:
-
allow_origins:对于生产部署,请指定确切的来源(例如 ["http://localhost:3000"])而不是 ["*"]
-
allow_headers:必须包括 mcp-protocol-version、mcp-session-id 和 Authorization(对于经过身份验证的服务器)
-
expose_headers:必须包括 mcp-session-id,以便 JavaScript 可以从响应中读取会话 ID 并在后续请求中发送它
如果没有 expose_headers=["mcp-session-id"],浏览器将收到会话 ID,但 JavaScript 无法访问它,导致会话管理失败。
警告:生产环境安全:在生产中切勿使用 allow_origins=["*"]。指定基于浏览器的客户端的确切来源。使用通配符会使您的服务器面临来自任何网站的未经授权访问的风险。
四、与 Web 框架集成
如果您已经有正在运行的 Web 应用程序,可以通过将 FastMCP 服务器挂载为子应用程序来添加 MCP 功能。这允许您在与现有 API 端点相同的域和基础设施下公开 MCP 工具。MCP 服务器成为应用程序中的另一个路由,使其易于管理和部署。
4.1 在 Starlette 中挂载
在 Starlette 应用程序中挂载 FastMCP 服务器:
python
from fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
# 创建 FastMCP 服务器
mcp = FastMCP("我的服务器")
@mcp.tool
def analyze(data: str) -> dict:
return {"result": f"已分析:{data}"}
# 创建 ASGI 应用程序
mcp_app = mcp.http_app(path='/mcp')
# 创建 Starlette 应用程序并挂载 MCP 服务器
app = Starlette(
routes=[
Mount("/mcp-server", app=mcp_app),
# 根据需要添加其他路由
],
lifespan=mcp_app.lifespan,
)
MCP 端点将在生成的 Starlette 应用程序的 /mcp-server/mcp/ 路径下可用。
警告:对于可流式 HTTP 传输,您必须将生命周期上下文从 FastMCP 应用程序传递到生成的 Starlette 应用程序,因为嵌套的生命周期不被识别。否则,FastMCP 服务器的会话管理器将无法正确初始化。
嵌套挂载
您可以通过嵌套挂载创建复杂的路由结构:
python
from fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
# 创建 FastMCP 服务器
mcp = FastMCP("我的服务器")
# 创建 ASGI 应用程序
mcp_app = mcp.http_app(path='/mcp')
# 创建嵌套应用程序结构
inner_app = Starlette(routes=[Mount("/inner", app=mcp_app)])
app = Starlette(
routes=[Mount("/outer", app=inner_app)],
lifespan=mcp_app.lifespan,
)
在此设置中,MCP 服务器可在 /outer/inner/mcp/ 路径下访问。
4.2 FastAPI 集成
有关 FastAPI 特定的集成模式,包括将 MCP 服务器挂载到 FastAPI 应用程序中以及从 FastAPI 应用程序生成 MCP 服务器,请参阅 FastAPI 集成指南。
以下是一个快速示例,展示如何向现有 FastAPI 应用程序添加 MCP:
python
from fastapi import FastAPI
from fastmcp import FastMCP
# 您现有的 API
api = FastAPI()
@api.get("/api/status")
def status():
return {"status": "ok"}
# 创建 MCP 服务器
mcp = FastMCP("API 工具")
@mcp.tool
def query_database(query: str) -> dict:
"""运行数据库查询"""
return {"result": "数据"}
# 在 /mcp 挂载 MCP
api.mount("/mcp", mcp.http_app())
# 运行:uvicorn app:api --host 0.0.0.0 --port 8000
您现有的 API 保留在 http://localhost:8000/api,而 MCP 在 http://localhost:8000/mcp 可用。
4.3 挂载经过身份验证的服务器
新版本:2.13.0 功能
提示:本节仅适用于当您使用 Mount() 在另一个应用程序中的路径前缀下(如 /api)挂载 OAuth 保护的 FastMCP 服务器时。
如果您在没有任何 Mount() 前缀的根级别部署 FastMCP 服务器,则已知路由会自动包含在 mcp.http_app() 中,您无需执行任何特殊操作。
OAuth 规范(RFC 8414 和 RFC 9728)要求发现元数据可在域根级别下的已知路径访问。当您在路径前缀(如 /api)下挂载 OAuth 保护的 FastMCP 服务器时,这会产生路由挑战:您的操作 OAuth 端点移动到前缀下,但发现端点必须保留在根级别。
警告:需要避免的常见错误:
-
忘记在根级别挂载 .well-known 路由 - 当您的服务器在路径前缀下挂载时,FastMCP 无法自动执行此操作。您必须显式地在根级别挂载已知路由。
-
在 base_url 和 mcp_path 中都包含挂载前缀 - 挂载前缀(如 /api)应仅在 base_url 中,而不在 mcp_path 中。否则您将得到双倍路径。
正确示例:
python
base_url = "http://localhost:8000/api"
mcp_path = "/mcp"
# 结果:/api/mcp
错误示例:
python
base_url = "http://localhost:8000/api"
mcp_path = "/api/mcp"
# 结果:/api/api/mcp(双前缀!)
- 挂载时未设置 issuer_url - 如果没有将 issuer_url 设置为根级别,OAuth 发现将首先尝试路径范围的发现(这将返回 404),从而产生不必要的错误日志。
请按照下面的配置说明正确设置挂载。
警告:CORS 中间件冲突:
如果您将 FastMCP 集成到具有自己的 CORS 中间件的现有应用程序中,请注意分层 CORS 中间件可能导致冲突(例如在 .well-known 路由或 OPTIONS 请求上出现 404 错误)。
FastMCP 和 MCP SDK 已经为 OAuth 路由处理了 CORS。如果您需要在自己的应用程序路由上使用 CORS,请考虑使用子应用程序模式:将 FastMCP 和您的路由作为单独的应用程序挂载,每个应用程序都有自己的中间件,而不是添加应用程序范围的 CORS 中间件。
4.4 路由类型
受 OAuth 保护的 MCP 服务器公开两类路由:
操作路由处理 OAuth 流和 MCP 协议:
-
/authorize - OAuth 授权端点
-
/token - 令牌交换端点
-
/auth/callback - OAuth 回调处理程序
-
/mcp - MCP 协议端点
发现路由为 OAuth 客户端提供元数据:
-
/.well-known/oauth-authorization-server - 授权服务器元数据
-
/.well-known/oauth-protected-resource/* - 受保护资源元数据
当您在前缀下挂载 MCP 应用程序时,操作路由随之移动,但发现路由必须保留在根级别以符合 RFC 规范。
4.5 配置参数
三个参数控制路由的位置以及它们如何组合:
base_url 告诉客户端在哪里找到操作端点。这包括任何 Starlette Mount() 路径前缀(例如 /api):
python
base_url="http://localhost:8000/api" # 包括挂载前缀
mcp_path 是内部的 FastMCP 端点路径,它附加到 base_url:
python
mcp_path="/mcp" # 内部 MCP 路径,不是挂载前缀
issuer_url 告诉客户端在哪里找到发现元数据。这应指向挂载已知路由的服务器的根级别:
python
issuer_url="http://localhost:8000" # 根级别,无前缀
关键不变量:base_url + mcp_path = 实际外部可访问的 MCP URL
示例:
-
base_url:http://localhost:8000/api(挂载前缀 /api)
-
mcp_path:/mcp(内部路径)
-
结果:http://localhost:8000/api/mcp(最终 MCP 端点)
请注意,挂载前缀(来自 Mount("/api", ...) 的 /api)放在 base_url 中,而 mcp_path 只是内部 MCP 路由。不要在两个地方都包含挂载前缀,否则您将得到 /api/api/mcp。
4.6 挂载策略
当在路径前缀下挂载受 OAuth 保护的服务器时,预先声明您的 URL 以使关系清晰:
python
from fastmcp import FastMCP
from fastmcp.server.auth.providers.github import GitHubProvider
from starlette.applications import Starlette
from starlette.routing import Mount
# 定义路由结构
ROOT_URL = "http://localhost:8000"
MOUNT_PREFIX = "/api"
MCP_PATH = "/mcp"
使用 issuer_url 和 base_url 创建身份验证提供程序:
python
auth = GitHubProvider(
client_id="您的客户端 ID",
client_secret="您的客户端密钥",
issuer_url=ROOT_URL, # 发现元数据在根级别
base_url=f"{ROOT_URL}{MOUNT_PREFIX}", # 操作端点在前缀下
)
创建 MCP 应用程序,它在指定路径生成操作路由:
python
mcp = FastMCP("受保护的服务器", auth=auth)
mcp_app = mcp.http_app(path=MCP_PATH)
从身份验证提供程序检索发现路由。mcp_path 参数应与创建 MCP 应用程序时使用的路径匹配:
python
well_known_routes = auth.get_well_known_routes(mcp_path=MCP_PATH)
最后,在 Starlette 应用程序中挂载所有内容,发现路由在根级别,MCP 应用程序在前缀下:
python
app = Starlette(
routes=[
*well_known_routes, # 发现路由在根级别
Mount(MOUNT_PREFIX, app=mcp_app), # 操作路由在前缀下
],
lifespan=mcp_app.lifespan,
)
此配置产生以下 URL 结构:
-
OAuth 授权:http://localhost:8000/api/authorize
-
授权服务器元数据:http://localhost:8000/.well-known/oauth-authorization-server
-
受保护资源元数据:http://localhost:8000/.well-known/oauth-protected-resource/api/mcp
4.7 完整示例
以下是一个完整的工作示例,展示所有部分如何组合在一起:
python
from fastmcp import FastMCP
from fastmcp.server.auth.providers.github import GitHubProvider
from starlette.applications import Starlette
from starlette.routing import Mount
import uvicorn
# 定义路由结构
ROOT_URL = "http://localhost:8000"
MOUNT_PREFIX = "/api"
MCP_PATH = "/mcp"
# 创建 OAuth 提供程序
auth = GitHubProvider(
client_id="您的客户端 ID",
client_secret="您的客户端密钥",
issuer_url=ROOT_URL,
base_url=f"{ROOT_URL}{MOUNT_PREFIX}",
)
# 创建 MCP 服务器
mcp = FastMCP("受保护的服务器", auth=auth)
@mcp.tool
def analyze(data: str) -> dict:
return {"result": f"已分析:{data}"}
# 创建 MCP 应用程序
mcp_app = mcp.http_app(path=MCP_PATH)
# 获取根级别的发现路由
well_known_routes = auth.get_well_known_routes(mcp_path=MCP_PATH)
# 组装应用程序
app = Starlette(
routes=[
*well_known_routes,
Mount(MOUNT_PREFIX, app=mcp_app),
],
lifespan=mcp_app.lifespan,
)
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
有关 OAuth 身份验证的更多详细信息,请参阅身份验证指南。
五、生产部署
5.1 使用 Uvicorn 运行
当部署到生产环境时,您需要优化服务器以获得性能和可靠性。Uvicorn 提供了几个选项来改进服务器的能力:
python
# 使用基本配置运行
uvicorn app:app --host 0.0.0.0 --port 8000
# 为生产环境运行多个工作进程
uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4
5.2 环境变量
生产部署绝不应硬编码敏感信息,如 API 密钥或身份验证令牌。相反,应使用环境变量在运行时配置服务器。这可以保持代码安全,并使相同的代码能够轻松部署到具有不同配置的不同环境。
以下是使用承载令牌身份验证的示例(尽管生产环境推荐使用 OAuth):
python
import os
from fastmcp import FastMCP
from fastmcp.server.auth import BearerTokenAuth
# 从环境变量读取配置
auth_token = os.environ.get("MCP_AUTH_TOKEN")
if auth_token:
auth = BearerTokenAuth(token=auth_token)
mcp = FastMCP("生产服务器", auth=auth)
else:
mcp = FastMCP("生产服务器")
app = mcp.http_app()
将秘密安全地存储在环境变量中进行部署:
python
MCP_AUTH_TOKEN=secret uvicorn app:app --host 0.0.0.0 --port 8000
5.3 OAuth 令牌安全性
新版本:2.13.0 功能
如果您使用 OAuth 代理,FastMCP 会向客户端颁发自己的 JWT 令牌,而不是转发上游提供程序的令牌。这保持了适当的 OAuth 2.0 令牌边界。
默认行为(仅开发):
默认情况下,FastMCP 自动管理加密密钥:
-
Mac/Windows:密钥生成并存储在系统密钥环中,在服务器重启后仍然存在。仅适用于开发和本地测试。
-
Linux:密钥是临时的(启动时随机盐),因此令牌在重启时失效。
这种自动方法对于开发很方便,但不适用于生产部署。
对于生产环境:
生产需要显式的密钥管理,以确保令牌在重启后仍然存在并且可以在多个服务器实例之间共享。这需要以下两件事协同工作:
-
显式 JWT 签名密钥用于签署颁发给客户端的令牌
-
持久化网络可访问存储用于上游令牌(包装在 FernetEncryptionWrapper 中以加密静态敏感数据)
配置:
向您的身份验证提供程序添加两个参数:
python
from key_value.aio.stores.redis import RedisStore
from key_value.aio.wrappers.encryption import FernetEncryptionWrapper
from cryptography.fernet import Fernet
auth = GitHubProvider(
client_id=os.environ["GITHUB_CLIENT_ID"],
client_secret=os.environ["GITHUB_CLIENT_SECRET"],
jwt_signing_key=os.environ["JWT_SIGNING_KEY"],
client_storage=FernetEncryptionWrapper(
key_value=RedisStore(host="redis.example.com", port=6379),
fernet=Fernet(os.environ["STORAGE_ENCRYPTION_KEY"])
),
base_url="https://your-server.com" # 使用 HTTPS
)
这两个参数都是生产环境所必需的。没有显式签名密钥,密钥将使用从 client_secret 派生的密钥进行签名,这将在客户端密钥轮换时导致失效。没有持久化存储,令牌对服务器是本地的,并且不会跨主机信任。将您的存储后端包装在 FernetEncryptionWrapper 中以加密静态的敏感 OAuth 令牌 - 没有加密,令牌将以明文形式存储。
有关令牌架构和密钥管理的更多详细信息,请参阅 OAuth 代理密钥和存储管理。
5.4 测试您的部署
服务器部署完成后,您需要验证它是否可访问并正常运行。有关全面的测试策略,包括连接性测试、客户端测试和身份验证测试,请参阅测试您的服务器指南。
5.5 托管您的服务器
本指南向您展示了如何创建可通过 HTTP 访问的 MCP 服务器,但您仍然需要托管提供商使其在互联网上可用。您的 FastMCP 服务器可以在任何支持 Python Web 应用程序的地方运行:
-
云虚拟机(AWS EC2、Google Compute Engine、Azure VM)
-
容器平台(Cloud Run、Container Instances、ECS)
-
平台即服务(Railway、Render、Vercel)
-
边缘平台(Cloudflare Workers)
-
Kubernetes 集群(自管理或托管)
关键要求是 Python 3.10+ 支持和能够暴露 HTTP 端口。大多数提供商要求您根据他们的部署格式打包服务器(requirements.txt、Dockerfile 等)。有关托管、零配置部署,请参阅 FastMCP Cloud。