Skip to main content
Glama
README.md
# MCP Library Lab

这是一个面向学习者的 MCP(Model Context Protocol)完整示例。它不是生产级图书系统,而是一间足够小、可以逐行读懂的“教学图书馆”。

项目使用官方 Python SDK `mcp 2.x` 和 MCP `2026-07-28` 协议。服务端同时兼容旧握手协议客户端。

## 你能学到什么

| MCP 概念 | 本项目中的位置 | 作用 |
|---|---|---|
| Server / Client | `server.py` / `client_demo.py` | 能力提供方与能力消费方 |
| Tools | `search_books`、`checkout_book` 等 | 允许模型触发计算或副作用 |
| Structured Output | Pydantic 返回模型 | 同时生成 `outputSchema` 和 `structuredContent` |
| Tool Annotations | 每个 `@server.tool` | 声明只读、幂等、破坏性和开放世界提示 |
| Resources | `library://catalog` | 应用控制的只读上下文 |
| Resource Templates | `library://books/{book_id}` | 带参数的资源 URI |
| Prompts | `make-research-plan` | 可发现、可参数化的消息模板 |
| Elicitation | `Resolve(ask_checkout_approval)` | 绕过模型,直接向用户确认敏感操作 |
| Progress | `audit_inventory` | 长任务进度通知 |
| Errors | `ToolError` | 区分可公开业务错误与内部异常 |
| Transports | in-process、stdio、Streamable HTTP | 测试、本地宿主和网络部署 |
| Discovery | `list_tools/resources/prompts` | 客户端运行时能力发现 |
| Protocol negotiation | `client.protocol_version` | v2 自动发现并兼容旧协议 |

## 代码地图

```text
src/mcp_library/
├── domain.py       # 纯业务层,不依赖 MCP
├── server.py       # MCP 能力注册与两种传输入口
└── client_demo.py  # 发现、读取、调用、确认和进度处理
tests/
└── test_server.py  # 使用进程内传输的协议集成测试
```

建议按 `domain.py` → `server.py` → `client_demo.py` → `tests` 的顺序阅读。

## 环境与安装

本仓库当前验证环境是 Python 3.13 和 `mcp 2.1.1`。使用当前终端的 Python 安装:

```powershell
python -m pip install -e ".[dev]"
```

也可以使用 uv:

```powershell
uv sync
```

确认解释器与 SDK:

```powershell
python -c "import sys, mcp; print(sys.executable); print(mcp.__file__)"
python -m pip show mcp
```

## 最快体验:进程内 Client

不启动端口,Client 与 Server 仍经过完整的 MCP 类型和分发层:

```powershell
$env:PYTHONPATH = "src"
python -m mcp_library.client_demo
```

这个演示会依次完成协议协商、能力发现、资源读取、工具调用、Prompt 获取、借阅确认,以及盘点进度通知。

## stdio 传输

stdio 适合 Claude Desktop、Codex 等本地宿主拉起子进程。协议消息走标准输入输出,因此服务端不要向 stdout 随意 `print`,日志应写 stderr。

```powershell
$env:PYTHONPATH = "src"
python -m mcp_library.server --transport stdio
```

客户端配置示例(路径按实际解释器修改):

```json
{
  "mcpServers": {
    "teaching-library": {
      "command": "E:\\aaa_SpecializedSoftware\\MiniConda\\envs\\python_3_13\\python.exe",
      "args": ["-m", "mcp_library.server", "--transport", "stdio"],
      "cwd": "E:\\program\\agent\\0000personal-projects\\08MCP",
      "env": {"PYTHONPATH": "src"}
    }
  }
}
```

## Streamable HTTP 传输

终端一:

```powershell
$env:PYTHONPATH = "src"
python -m mcp_library.server --transport streamable-http --host 127.0.0.1 --port 8000
```

终端二:

```powershell
$env:PYTHONPATH = "src"
python -m mcp_library.client_demo --url http://127.0.0.1:8000/mcp
```

网络部署时需要进一步增加 HTTPS、认证、Host/Origin 校验、限流、超时和持久化存储。本项目只监听 `127.0.0.1`,不应直接暴露到公网。

## 使用 MCP Inspector

服务启动后,可用 Inspector 检查 schema 和手动发起调用:

```powershell
npx -y @modelcontextprotocol/inspector
```

连接 Streamable HTTP 地址 `http://127.0.0.1:8000/mcp`。Inspector 是独立的 Node 工具,因此首次运行需要 Node.js 和联网下载。

## 三种原语如何选择

- Tool:模型决定何时调用;适合搜索、计算、写入或外部 API。
- Resource:应用决定何时提供;适合文件、记录、配置和稳定上下文。
- Prompt:用户或应用选择模板;适合固化高质量工作流提示。

不要仅因为某个 Python 函数容易写,就把它注册成 Tool。涉及写操作时应最小化权限、明确注解,并在真正执行前确认。

## v2 协议值得注意的变化

- `FastMCP` 在 SDK v2 中更名为 `MCPServer`。
- 默认 Client 会先尝试 `server/discover`;`client.protocol_version` 可查看协商结果。
- 现代协议没有长期会话和服务端主动回调通道。
- `Resolve(...)` 可把 elicitation 变成多轮请求结果,在新旧协议中使用同一套工具实现。
- 旧式 `ctx.elicit()`、sampling、roots 和协议级 logging 属于旧协议时代能力;学习遗留系统时仍会遇到,但不应作为新项目主路径。

## 错误处理与安全

SDK 会隐藏普通未处理异常,只向客户端返回通用工具错误,以免泄露堆栈或内部数据。可预期、可以公开的业务错误应转换为 `ToolError`。不要把密钥、数据库异常或内部路径放进 `ToolError`。

`ToolAnnotations` 是给客户端和模型的提示,不是权限控制。生产环境仍需独立实现身份认证、授权、参数校验、审计和速率限制。

## 运行测试

```powershell
python -m pytest -q
```

测试不占用端口,覆盖能力发现、结构化输出、参数化资源、elicitation、副作用、进度通知和错误结果。

## 推荐练习

1. 增加 `library://loans/{member_id}` 资源模板。
2. 为搜索加入游标分页,并观察 list API 自身的分页结构。
3. 把内存 `Library` 替换为 SQLite,同时保持 MCP 层不变。
4. 给 HTTP 服务增加 OAuth 资源服务器配置。
5. 编写一个会拒绝借阅的 elicitation callback,并断言库存不变化。
6. 人为抛出普通异常,对比它与 `ToolError` 的客户端结果和服务端日志。

## 参考资料

- [MCP 官方文档](https://modelcontextprotocol.io/)
- [官方 Python SDK](https://github.com/modelcontextprotocol/python-sdk)
- [MCP Inspector](https://github.com/modelcontextprotocol/inspector)

TDQS

A4.1/5.0

Scored across 4 tools

Disambiguation5/5

每个工具对应一个独立且清晰的动作:搜索、借出、归还、盘点,边界分明,无功能重叠,代理可以轻松区分选择。

Naming Consistency5/5

所有工具均采用小写snake_case且遵循动词_名词模式,如search_books、checkout_book,命名风格高度一致,可预测性强。

Tool Count5/5

4个工具数量精简,每个工具都在借阅流程中扮演必要角色,没有冗余,符合教学库的定位和范围。

Completeness3/5

核心借阅工作流(搜索、借出、归还)已覆盖,但缺少图书的增删改以及查看当前借阅列表等基本管理操作,存在明显但非致命的覆盖缺口。

Maintenance

ActivityMaintained
ResponsivenessNo issues