# MCP 资源订阅教程：文件更新后接收通知，取消订阅后停止推送

MCP SDK stdio服务与客户端已实跑资源订阅、更新通知、未订阅URI隔离与取消后不新增通知；未调用LLM。

## 环境

- Python 3.12+；在 reference 中 pip install -r requirements.txt。

## 启动

~~~sh
cd reference
python3 verify.py
# 运行后查看原生结果阅读器（读取records.json）
python3 -m http.server 8787
# 打开 http://127.0.0.1:8787/report.html
~~~

## 七步操作

1. 启动原生服务

下载 server.py 与 verify.py，安装锁定的 MCP Python SDK。服务通过 stdio 运行在独立子进程，提供 exercise://notes/a 和 b 两个资源，不连接真实工作文件或模型。

2. 声明订阅能力

本题采用与2025-11-25资源规范对应的 SDK 1.25.0 接口。初始化明确声明 resources.subscribe；仅有 resources/list 并不代表客户端可以假设订阅一定受支持。

3. 订阅指定资源

客户端先读取 a 的 version 1，再发送 resources/subscribe。URI 是订阅键；a 与 b 必须保持独立，工具调用只是本题用来触发本地版本变化的入口。

4. 修改并收通知

先更新未订阅的 b，确认没有通知；再更新 a，原生 ClientSession 的 message handler 收到一次 resources/updated。通知只给出发生变化的 URI，需要另行读取内容。

5. 取消后再修改

调用 resources/unsubscribe 后再更新 a。已经收过的历史通知不会从日志中消失，但本次不应多收到一条；应比较通知数量的增量，而不是要求日志清空。

6. 主动回读新版

取消订阅不撤销读取权限。客户端主动 read_resource 仍能得到 version 3，这与“服务器仍在推送”是两件不同的事。

7. 复跑客户端

运行 python3 verify.py，回读初始化能力、订阅更新、未订阅资源和取消后行为。这里实际执行的是 SDK 服务与客户端，没有调用聊天模型，也没有把固定通知数组当作协议执行。

## 目录身份

- starter：待完成的任务接口与原创输入，TODO不是已完成实现。
- reference：作者原生完成参考和实际产物。records.json/browser-result.json为本地实测记录，不是AI助手回复。
- TASK.md：可交给相应AI助手的原始任务合同。该助手账号生成会话未运行。

## 依赖与许可

原创教学代码以MIT许可提供。第三方项目、模型及浏览器遵循其自身许可。第三方依赖由本地安装获取，不包含node_modules、模型权重、WASM运行时、数据库、缓存或凭据。

## 官方依据

- https://modelcontextprotocol.io/specification/2025-11-25/server/resources
