Dapr 为 MCP 服务器做了什么?
使用 Dapr,开发者可以安全地与 MCP 服务器交互,并启用细粒度的 ACL(访问控制列表),同时具备内置的追踪和指标功能,以及弹性策略来处理 MCP 服务器可能宕机或无响应的情况。
This is the multi-page printable view of this section. Click here to print.
使用 Dapr,开发者可以安全地与 MCP 服务器交互,并启用细粒度的 ACL(访问控制列表),同时具备内置的追踪和指标功能,以及弹性策略来处理 MCP 服务器可能宕机或无响应的情况。
MCP 规范 并不强制要求 MCP 客户端与服务器之间的任何形式的身份验证。安全模型由用户自行规划和实施。这给开发者带来了维护负担,并使 MCP 服务器面临各种攻击面。
虽然 MCP 服务器缺少身份标识,但 OAuth2 是一个成熟的标准,可用于正确地对 MCP 客户端进行身份验证以访问 MCP 服务器。
在以下场景中,OAuth2 变得尤为重要:
Dapr 通过使用 中间件 组件,支持 MCP 客户端与服务器之间的 OAuth2 身份验证。
Dapr 为 MCP 服务器的生产级部署支持两种关键身份验证机制——客户端和服务器端。
客户端发起 OAuth2 以获取访问令牌,并在连接到 MCP 服务器时包含该令牌。 这证明了用户的身份和权限,对于远程、敏感或多租户 MCP 服务器是必需的。 它确保服务器可以信任调用方以及客户端允许使用的范围。
服务器验证客户端的令牌,或者在令牌缺失或不足时触发 OAuth2 登录或范围升级。 这对于云托管或共享 MCP 服务器、租户感知系统以及需要用户特定授权的集成是必需的。 它强制执行访问控制,隔离用户,并保护特权工具和数据。
Dapr 允许开发者和运维人员将远程 HTTP 服务建模为可使用 Dapr 服务调用 API 管理和调用的资源。
创建此 HTTPEndpoint 资源来表示 MCP 服务器:
apiVersion: dapr.io/v1alpha1
kind: HTTPEndpoint
metadata:
name: "mcp-server"
spec:
baseUrl: https://my-mcp-server:443
headers:
- name: "Accept"
value: "text/event-stream"
以下中间件组件定义了与 OAuth2 提供程序的连接:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: oauth2
spec:
type: middleware.http.oauth2
version: v1
metadata:
- name: clientId
value: "<client-id>"
- name: clientSecret
value: "<client-secret>"
- name: authURL
value: "<authorization-url>"
- name: tokenURL
value: "<token-url>"
- name: scopes
value: "<comma-separated scopes>"
接下来,创建配置资源,告诉 Dapr 使用 OAuth2 中间件:
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: auth
spec:
tracing:
samplingRate: "1"
httpPipeline:
handlers:
- name: oauth2 # 在此引用 oauth 组件
type: middleware.http.oauth2
将以下代码复制到名为 mcpclient.py 的文件中:
import asyncio
from mcp import ClientSession
from mcp.transport.http import HttpClientTransport
async def main():
# Dapr 进程的默认地址。在生产环境中使用环境变量
server_url = "http://localhost:3500/"
# 创建带有标头的 HTTP/SSE 传输,以针对上面定义的 HTTPEndpoint
transport = HttpClientTransport(
url=server_url,
headers={
"dapr-app-id": "mcp-server",
}
event_headers={
"Accept": "text/event-stream",
},
)
# 创建绑定到传输的 MCP 会话
async with ClientSession(transport) as session:
await session.initialize()
tools = await session.call("tools/list")
print("Server Tools:", tools)
await session.shutdown()
if __name__ == "__main__":
asyncio.run(main())
将上面的 YAML 文件放入 components 目录并运行 Dapr:
dapr run --app-id mcpclient --resources-path ./components --dapr-http-port 3500 --config ./config.yaml -- python mcpclient.py
MCP 客户端使 Dapr 在连接到 MCP 服务器之前启动 OAuth2 流水线。
定义一个与客户端示例相同的中间件组件。
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: oauth2
spec:
type: middleware.http.oauth2
version: v1
metadata:
- name: clientId
value: "<client-id>"
- name: clientSecret
value: "<client-secret>"
- name: authURL
value: "<authorization-url>"
- name: tokenURL
value: "<token-url>"
- name: scopes
value: "<comma-separated scopes>"
接下来,创建配置组件,修改 appHttpPipeline 字段。这告诉 Dapr 对传入的调用应用中间件。
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: auth
spec:
tracing:
samplingRate: "1"
appHttpPipeline:
handlers:
- name: oauth2 # 在此引用 oauth 组件
type: middleware.http.oauth2
将上面的 YAML 文件放入 components 目录并运行 Dapr:
dapr run --app-id mcpserver --resources-path ./components --dapr-http-port 3500 --config ./config.yaml -- python mcpserver.py
当 MCP 服务器的请求到达时,Dapr 将启动 OAuth2 流水线。