如何在MCP Python SDK中结合SSE使用Bearer请求头实现客户端授权?
如何在MCP Python SDK中结合SSE使用Bearer请求头实现客户端授权?
嗨,我刚好在MCP Python SDK里折腾过类似的授权需求,给你一步步梳理下怎么结合SSE用Bearer请求头实现客户端授权哈!
首先得明确:SSE是基于HTTP长连接的,客户端发起SSE连接的第一步会发一个普通的HTTP请求握手,这个时候就会带上Authorization请求头,我们要做的就是在服务器端拦截这个请求,验证Bearer Token的合法性。
第一步:在服务器端添加Token验证的预处理钩子
MCP SDK提供了请求预处理的钩子,所有进来的请求(包括SSE的初始连接请求)都会经过这个钩子,我们可以在这里做Token校验:
from mcp.server import MCPServer from mcp.types import RequestContext def validate_bearer_token(context: RequestContext): # 从请求头里取出Authorization字段 auth_header = context.request.headers.get("Authorization") # 先检查有没有这个头 if not auth_header: context.response.status_code = 401 context.response.body = "请提供Authorization请求头" return False # 检查是否是Bearer类型的Token格式 if not auth_header.startswith("Bearer "): context.response.status_code = 401 context.response.body = "授权格式错误,请使用Bearer方案" return False # 提取实际的Token字符串 token = auth_header.split(" ")[1] # 这里替换成你自己的Token验证逻辑——比如查数据库、调用内部认证接口等 # 举个简单的示例验证逻辑,你根据实际业务改就行 def is_valid_token(token_str): # 这里写你的验证逻辑,比如判断token是否在有效列表里、签名是否合法等 return token_str == "your-valid-token-123" if not is_valid_token(token): context.response.status_code = 403 context.response.body = "Token无效或已过期" return False # 验证通过,继续处理后续请求 return True # 创建MCP服务器实例 server = MCPServer() # 把验证钩子注册成全局预处理钩子,所有请求都会走这个校验 server.register_pre_request_hook(validate_bearer_token)
第二步:处理SSE业务逻辑
Token验证通过后,就可以正常处理SSE的流推送了,比如注册你的SSE服务方法:
@server.register_method("sse_authorized_stream") def handle_authorized_sse_stream(context: RequestContext): # 这里已经通过Token验证了,直接处理SSE推送逻辑就行 # 比如给客户端发事件 context.response.sse.send_event("system_notice", data="已通过授权,开始推送SSE事件...") # 后续可以加定时推送、业务触发推送的逻辑
客户端这边的设置
就像你截图里的MCP Inspector那样,客户端在发起SSE请求的时候,要在请求头里带上Authorization: Bearer <你的有效Token>。不管是用MCP Inspector测试,还是自己写客户端代码,只要把这个请求头加上,服务器端的预处理钩子就能拿到Token并验证了。
一些小提醒
- SSE是长连接,只要初始握手时Token验证通过,后续的事件推送就不需要重复校验了,所以初始的一次校验就够
- 你的Token验证逻辑要尽量高效,毕竟每个SSE连接都会触发这个钩子,别用太耗时的操作拖慢连接建立速度
- 如果你的Token有过期时间,得考虑Token过期后的处理:比如客户端检测到连接断开后,用新的Token重连,或者在SSE流里定期返回Token过期的事件提示客户端更新
备注:内容来源于stack exchange,提问作者Roman Gelembjuk




