79 lines
4.0 KiB
Markdown
79 lines
4.0 KiB
Markdown
---
|
||
id: ai.mcp.scenario.internal-tools-gateway
|
||
title: 企业内部 MCP 服务:统一接入、鉴权、审计和版本管理
|
||
type: scenario
|
||
domain: ai
|
||
stack: [mcp, fastapi, nginx]
|
||
tags: [MCP, 企业集成, 鉴权, 审计, 工具治理, Streamable HTTP]
|
||
level: advanced
|
||
prerequisites: [ai.mcp.protocol-server]
|
||
est_hours: 2.5
|
||
related: [ai.function-calling.scenario.safe-business-tools, ai.mcp.interview]
|
||
week: [10, 11]
|
||
---
|
||
|
||
# 企业内部 MCP 服务:统一接入、鉴权、审计和版本管理
|
||
|
||
## 业务背景与问题
|
||
|
||
各团队都在做 AI 助手(客服 Agent、研发助手、运营报表 Agent),每个团队都自己对接一遍工单、知识库、CRM 接口,出现:
|
||
|
||
1. 同一个系统被对接了 4 次,接口变更时要改 4 个地方;
|
||
2. 有团队把 CRM 的高权限账号写在了 Agent 的配置里;
|
||
3. 员工在 Cursor 里装了来源不明的 MCP 服务,可能读取本地代码和密钥;
|
||
4. 出了问题不知道是哪个 Agent、哪个用户调用的。
|
||
|
||
## 约束
|
||
|
||
- 已有统一登录(OAuth 2.0 / OIDC)。
|
||
- 各业务系统的接口和权限体系保持不变。
|
||
|
||
## 方案设计
|
||
|
||
1. **按领域提供 MCP 服务**:工单服务、知识库服务、CRM 只读服务,由各系统的负责团队维护,部署为 **Streamable HTTP** 远程服务。
|
||
2. **鉴权**:MCP 规范为 HTTP 传输定义了基于 OAuth 2.1 的授权流程;服务从令牌中识别用户,调用业务系统时使用用户身份,业务系统按原权限校验。不在客户端配置高权限账号。
|
||
3. **网关**:Nginx / API 网关统一做 TLS、限流、访问日志;服务内部记录工具级审计日志(用户、客户端、工具、参数摘要、结果、耗时)。
|
||
4. **工具治理**:工具命名和描述规范;写操作工具标注并要求确认;工具变更做版本记录,删除工具前先标记废弃。
|
||
5. **客户端白名单**:公司发布允许接入的 MCP 服务清单;本地 stdio 服务只允许使用内部审核过的。
|
||
|
||
## 关键代码
|
||
|
||
带鉴权的远程服务(示意,SDK 2.x 的鉴权参数为 `token_verifier` / `auth`,具体写法以官方文档为准):
|
||
|
||
```python
|
||
from mcp.server.mcpserver import MCPServer
|
||
|
||
mcp = MCPServer(
|
||
"ticket-service",
|
||
token_verifier=CompanyTokenVerifier(issuer="https://sso.example.com"), # 校验 SSO 签发的令牌
|
||
auth=AuthSettings(issuer_url="https://sso.example.com", resource_server_url="https://mcp.example.com/tickets"),
|
||
)
|
||
|
||
|
||
@mcp.tool()
|
||
async def create_ticket(ticket: TicketIn, ctx: Context) -> dict:
|
||
user = current_user(ctx) # 从令牌中取用户
|
||
audit.log(user=user.id, tool="create_ticket", args=ticket.model_dump())
|
||
return await ticket_api.create(ticket, on_behalf_of=user.token, idempotency_key=ticket.request_id)
|
||
```
|
||
|
||
## 取舍
|
||
|
||
| 选择 | 优点 | 缺点 |
|
||
| --- | --- | --- |
|
||
| **按领域的远程 MCP 服务(本方案)** | 一次实现多处复用;权限和审计集中 | 需要部署和维护;网络调用多一跳 |
|
||
| 每个 Agent 自己对接接口 | 灵活 | 重复建设,权限分散 |
|
||
| 一个大而全的 MCP 服务 | 部署简单 | 工具太多,上下文膨胀;团队边界不清 |
|
||
| 本地 stdio 服务 | 适合访问本地文件、开发工具 | 不适合共享的业务系统 |
|
||
|
||
## 易错点
|
||
|
||
- 远程服务没有鉴权,或者用一个共享令牌。
|
||
- 工具返回了超出用户权限的数据。
|
||
- 工具描述随意修改,导致各 Agent 的行为突然变化:工具描述也要评审和回归测试。
|
||
- 只监控 HTTP 状态码,不知道工具执行的业务结果。
|
||
|
||
## 面试怎么讲
|
||
|
||
> “我们把工单、知识库这些内部能力按领域做成远程 MCP 服务,由系统负责团队维护,各个 Agent 和 Cursor 都通过它接入,避免重复对接。服务使用 Streamable HTTP,令牌来自公司 SSO,调用业务系统时用用户身份,原有权限照常生效;写操作工具要求确认并带幂等 ID;网关做限流,服务记录工具级审计日志;工具描述和接口一样要评审和做回归。”
|