一、FastMCP开源项目
fastMCP(开源项目 modelcontextprotocol/fastmcp)是由 MCP 协议社区推动的一个官方参考实现(截至 2025–2026 年逐渐成熟)。但在安全方面,仍然有待加强。
用它来创建一个MCP SERVER非常简单。
from fastmcp import create_app, tool
@tool
def get_weather(city: str) -> str:
return f"Weather in {city} is sunny."
app = create_app(tools=[get_weather])
通过tool装饰器可以实现MCP的tool功能,通过create_app建立MCP服务。
二、安全属性
但对于实际生产使用,还要考虑各种安全性,这在开源的fastMCP中并未实现。
根据2026年1月份版本的情况,在认证、授权、输入验证、速率限制、审计日志、敏感信息保护等方面还有待加强。
| 安全特性 | 是否内置 | 说明 |
|---|---|---|
| 认证(AuthN) | ❌ 否 | 无 API Key、JWT、OAuth 支持 |
| 授权(AuthZ) | ❌ 否 | 所有工具对所有调用者开放 |
| 输入验证 | ⚠️ 部分 | 依赖 Python 类型注解,但无运行时 schema 校验(易被绕过) |
| 速率限制 | ❌ 否 | 无内置限流 |
| 审计日志 | ❌ 否 | 仅 debug 日志,无结构化审计 |
| 敏感信息保护 | ❌ 否 | 参数直接打印或返回 |
三、加强安全属性
接下来我们针对每一项,进行安全加强,使得更能满足生产需要。
1、认证
# ===== 认证 =====
VALID_API_KEYS = set(os.getenv("MCP_API_KEYS", "dev-key").split(","))
async def verify_api_key(x_api_key: str = Header(...)):
if x_api_key not in VALID_API_KEYS:
raise HTTPException(status_code=401, detail="Invalid X-API-Key")
return x_api_key
通过设定并验证输入KEY的合法性,实现访问认证。
2、授权
原生的tool不支持role功能,可以对其进行扩展。
from fastmcp import tool as base_tool
def secure_tool(roles: list = None):
def decorator(func):
func._mcp_roles = roles or ["user"]
return base_tool(func)
return decorator
# 使用
@secure_tool(roles=["admin"])
def delete_user(user_id: str): ...
然后在endpoint中添加对角色的判断
# 在 secured_endpoint 中
tool_name = request.json().get("name")
tool = server.tools[tool_name]
required_roles = getattr(tool.func, "_mcp_roles", ["user"])
caller_role = get_role_from_api_key(api_key)
if caller_role not in required_roles:
raise HTTPException(403, "Forbidden")
3、输入验证
为每个tool定义 Pydantic 模型,避免 LLM 注入任意参数。
from pydantic import BaseModel
class SayHelloArgs(BaseModel):
name: str
@register_tool("say_hello", roles=["user"])
def say_hello(args: SayHelloArgs): # ← 接收模型实例 return f"Hello, {args.name}!"
4、限流
这里引入slowapi实现限流限速。
from slowapi import Limiter
from slowapi.middleware import SlowAPIMiddleware
limiter = Limiter(key_func=get_remote_address)
应用到具体接口
from security.rate_limit import limiter
app.state.limiter = limiter
@app.post("/mcp/v1/tool_call")
@limiter.limit("10/minute") # 每 IP 10 次/分钟
async def call_tool(...): ...
5、审计日志及自动脱敏
引入行为审计,并根据敏感列表对敏感字段进行脱敏。
import logging
import json
import time
#敏感列表
SENSITIVE_PARAMS = {"password", "token", "secret", "key"}
#脱敏操作
def sanitize(args: dict) -> dict:
return {k: "[REDACTED]" if k in SENSITIVE_PARAMS else v for k, v in args.items()}
def log_call(api_key: str, ip: str, tool: str, args: dict, success: bool, msg: str, duration: float):
safe_args = sanitize(args)
record = {
"timestamp": time.time(),
"api_key_prefix": api_key[:6] + "...",
"client_ip": ip,
"tool": tool,
"arguments": safe_args,
"success": success,
"duration_sec": round(duration, 3)
}
if success:
record["result"] = msg
else:
record["error"] = msg
logging.info(json.dumps(record))
在call_tool中调用
start = time.time()
try:
# ... 执行工具 ...
duration = time.time() - start
log_call(api_key, request.client.host, tool_name, req["arguments"], True, str(result), duration)
except Exception as e:
duration = time.time() - start
log_call(api_key, request.client.host, tool_name, req["arguments"], False, str(e), duration)
raise
四、部署层加固
除了代码层进行授权、验证方面的安全加固,还需要在部署层进行技术层面的安全加固。包括以下措施。
| 措施 | 说明 |
|---|---|
| 强制 HTTPS | 用 Nginx/Traefik 终止 TLS,禁止 HTTP |
| IP 白名单 | 仅允许 Agent 服务器 IP 访问 MCP 服务 |
| 容器隔离 | MCP 服务运行在独立 Pod/容器,网络策略限制 |
| 密钥管理 | MCP_API_KEYS 从 Secret Manager 注入,不写死代码 |
五、其他规范要求
经过以上的技术措施,你的MCP服务框架已经有足够的风险防范能力。
相比于原始的MCP服务,增强后的MCP服务能够抵御以下风险或攻击。
| 攻击场景 | 原始 fastmcp | 增强后 |
|---|---|---|
| 未授权调用 | ✅ 成功 | ❌ 401 |
| 普通用户调用 admin 工具 | ✅ 成功 | ❌ 403 |
LLM 注入 {"cmd": "rm -rf /"} | ✅ 执行 | ❌ 校验失败(若未定义 cmd 字段) |
| 暴力循环调用 | ✅ DoS | ❌ 429 限流 |
| 日志泄露密码 | ✅ 明文记录 | ✅ 自动脱敏 |
此外,还有一些场景是需要在tool的实现层进行限制。我们可以在以上的基础上增加一些规范要求,进一步规范MCP服务的使用。
1、变更操作必须验证状态并支持一键回退;
2、不允许直接执行智能体输入的SQL;
3、不允许直接操作系统文件;
还有其他情况,可以根据生产运行情况进行补充。