跳转到内容
搜索文档

授权

最后更新 查看 MarkdownAgent 设置

构建 Model Context Protocol (MCP) server 时,既需要让用户登录(authentication),也需要让用户授权 MCP client 访问其账户上的资源(authorization)。

Model Context Protocol 使用 OAuth 2.1 的子集进行授权。OAuth 允许用户授予有限资源访问权限,而无需共享 API 密钥或其他凭据。

Cloudflare 提供 OAuth Provider Library,实现 OAuth 2.1 协议的 provider 端,便于为 MCP server 添加授权。

OAuth Provider Library 有四种用法:

  1. 使用 Cloudflare Access 作为 OAuth provider。
  2. 直接与第三方 OAuth provider 集成,例如 GitHub 或 Google。
  3. 与自有 OAuth provider 集成,包括你可能已依赖的 authorization-as-a-service provider,如 Stytch、Auth0 或 WorkOS。
  4. Worker 自行处理 authorization 与 authentication。运行在 Cloudflare 上的 MCP server 处理完整 OAuth 流程。

以下各节说明这些选项,并链接到可运行的代码示例。

授权选项

(1) Cloudflare Access OAuth 提供方

Cloudflare Access 可为 MCP server 添加单点登录(SSO)功能。用户通过已配置的身份提供商一次性 PIN向 MCP server 认证,仅当身份符合 Access 策略时才授予访问权限。

要以 Cloudflare Access 作为 OAuth 提供方部署示例 MCP 服务器,请参阅 使用 Access for SaaS 保护 MCP 服务器

(2) 第三方 OAuth 提供方

OAuth Provider Library 可配置为使用第三方 OAuth 提供方(如 GitHub 或 Google)。完整示例见 GitHub 示例

使用第三方 OAuth 提供方时,须向 OAuthProvider 提供实现该提供方 OAuth 流程的处理函数。

import MyAuthHandler from "./auth-handler";

export default new OAuthProvider({
	apiRoute: "/mcp",
	// Your MCP server:
	apiHandler: MyMCPServer.serve("/mcp"),
	// Replace this handler with your own handler for authentication and authorization with the third-party provider:
	defaultHandler: MyAuthHandler,
	authorizeEndpoint: "/authorize",
	tokenEndpoint: "/token",
	clientRegistrationEndpoint: "/register",
});

请注意,如 Model Context Protocol 规范所定义,使用第三方 OAuth provider 时,MCP Server(你的 Worker)会生成并向 MCP client 签发自己的 token:

sequenceDiagram
    participant B as User-Agent (Browser)
    participant C as MCP Client
    participant M as MCP Server (your Worker)
    participant T as Third-Party Auth Server

    C->>M: Initial OAuth Request
    M->>B: Redirect to Third-Party /authorize
    B->>T: Authorization Request
    Note over T: User authorizes
    T->>B: Redirect to MCP Server callback
    B->>M: Authorization code
    M->>T: Exchange code for token
    T->>M: Third-party access token
    Note over M: Generate bound MCP token
    M->>B: Redirect to MCP Client callback
    B->>C: MCP authorization code
    C->>M: Exchange code for token
    M->>C: MCP access token

更多细节请参阅 Workers OAuth Provider Library 的文档说明。

(3) 自带 OAuth 提供方

若应用已实现 OAuth 提供方,或使用授权即服务提供方,用法与上文 (2) 第三方 OAuth 提供方 相同。

可将 auth provider 用于:

  • 允许用户通过邮件、社交登录、SSO(单点登录)和 MFA(多因素认证)向 MCP server 认证。
  • 定义直接映射到 MCP tool 的 scope 与权限。
  • 向用户展示与所请求权限对应的同意页。
  • 强制执行权限,使 Agent 只能调用被允许的工具。

Stytch

使用 Stytch 的远程 MCP 服务器 开始,让用户通过邮件、Google 登录或企业 SSO 登录,并授权其 AI Agent 代表其查看与管理公司 OKR。Stytch 会根据用户在组织内的角色与权限,限制授予 AI Agent 的范围。MCP 客户端授权时,每位用户会看到同意页,列出根据其角色可授予 Agent 的权限。

部署到 Cloudflare

更多面向消费者的用例:部署用于待办应用的远程 MCP 服务器,使用 Stytch 进行身份验证与 MCP 客户端授权。用户可通过邮件登录并立即访问账户关联的待办列表,并授权任意 AI 助手帮助管理任务。

部署到 Cloudflare

Auth0

从使用 Auth0 的远程 MCP 服务器开始,让用户通过邮件、社交登录或企业 SSO 认证,并通过 AI Agent 与其待办与个人数据交互。MCP 服务器代表用户安全连接 API 端点,并准确展示 Agent 在用户同意后能访问的资源。此实现中,访问令牌在长时间交互期间会自动刷新。

设置步骤:首先部署受保护的 API 端点:

部署到 Cloudflare

然后部署通过 Auth0 处理身份验证、并将 AI Agent 安全连接到你 API 端点的 MCP 服务器。

部署到 Cloudflare

WorkOS

从使用 WorkOS AuthKit 的远程 MCP 服务器开始,认证用户并管理授予 AI Agent 的权限。此示例中,MCP 服务器根据用户角色与访问权限动态暴露工具。所有已认证用户可使用 add 工具,但仅在 WorkOS 中被分配 image_generation 权限的用户才能授权 AI Agent 访问图像生成工具。这展示了 MCP 服务器如何根据已认证用户的角色与权限有条件地向 AI Agent 暴露能力。

部署到 Cloudflare

Descope

从使用 Descope Inbound Apps 的远程 MCP 服务器开始,认证并授权用户(例如邮件、社交登录、SSO)通过 AI Agent 与其数据交互。利用 Descope 自定义范围定义与管理权限,实现更细粒度控制。

部署到 Cloudflare

(4) MCP 服务器自行处理授权与认证

MCP 服务器使用 OAuth Provider Library 可独立完成完整 OAuth 授权流程,无需第三方参与。

Workers OAuth Provider Library 是实现 fetch() 处理函数 的 Cloudflare Worker,处理发往 MCP 服务器的请求。

如下所示,你提供 MCP 服务器 API 的处理函数、认证与授权逻辑,以及 OAuth 端点的 URI 路径:

export default new OAuthProvider({
	apiRoute: "/mcp",
	// Your MCP server:
	apiHandler: MyMCPServer.serve("/mcp"),
	// Your handler for authentication and authorization:
	defaultHandler: MyAuthHandler,
	authorizeEndpoint: "/authorize",
	tokenEndpoint: "/token",
	clientRegistrationEndpoint: "/register",
});

完整 OAuthProvider 用法(含模拟认证流程)见快速入门示例

此情况下的授权流程如下:

sequenceDiagram
    participant B as User-Agent (Browser)
    participant C as MCP Client
    participant M as MCP Server (your Worker)

    C->>M: MCP Request
    M->>C: HTTP 401 Unauthorized
    Note over C: Generate code_verifier and code_challenge
    C->>B: Open browser with authorization URL + code_challenge
    B->>M: GET /authorize
    Note over M: User logs in and authorizes
    M->>B: Redirect to callback URL with auth code
    B->>C: Callback with authorization code
    C->>M: Token Request with code + code_verifier
    M->>C: Access Token (+ Refresh Token)
    C->>M: MCP Request with Access Token
    Note over C,M: Begin standard MCP message exchange

请记住——authentication(身份验证)与 authorization(授权)不同。MCP Server 可自行处理授权,同时仍依赖外部身份验证服务先认证用户。快速入门示例 提供模拟身份验证流程。你需要实现自有身份验证 handler——自行处理身份验证,或使用外部身份验证服务。

在 tool 中使用认证上下文

用户通过 OAuth Provider 认证后,身份信息可在 tool 内访问。访问方式取决于使用 McpAgent 还是 createMcpHandler

使用 McpAgent

McpAgent 的第三个类型参数定义认证上下文形状。在 init() 与工具处理函数中通过 this.props 访问。

import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

type AuthContext = {
	claims: { sub: string; name: string; email: string };
	permissions: string[];
};

export class MyMCP extends McpAgent<Env, unknown, AuthContext> {
	server = new McpServer({ name: "Auth Demo", version: "1.0.0" });

	async init() {
		this.server.tool("whoami", "Get the current user", {}, async () => ({
			content: [{ type: "text", text: `Hello, ${this.props.claims.name}!` }],
		}));
	}
}

使用 createMcpHandler

在工具处理函数内使用 getMcpAuthContext() 访问相同信息。底层使用 AsyncLocalStorage

import { createMcpHandler, getMcpAuthContext } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

function createServer() {
	const server = new McpServer({ name: "Auth Demo", version: "1.0.0" });

	server.tool("whoami", "Get the current user", {}, async () => {
		const auth = getMcpAuthContext();
		const name = (auth?.props?.name as string) ?? "anonymous";
		return {
			content: [{ type: "text", text: `Hello, ${name}!` }],
		};
	});

	return server;
}

基于权限的 tool 访问

可根据用户权限控制可用工具。两种方式:在工具处理函数内检查权限,或条件注册工具。

export class MyMCP extends McpAgent<Env, unknown, AuthContext> {
	server = new McpServer({ name: "Permissions Demo", version: "1.0.0" });

	async init() {
		this.server.tool("publicTool", "Available to all users", {}, async () => ({
			content: [{ type: "text", text: "Public result" }],
		}));

		this.server.tool(
			"adminAction",
			"Requires admin permission",
			{},
			async () => {
				if (!this.props.permissions?.includes("admin")) {
					return {
						content: [
							{ type: "text", text: "Permission denied: requires admin" },
						],
					};
				}
				return {
					content: [{ type: "text", text: "Admin action completed" }],
				};
			},
		);

		if (this.props.permissions?.includes("special_feature")) {
			this.server.tool("specialTool", "Special feature", {}, async () => ({
				content: [{ type: "text", text: "Special feature result" }],
			}));
		}
	}
}

在处理函数内检查会向 LLM 返回错误信息,LLM 可向用户解释拒绝原因。条件注册意味着 LLM 看不到用户无权访问的工具——完全无法尝试调用。

后续步骤

MCP portals

设置 MCP 门户以提供治理与安全。

这篇文档对您有帮助吗?