如何在Cloudflare远程MCP服务器的工具调用中传递API密钥
问题背景
我通过npm create cloudflare@latest -- my-mcp-server --template=cloudflare/ai/demos/remote-mcp-authless模板搭建了无OAuth的远程MCP服务器,已经能在fetch函数中从请求头拿到Authorization的Bearer Token,但不知道如何将这个Token传递到MCP工具调用的extra参数中使用。
我已配置mcp remote通过请求头传递Token:
{ "mcpServers": { "remote-example": { "command": "npx", "args": [ "mcp-remote", "https://remote.mcp.server/sse", "--header", "Authorization: Bearer ${AUTH_TOKEN}" ] } } }
解决方案
可以通过扩展McpAgent类并传递上下文参数的方式,将Token注入到工具调用的extra变量中,具体实现如下:
1. 扩展McpAgent类,添加上下文传递逻辑
修改MyMCP类,新增上下文属性存储Token,并在工具调用时将其注入extra:
import { McpAgent } from "agents/mcp"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; export class MyMCP extends McpAgent { // 私有属性存储上下文(包含Token) #context; // 修改构造函数,接收上下文参数 constructor(context) { super(); this.#context = context; this.server = new McpServer({ name: "Authless Calculator", version: "1.0.0", }); } async init() { this.server.tool( "add", { a: z.number(), b: z.number() }, async ({ a, b }, extra) => { // 从extra中获取token const token = extra.token; console.log("add工具收到Token:", token); return { content: [{ type: "text", text: String(a + b) }], }; } ); this.server.tool( "calculate", { operation: z.enum(["add", "subtract", "multiply", "divide"]), a: z.number(), b: z.number(), }, async ({ operation, a, b }, extra) => { // 从extra中获取token const token = extra.token; console.log("calculate工具收到Token:", token); let result: number; switch (operation) { case "add": result = a + b; break; case "subtract": result = a - b; break; case "multiply": result = a * b; break; case "divide": if (b === 0) return { content: [ { type: "text", text: "Error: Cannot divide by zero", }, ], }; result = a / b; break; } return { content: [{ type: "text", text: String(result) }] }; } ); } // 重写create方法,传递上下文到实例 static create(context) { const agent = new this(context); return agent.init().then(() => agent); } }
2. 修改fetch函数,传递Token到MCP服务
在fetch函数中,调用serve和serveSSE时,通过自定义的create方法传入包含Token的上下文:
export default { fetch(request: Request, env: Env, ctx: ExecutionContext) { const url = new URL(request.url); const authHeader = request.headers.get("authorization"); if (!authHeader?.startsWith("Bearer ")) { return new Response("Forbidden", { status: 403 }); } const token = authHeader.split(/\s+/)[1] ?? ""; // 封装包含Token的上下文 const context = { token }; if (url.pathname === "/sse" || url.pathname === "/sse/message") { // 传递上下文到SSE服务 return MyMCP.serveSSE("/sse", { create: () => MyMCP.create(context) }).fetch(request, env, ctx); } if (url.pathname === "/mcp") { // 传递上下文到MCP服务 return MyMCP.serve("/mcp", { create: () => MyMCP.create(context) }).fetch(request, env, ctx); } return new Response("Not found", { status: 404 }); }, };
原理说明
- 通过重写
McpAgent的create方法,将包含Token的上下文传入Agent实例 - 在工具函数的
extra参数中,可直接获取到注入的Token值 - 该方案保留了MCP工具的原有结构,同时实现了上下文参数的安全传递
内容的提问来源于stack exchange,提问作者Vladislav
相关产品推荐
相关产品推荐

