从REST API构建安全MCP服务器:OAuth、权限与风险分级实战

从现有REST API构建安全MCP服务器:不暴露危险操作、双套凭证分离、scope与claim锁定调用方身份。
本文以订单API为例,系统梳理了将REST API封装为MCP服务器时的安全实践全流程。核心思路是"分层收口":在工具选择阶段直接不暴露破坏性操作(如DELETE接口),在权限层用OAuth scope限制工具调用资格、用加密转发的claim绑定调用方租户身份,在凭证层将客户端OAuth凭证与后端API密钥严格隔离,在运行层为每次调用打上Read/Write/Destructive风险标签并全量记录日志。文章指出MCP协议本身只解决工具发现与调用的标准化问题,权限边界和危险操作识别必须由开发者在服务器构建阶段主动介入,而非依赖模型的自我约束。
每个团队现在都想做同一件事:让 Claude、Cursor 或内部智能体通过已有的 API 查询订单、核对客户、开工单。而每个安全团队都会反问同一个问题:什么能阻止模型去调用那个执行删除操作的接口?
Model Context Protocol(MCP)只解决了一半问题。它为 AI 客户端提供了发现和调用工具的标准方式。另一半——决定哪些工具存在、谁能调用、什么样的调用算"危险"——仍然要靠你自己把控。
本文梳理如何从一个现有的 REST API 构建 MCP 服务器,并正确处理 MCP 的授权与认证:面向客户端的 OAuth、面向工具的 scope 与 claim,以及给任何会改动数据的操作打上风险分级。文中以 Koodisi 的实践为例(它通过已发布的 API 集合自动生成 MCP 服务器),但这套模式适用于任何你自建的方案。
示例场景:一个订单 API
假设你有一个精简的订单 API,包含三个操作:
| 操作 | 功能 | 风险 |
|---|---|---|
GET /orders/{id} | 读取订单 | Read(读) |
POST /orders/{id}/refund | 发起退款 | Write(写) |
DELETE /customers/{id} | 删除客户 | Destructive(破坏性) |
目标很明确:Claude 可以自由查询订单,可以在带确认步骤的前提下发起退款,而删除接口——它压根就不应该看到。

第一步:从已发布的 API 和安全配置出发
构建 MCP 服务器前,需要三样东西先就位:
- 已发布的 API 集合,并生成了 OpenAPI 规范。规范中的每个操作都是候选工具。
- 安全配置(Security Profile),用来定义身份提供方、scope(例如
orders:read、orders:write)以及令牌可携带的 claim(例如tenant_id)。 - 一个运行环境。
安全配置的重要性超出表面。一个服务器只能绑定到一个配置,而你只能授予该配置中已定义的 scope 和 claim。换句话说,没人能把身份提供方从未签发过的权限交给 AI 客户端——这是从源头上收紧权限边界。
OpenAPI 规范(原名 Swagger)是描述 REST API 结构的 JSON/YAML 文件,包含每个端点的路径、HTTP 方法、参数、请求体和响应格式。MCP 服务器生成工具时,本质上是将规范中每个 operationId 对应的操作翻译成一个可供模型调用的函数——函数名、入参类型和描述都来自规范本身。这意味着规范的质量直接决定模型"理解"工具的质量:描述模糊的操作会导致模型猜测该什么时候调用,描述精确的操作则让模型能准确判断意图。因此,在将 API 接入 MCP 之前,值得检查规范中每个操作的 summary 和 description 字段是否清晰表达了该操作的业务语义和副作用,而不仅仅是技术签名。
第二步:创建服务器并挑选工具
在创建流程中,你需要给服务器命名、选择环境与安全配置,然后选取要暴露的已发布操作。本例只暴露了前两个:
GET /orders/{id}→ 工具,风险分级 ReadPOST /orders/{id}/refund→ 工具,风险分级 WriteDELETE /customers/{id}→ 不暴露
最后一行是整篇文章里最关键的安全决策。最廉价的护栏,就是一开始就不暴露某个操作。
风险分级分为 Read、Write、Destructive 三类。它们会随每个工具一起传递,这样客户端就能在任何会改动数据的操作(比如退款)前插入确认步骤。
第三步:按工具粒度配置 scope 与 claim
在"APIs & Tools"页面,你可以为整个规范设置默认值(所有工具继承),再为单个工具追加额外要求:
该规范默认值: scopes: orders:read claims: tenant_id
refund 工具(追加): scopes: orders:write
claim 是很多人跳过、随后又后悔的部分。附加在调用方身上的 claim 值会被加密转发到下游 API,这样后端仍然能收到调用方的租户信息并套用自己的常规规则。模型无法靠话术钻进另一个租户的订单——因为租户来自令牌,而非 prompt。
OAuth 2.0 中的 scope 是附加在访问令牌上的权限字符串,用于声明持有者被授权执行哪类操作。当 MCP 服务器在接收到工具调用请求时,会校验请求方携带的令牌中是否包含该工具所要求的 scope——例如 orders:write——不满足则直接拒绝,不会转发到下游 API。Claim 则是令牌载荷(payload)中的键值对字段,常见的有 sub(用户ID)、tenant_id(租户ID)、role 等,由身份提供方(IdP)在颁发令牌时签入,客户端无法自行伪造。将 tenant_id 作为 claim 转发到下游,意味着后端 API 收到的每个请求都携带了经过加密验证的租户信息,无需依赖调用方在请求体或 prompt 中自报家门,从根本上防止了跨租户越权访问。
第四步:为工具配置下游凭证
工具需要向你真实的 API 完成认证。在"Downstream Credentials"中,你为每个安全方案填入 API Key、Bearer Token 或 Basic Auth 值。这些凭证会加密存储,且不再二次显示。
注意这里的职责分离:客户端通过 OAuth 应用向 MCP 服务器认证;工具通过下游凭证向你的后端认证。 AI 客户端永远看不到后端密钥。这是整套架构的安全基石之一。
这里的"职责分离"对应信息安全中的 Separation of Concerns 原则,在凭证管理上具体体现为两个独立的信任链:其一,AI 客户端(Claude、Cursor 等)持有 OAuth client_id 和 client_secret,只能向 MCP 服务器证明"我是谁、我有哪些权限",无法接触到后端 API 的真实密钥;其二,MCP 服务器在确认客户端身份与 scope 合法后,才使用自己保管的下游凭证向后端发起请求。这样即使 AI 客户端被恶意 prompt 注入或会话被劫持,攻击者也只能以该客户端已有的 scope 范围行事,而无法提取或复用后端凭证去直接绕过 MCP 层调用 API。这一架构也方便凭证轮换:更换后端 API Key 只需更新服务器端配置,所有接入的客户端无需感知。
第五步:用 OAuth 应用做客户端认证
在"Client Access"中新建 OAuth 应用,设置 scope 和默认 claim,分配用户,拿到 client_id 和 client_secret(只显示一次,务必复制保存)。
对组织外部的人员,可以开启"接受外部客户端"并分享注册链接。注册请求会先进入 Pending(待审) 状态,在有人批准前,登录会返回 401。这正是一个值得每个 API 都拥有的审核队列。
第六步:接入 Claude 之前先测试
"Connect"页签可以生成一个短期有效的测试令牌,让你用纯 JSON-RPC 直接访问服务器。MCP 基于 JSON-RPC 2.0,列出工具的请求是这样的:
curl -s "$MCP_ENDPOINT" \
-H "Authorization: Bearer $TEST_TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
你应当恰好看到两个工具。如果看到三个,回第二步检查。
第七步:把 Claude(或 Cursor)接到 MCP 服务器
同一个"Connect"页签能为 Claude、Cursor、Gemini CLI、mcp-remote、Python 或 cURL 生成配置片段。以 Claude Desktop 为例:进入 Settings → Developer → Edit Config,把片段粘贴进 claude_desktop_config.json,填好 client ID 和 secret,重启即可。Claude 会通过 OAuth 完成登录,工具随即出现。
然后试一下最直观的指令:
"订单 1042 的状态是什么?如果还没发货,就退款。"
Claude 会用读取工具查到订单,而标记为 Write 的退款工具,正是客户端可以放在确认步骤之后的那个。无论如何,删除接口都不在菜单上。

第八步:盯住它到底做了什么
"Analytics"页签展示总调用数、成功率、错误、被阻止的调用以及 p95 延迟,并可按工具或用户维度拆分;"Activity log"则让你定位到每一次具体调用。当有人问"那笔退款是 AI 发起的吗?",你可以拿记录回答,而不是靠猜。
几点核心经验
- 少暴露。 最安全的破坏性工具,就是根本不存在的那个。
- 标注风险。 Read、Write、Destructive 给了客户端一个停下来询问的标准理由。
- 绑定身份,而非 prompt。 scope 与转发的 claim 把模型锁在调用方的权限范围内。
- 分离两套凭证。 客户端用 OAuth,后端密钥留在服务器端。
- 记录每一次调用。 智能体以机器速度行动,逐次调用的日志不是可选项。
智能体接入企业 API 的浪潮正在到来,而把它们关进可控的笼子里,比让它们"能跑起来"重要得多。这套从 OpenAPI 规范出发、以风险分级和双重凭证收口的模式,为团队提供了一个可落地的起点。
相关推荐

零成本搭建AI超级员工系统:智能体自动工作流全解析
深度拆解B站演示的AI超级员工系统:Agent智能体编排、数字人口播、地图与企业获客、24小时智能客服及法务模块全覆盖。分析零成本开户背后的商业逻辑与合规风险,帮助创业者判断这套AI数字员工系统的真实投产比。

Chatbot与AI Agent的本质区别:从对话到执行的跨越
Chatbot和AI Agent有什么区别?本文基于Learn Tech频道的MCP系列讲解,用订机票、笔记摘要等实例说明:Chatbot只给答案,Agent通过思考-行动-观察循环真正完成任务,并拆解模型、工具、记忆、目标四大部件及MCP的桥梁作用,同时讨论Agent的适用边界与权限风险。

免费GitHub仓库:342小时AI课程,从数学到MCP服务器
一个免费GitHub仓库提供342小时AI课程,包含523节课、20个阶段,覆盖数学基础到Agent构建和MCP服务器。支持目标驱动学习,每节课产出可留存的prompt、skill或agent,已有近10万人开始学习。