无国籍MCP门户和注册表入口
Type: Learn
Languages: Python
Prerequisites: Phase 13 · 15 (security), Phase 13 · 16 (authorization)
Time: ~75 minutes
学习目标
- 聚合多个MCP服务器在一个2026-07-28终端点后,而没有会话亲密性.
- 在政策或转发之前,按要求验证元数据和路由标题.
- 结合工具,使用稳定的命名空间,确定性顺序,描述符针,RBAC和私人缓存.
- 作为发现证据,仍然需要入学政策.
- 路线要求范围的SSE,
subscriptions/listenMRTR 再试, 任务延长调用正确. - 隔离传统的握手和会议支持.
问题
直接连接一个客户端到一个服务器是简单的.更大的部署需要一致的答案更难的问题:
- 哪些服务器可以使用?
- 哪个校长可以看到和打电话每个工具?
- 如果两个后端暴露出同一个名字,会发生什么?
- 描述符的变化如何进行审查?
- 利率限制和审计活动在哪里适用?
- 任何一个案例能处理下一个请求吗?
网关位于客户端和后端MCP服务器之间. 它呈现一个MCP终端点,应用跨界政策,并传递批准的请求.
旧的网关设计通常将一个客户端会议复杂化成多个后端会议,然后重新写Mcp-Session-Id这是一个传统的兼容性设计. 2026-07-28核心没有协议会议.
概念
现代门口之路
对于每项请求:
- 确认出境许可证的本人身份.
- 验证
MCP-Protocol-Version现在Mcp-Method现在Mcp-Name其他params._meta现在,我们要去. - 授权主题,资源,方法,工具和论点.
- 应用描述符,注册表,利率和数据政策.
- 创建一个新的独立请求,为选择的后端.
- 验证后端结果并返回网关结果.
- 记录一个审计事件,没有记录秘密.
没有步骤需要隐藏协议会议.应用状态仍然可以存在数据库,明确手柄,任务或完整性保护的MRTR状态中.
运行时间政策是主要的关门决定
录取决定后端版本可以进入门口.它不授权直播通话.对于每个请求,门口从认证的主,发行者和资源,租户,匹配的方法和名称,正常化参数,被允许的描述符针,当前后端健康,能力交叉,数据分类,利率状态以及任何行动相关的批准重新计算了政策.
登记记录可以保持活跃,而用户的角色被撤销.一个描述符可以保持固定,而一个目的地参数跨越租户界限.一个后端可以保持批准,而事件政策隔离状态变化的呼叫.因此,运行时间政策是主要允许或拒绝决定,登记和描述符证据作为输入.
不要在连接或删除会议识别器下缓存允许决定. 如果没有可用的政策,按操作类进行声明的失败政策. 安全默认是,如果无法关闭状态变化和敏感阅读,而明确批准的公共阅读路径只能使用短期的最后已知政策,只有当其风险模型允许时. 记录该政策版本和失败路径作出决定,然后在返回之前验证后端结果.
一个POST终点
现代流向 HTTP 通过 POST 发送每个 JSON-RPC 消息:
POST /mcp
Authorization: Bearer <gateway-token>
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: notes.search
Accept: application/json, text/event-stream网关可以返回JSON或请求-scoped SSE,为 POST. GET和 DELETE返回405现代请求. Mcp-Session-Id其他Last-Event-ID不要创造权威,亲密关系或重复行为.
标题和体值必须一致. 拒绝与-32020在搜索后端之前,这允许负载平衡器,门户和速度限制器路由,而不会分析整个机体,同时保持端到端完整性.
验证在一个确切的顺序:JSON-RPC和元数据类型,标题和体格等,然后支持匹配的版本.一个不匹配返回HTTP 400-32020如果标题和体格同意不支持的版本,请返回HTTP 400-32022其他data完全是{"supported":["2026-07-28"],"requested":"<actual>"}未知方法返回了HTTP 404-32601现在,我们要去.
ProtocolError带有可选的data通过一个通道将其串行到JSON-RPC错误对象中.id通过 HTTP 通知,它返回 202 个空格.
实现发现在每个层
通过网关实现server/discover它还发现每个后端,所以它知道协议版本,功能和扩展.
举例的网关结果:
{
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {"listChanged": true}
},
"ttlMs": 30000,
"cacheScope": "private",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "enterprise-gateway",
"version": "2.0.0"
}
}
}广告只能在网关可以尊重的功能交叉点.后端功能不自动安全地暴露.没有后端路径的网关功能不有用广告.
serverInfo没有任何数据显示或诊断数据,请不要使用它们作为注册表或出版商证明.
客户端要求能力
每个转发的请求都需要一个最新的信息_meta包裹:
{
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/clientInfo": {
"name": "enterprise-gateway",
"version": "1.0.0"
}
}通过后端,不要盲目复制外部客户端功能.门户端是后端客户端. 广告只能具有门户端正确的调解功能.
确定性名称空间
合并后端工具以稳定的公共名称:
notes.search
notes.create
issues.list
issues.open保持一个地图从公众名称到后端和原始工具名称. 永远不要选择第一个或最后的碰撞. 公众名称是批准和审计合同的一部分,所以更改它是一个迁移.
tools/list显度因主体而异时,返回cacheScope: private没有任何限制.ttlMs减少后端发现负载,而不会允许用户特定列表在授权环境中泄露.
每个暴露的工具描述符都包含一个稳定的名称,描述和对象根inputSchema名称空间不能删除所需的描述字段.完整列表结果还包括resultType服务器身份元数据,以及缓存提示.
印批准的描述符
在入学时,将完整的描述符归类为法典,并将其消化器存储在合格的公众名称下.在列表和电话时间,将现场描述器与批准的消化器进行比较.
如果变化:
- 删除它
tools/list现在,我们要去. - 拒绝直接电话.
- 发出审计活动.
- 需要在更新之前重新批准政策或人类.
网关是一个有用的中央执行点,但它不会使一条第一次看到的描述符成为安全的描述符.
登记文件帮助发现,而不是决定
一个注册书server.json提供出版元数据. 包装支持的记录可以看起来像这样:
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
"name": "com.example/notes",
"description": "Example notes MCP server.",
"version": "1.0.0",
"packages": [
{
"registryType": "npm",
"identifier": "@example/notes-mcp",
"version": "1.0.0",
"transport": {"type": "stdio"}
}
]
}发布元数据不包含网关的安全决定. 保存经验证的出版商和来源证据在单独的录取状态:
{
"registryName": "com.example/notes",
"registryVersion": "1.0.0",
"publisher": {"namespace": "com.example", "status": "verified"},
"provenance": {
"source": "registry.modelcontextprotocol.io",
"recordId": "com.example/notes@1.0.0"
},
"admission": {"status": "approved", "reviewedBy": "gateway-policy"}
}门口检查了server.json通过通过该网关,我们可以将其与外部状态联系起来.
对于每一个被允许的后端,记录:
- 记录和记录的确切标识.
- 经过验证的出版商名字空间或域名证据.
- 允许运输和终点.
- 嵌版本或批准的升级政策.
- 艺术品或描述器消化.
- 授权发行人和资源.
- 审核,批准时间,和过期.
由于其显示名称类似于熟悉的产品,所以不要接受服务器.不要把登记器存在视为运营安全审查.即使它们从未出现在公开登记器中,也可以通过相同的证据方案接入私人服务器.
这一课实现了门口接:在后端成为可路由之前,将出版证据与本地录取相结合. Lesson 30: MCP Registry Supply Chain, Admission, Drift, and Rollback建立完整的控制平面,以确定名称空间的确切性,文物来源,不可变的针头,直播描述器漂移,登记处状态调整,具有明显的录取账本和证据支持的反转.保持供应链状态与上述按要求运行时间决定分开.
权证调解
后端的身份证件从未传递给客户端.
保持这些义务明确:
outer principal -> gateway role and policy
backend issuer + resource -> backend registration and token永远不要将外部门口代币传递给后端.永远不要在不同的发行商或资源中重复使用后端代币.如果工具代表最终用户,则用设计的交易或索赔模型保存该代权,而不是用共享服务凭证伪装用户.
没有会议的定位限制
通过认证的资本,发行人,资源,公共工具,成本类别和时间窗口的关键限制. 会议ID是缺失的,即使存在,也很容易旋转.
在消耗昂贵的工作之前,请使用廉价验证.
审计决策链
记录足以重建电话:
- 要求和追踪标识符.
- 证实资本和发行人
- 公共工具和后端路线.
- 描述器印版本.
- 政策决定和理由.
- 延迟和结果类.
- 适用时MRTR轮或任务标识符.
编辑代码,授权代码,更新代码,原始秘密和不必要的敏感论点.
根据要求进行的SSE
当一个请求中工作流时,正常的POST可能会返回请求-scopeed SSE.关闭响应流会取消飞行中现代HTTP请求.
别创建一个独立的GET流,不要承诺重播最后事件ID.
长期变化通知
对于列表和资源更改通知,当前客户端发送subscriptions/listen通知过器使用精确的平面字段 toolsListChanged现在promptsListChanged现在resourcesListChanged其他resourceSubscriptions其他:
{
"jsonrpc": "2.0",
"id": "listen-tools",
"method": "subscriptions/listen",
"params": {
"notifications": {
"toolsListChanged": true
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}首先,确认支持的子集.其订阅标识符是开放流的请求的JSON-RPC id:
{
"jsonrpc": "2.0",
"method": "notifications/subscriptions/acknowledged",
"params": {
"_meta": {
"io.modelcontextprotocol/subscriptionId": "listen-tools"
},
"notifications": {
"toolsListChanged": true
}
}
}接下来,网关只传输确认的变更类型.io.modelcontextprotocol/subscriptionId在params._meta没有自动重播或自动重听.重连接后,客户端重新打开订阅并更新其依赖的列表.服务器启动的优雅闭幕返回最终完整结果,标记为相同的订阅ID.
现代道路取代了resources/subscribe现在resources/unsubscribe保持这些只在一个版本封闭的旧路径.
通过门口的MRTR
当一个后端回来时resultType: input_required通过输入,网关只能转发该结果,如果外部客户端支持所需的输入请求.requestState字节对字节,除非门户故意终止并重新发行互动.
客户端将使用新 JSON-RPC ID 重新尝试原始公共工具inputResponses网关重新授权重新尝试,检查相同的公共路线,然后发送新的后端请求. 它不能假设一个早些时候获得无限批准.
任务扩展路由
任务是官方扩展,io.modelcontextprotocol/tasks它们不是一个核心会议的替代品.
客户端声明扩展在每次请求客户端功能内,门口只在能够保存生命周期终端时将其公布在发现中.tools/call后端单独决定是否返回普通结果resultType: task任务结果带有taskId现在status时间,ttlMs其他选择性pollIntervalMs任务必须在发送结果之前已经可读.
后者是: 通过该网关记录了不透明任务识别器的认证主和后端路线.tasks/get现在tasks/update其他tasks/cancel电话使用params.taskId作为Mcp-Name通过此, 提供了路由密钥.tasks/get收益resultType: complete输入到终端状态的终端结果或协议错误. tasks/update发送钥匙inputResponses对于未完成任务输入,返回一个空白的完整确认. tasks/cancel合作的意图是完全承认的,而不是保证工作停止.
不要实施新的tasks/list或tasks/result需要输入的任务将通过 系统中包含的请求进行解明.tasks/get客户通过回复tasks/update客户端仍然在建议的间隔中进行投票;任务创建仍然是服务器导向的.
持久任务路径状态是应用程序数据,由任务处理器键化,而不是协议会议.
兼容性界限
如果网关必须为旧客户端或后端服务:
- 显然可以探测到时代.
- 保存初始化,运输会议,GET流,资源订阅和旧任务词汇在旧适配器中.
- 永远不要将旧的会议身份证泄露到现代路由或授权中.
- 宁愿有限于发现探测器和明确的反弹政策,
建立它
code/main.py通过程序中协议网关和两个后端服务器实现.每个后端都收到一个新的当前协议请求.tools/list名称间路由,登记server.json另外,外接状态,描述符,RBAC,主要关键利率限制,审计决定以及一个模型subscriptions/listen证实安全性.
该模型接收解析请求体,路由标题和认证的载体身份.它不是完整的HTTP适配器,也不解析Content-Type或是全部Accept连接到第09课的流向HTTP适配器,Content-Type: application/json其他Accept含有两者中的值application/json其他text/event-stream现在,我们要去.
运行它:
cd phases/13-tools-and-protocols/17-mcp-gateways-and-registries
python3 code/main.py
python3 -m unittest discover code/tests -v演示程序将打印外部请求 ID 和新版本的后端请求 ID,
用它
换取实时协议客户端的进程后端对象.保持相同的连接:
- 在连接前的录取记录.
- 在能力曝光之前的后端发现.
- 在授权之前的合格公众名称.
- 在列表或电话之前,点描述符.
- 在转发前,每次请求的新型元数据.
- 在返回之前验证结果.
运送它
这一课是很好的.outputs/skill-gateway-bootstrap.md它生产了一个现代化的门户设计,涵盖入口,发现,录取,命名空间,授权,缓存,流媒体,订阅,MRTR,任务,可观察性和遗产隔离.
运动
- 添加跟踪文本到外部和转发的请求元数据,并记录在审计事件中相关性.
- 添加一个可执行任务的后端和路线
tasks/get按任务IDMcp-Name现在,我们要去. - 改变一个后端描述符,证明发现和直接调用都被阻止了.
- 添加一个主要特定的服务器功能,并解释为什么发现必须保持私密缓存.
- 写一个旧的适配器界面,而不需要添加任何旧状态到现代的
Gateway课程.
关键词
| Term | Meaning |
|---|---|
| MCP gateway | Policy and routing server between clients and backend MCP servers |
| Admission record | Evidence and policy decision allowing one backend into the gateway |
| Qualified tool name | Stable public route such as notes.search |
| Descriptor pin | Approved digest checked during discovery and dispatch |
| Private cache scope | Cached result restricted to one authorization context |
| Request-scoped SSE | Streaming response attached to one POST request |
subscriptions/listen | Client-opened SSE stream for selected long-lived change notifications |
| Task route | Application mapping from an opaque task id to its backend |
| Legacy adapter | Explicit version-gated boundary for old handshake and session behavior |
进一步阅读
- Streamable HTTP transport
- Server discovery
- Official Registry server.json requirements
- MCP Tasks extension
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.