- 教程
- 文档
- 人工智能
【免费下载链接】mcp-for-beginners
This open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.
导读
本篇文章围绕mcp-for-beginners课程中「11-simple-auth」章节的 TypeScript 解决方案展开,讲解如何为基于 Express 的 MCP(Model Context Protocol)HTTP 服务器加上中间件认证:从验证Authorization请求头、校验 JWT 令牌,到按User.Read等作用域(scope)做细粒度授权。读完本文,你将能独立跑通整个示例,理解服务端中间件的完整校验链路,并掌握通过修改作用域来观察认证失败现象的调试方法。
认证与授权:先厘清两个概念
在进入代码之前,先明确两个容易混淆的概念(见 章节主文档):
- Authentication(认证):判断来访者是否有权进入系统,即是否能够访问承载 MCP Server 能力的资源服务器;
- Authorization(授权):判断该用户是否有权访问其所请求的具体资源,例如只能读取订单而不能删除。
最朴素的实现是 Basic Auth:客户端在Authorization请求头中携带凭据(用户名密码的 Base64 或 API Key),服务端通过**中间件(middleware)**在请求到达业务代码前校验凭据。校验失败时,服务端返回401 Unauthorized(未认证)或403 Forbidden(无权限)。
[!NOTE] 本文 TypeScript 示例基于 MCP
2025-11-25规范,使用mcp-session-id追踪会话;MCP2026-07-28规范已移除initialize握手与协议级会话 ID。差异说明可参考 What's Changed in MCP: The 2026-07-28 Specification。
示例工程全景
本示例位于 solution/typescript 目录,结构如下:
solution/typescript/ ├── package.json # 脚本与依赖定义 ├── tsconfig.json └── src/ ├── server.ts # Express + MCP Server,含认证中间件 ├── client.ts # MCP 客户端,携带令牌访问 /mcp ├── util.ts # JWT 生成(createToken)与校验(verifyToken) └── test.ts # 读取 .env 中令牌并验证的工具脚本从 package.json 可以看到全部操作都封装为 npm 脚本:
"scripts": { "start": "node ./build/server.js", "client": "node ./build/client.js", "generate": "node ./build/util.js", "build": "tsc" }依赖方面,示例使用@modelcontextprotocol/sdk(Streamable HTTP 传输)、express(Web 框架)、jsonwebtoken(JWT 签发与校验)、dotenv(读取 .env 环境变量)和zod(工具入参 schema 定义)。
四步跑通示例
第 1 步:安装依赖
npm install第 2 步:构建
npm run build该命令通过tsc将src/下的 TypeScript 编译到build/目录。
第 3 步:生成令牌
npm run generate这条命令会执行 util.ts 中的createToken():构造一个使用HS256签名的 JWT,其 payload 包含sub、name、admin、iat、exp(1 小时后过期)以及scopes: ["Admin.Write", "User.Read"],然后将令牌写入当前目录的.env文件(token=...)。客户端启动时会读取这个文件。
第 4 步:启动服务器与客户端
先在第一个终端启动服务器:
npm start再在第二个终端启动客户端:
npm run client服务器终端应看到类似输出:
User exists User has required scopes Middleware executed客户端终端应看到类似输出:
Connected to MCP server with session ID: c1e50d7b-acff-4f11-8f96-5ae490ca1eaa Available tools: { tools: [ { name: 'process-files', inputSchema: [Object] } ] } Client disconnected. Exiting...客户端成功连接后,通过listTools列出了服务端注册的process-files工具。
服务端中间件的四道校验关卡
核心认证逻辑集中在 server.ts 的app.use(...)中间件中,它对所有进入/mcp的请求依次执行四道检查:
app.use((req, res, next) => { // 1. Authorization 请求头是否存在 if(!req.headers["authorization"]) { res.status(401).send('Unauthorized'); return; } let token = req.headers["authorization"]; // 2. JWT 是否有效(完整性/签名校验) if(!isValid(token)) { res.status(403).send('Forbidden'); return; } // 3. 令牌对应的用户是否存在于系统中 if(!isExistingUser(token)) { res.status(403).send('Forbidden'); console.log("User does not exist"); return; } console.log("User exists"); // 4. 令牌是否具备所需作用域 if(!hasScopes(token, ["User.Read"])){ res.status(403).send('Forbidden - insufficient scopes'); return; } console.log("User has required scopes"); console.log('Middleware executed'); next(); });这四道检查对应了本文开头区分的认证与授权:
- 请求头存在性:缺失则直接返回
401 Unauthorized,属于认证失败; - 令牌有效性:
isValid内部调用verifyToken(jwt.verify)校验签名与过期时间,失败返回403 Forbidden; - 用户存在性:
isExistingUser将令牌中的name与内存中的用户列表比对(真实项目应查询数据库,代码中留有// TODO, check if user exists in DB); - 作用域校验:
hasScopes检查令牌中的scopes数组是否包含User.Read,不满足返回403 Forbidden - insufficient scopes。
其中hasScopes的实现(server.ts)使用了every语义——要求所有必需作用域都存在:
function hasScopes(scope: string, requiredScopes: string[]) { let decodedToken = verifyToken(scope); return requiredScopes.every(scope => decodedToken?.scopes.includes(scope)); }值得注意,这些检查只是作者强调的最低限度校验集合(章节文档原话:"these are the absolute minimum of checks you should be doing")。生产环境还应叠加来源 IP、请求频率(防机器人)、令牌吊销检查等。
客户端如何携带令牌
客户端 client.ts 通过dotenv读取.env中的令牌,并将其放入传输层requestInit.headers:
config(); let sessionId: string | undefined = undefined; let options: StreamableHTTPClientTransportOptions = { sessionId: sessionId, requestInit: { headers: { "Authorization": process.env.token || "secret123" } } }; const serverUrl = "http://localhost:8000/mcp";随后把options传给StreamableHTTPClientTransport,连接成功后记录transport.sessionId并调用client.listTools()。这正是章节文档所说的「两步走」:先构造携带凭据的配置对象,再将其传给传输层。
配套的 test.ts 可以在不启动服务器的情况下独立验证.env中的令牌:读取令牌、verifyToken解码、再检查用户是否存在,方便排查令牌生成环节的问题。
动手实验:修改作用域观察认证失败
为了验证作用域校验真的生效,按章节文档做如下实验。找到 server.ts 中的代码:
if(!hasScopes(token, ["User.Read"])){ res.status(403).send('Forbidden - insufficient scopes'); }把User.Read改成User.Write,然后重新构建并重启服务器:
npm run build npm start由于当前.env中令牌的scopes只有User.Read和Admin.Write,没有User.Write,认证会失败。此时客户端终端输出:
Error initializing client: Error: Error POSTing to endpoint (HTTP 403): Forbidden - insufficient scopes服务器终端则停留在:
User exists说明请求通过了「用户存在性」检查,但在「作用域校验」环节被拦截,没有继续往下执行。
恢复方式有两种:
- 改回服务端代码:把
User.Write改回User.Read,重新npm run build; - 给令牌补上该作用域:修改 util.ts 中 payload 的
scopes数组(例如加入"User.Write"),执行npm run generate重新生成.env,再重跑客户端。
这个实验直观展示了 MCP 场景下「认证通过、授权失败」的分层现象,也是排查403类错误的标准思路:先确认令牌是否过期/无效,再确认作用域是否满足服务端要求。
从 Basic Auth 走向 JWT 与更安全的架构
章节主文档 README 详细论述了从简单凭据升级到 JWT 的收益:
- 安全性:Basic Auth 反复传输凭据,JWT 有签发时间与过期时间,天然支持基于角色/作用域的细粒度访问控制;
- 无状态与可扩展性:JWT 自包含用户信息,无需服务端会话存储,可本地校验;
- 互操作与联邦:JWT 是 OpenID Connect 的核心,配合 Entra ID、Google Identity、Auth0 等身份提供商可支持单点登录;
- 模块化与灵活性:可配合 Azure API Management、NGINX 等 API 网关使用;
- 性能与缓存:解码后的 JWT 可缓存,减少重复解析开销;
- 高级特性:支持服务端 introspection(有效性检查)与 revocation(令牌吊销)。
同时务必注意代码中的安全提醒:不要将密钥硬编码在代码里(util.ts 的注释明确写着Use env vars in production),示例中的'your-secret-key'仅用于演示;传输凭据至少需要 HTTPS;还应规划短生命周期访问令牌 + 长生命周期刷新令牌的机制。
课程后续还提供了两处进阶路径:将身份模型迁移到标准 IdP(如 Entra)的 mcp-security-entra,以及将 MCP 服务器接入宿主环境的 Setting Up MCP Hosts。
总结
通过本文,你完整走通了mcp-for-beginners课程 11-simple-auth 章节的 TypeScript 样例:理解了认证与授权的区别、看到了 Express 中间件如何对/mcp请求实施「请求头 → 令牌 → 用户 → 作用域」四层校验、掌握了npm run generate生成 JWT 令牌并注入.env的流程,并通过修改User.Read为User.Write亲手验证了授权失败的行为。这套「中间件 + JWT + 作用域」的组合,正是为后续接入 OAuth 2.1 与标准身份提供商打下的基础。
- 教程
- 文档
- 人工智能
【免费下载链接】mcp-for-beginners
This open-source curriculum introduces the fundamentals of Model Context Protocol (MCP) through real-world, cross-language examples in .NET, Java, TypeScript, JavaScript, Rust and Python. Designed for developers, it focuses on practical techniques for building modular, scalable, and secure AI workflows from session setup to service orchestration.
相关推荐
MCP for Beginners TypeScript 简单认证实战:用 JWT 与 RBAC 中间件保护 Streamable HTTP 服务
MCP for Beginners TypeScript 简单认证实战:用 JWT 与 RBAC 中间件保护 Streamable HTTP 服务 导读 本文聚
教程文档人工智能基于 MCP Inspector 验证 TypeScript 低层 MCP 服务器:构建、工具调用与参数校验实战
基于 MCP Inspector 验证 TypeScript 低层 MCP 服务器:构建、工具调用与参数校验实战 本文围绕 mcp for beginners
教程文档人工智能MCP 服务认证从入门到实战:在 mcp-for-beginners 中用 Basic Auth、JWT 与 RBAC 保护你的 MCP Server
MCP 服务认证从入门到实战:在 mcp for beginners 中用 Basic Auth、JWT 与 RBAC 保护你的 MCP Server 导读 M
教程文档人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考