Skip to main content
Glama

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_bookscheckout_book

允许模型触发计算或副作用

Structured Output

Pydantic 返回模型

同时生成 outputSchemastructuredContent

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 自动发现并兼容旧协议

Related MCP server: BooksAPI-MCP

代码地图

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

建议按 domain.pyserver.pyclient_demo.pytests 的顺序阅读。

环境与安装

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

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

也可以使用 uv:

uv sync

确认解释器与 SDK:

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

最快体验:进程内 Client

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

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

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

stdio 传输

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

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

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

{
  "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 传输

终端一:

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

终端二:

$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 和手动发起调用:

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/discoverclient.protocol_version 可查看协商结果。

  • 现代协议没有长期会话和服务端主动回调通道。

  • Resolve(...) 可把 elicitation 变成多轮请求结果,在新旧协议中使用同一套工具实现。

  • 旧式 ctx.elicit()、sampling、roots 和协议级 logging 属于旧协议时代能力;学习遗留系统时仍会遇到,但不应作为新项目主路径。

错误处理与安全

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

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

运行测试

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 的客户端结果和服务端日志。

参考资料

Available Tools

4 tools
audit_inventory盘点库存A
Read-onlyIdempotent

模拟耗时盘点,并逐步报告进度

ParametersJSON Schema
NameRequiredDescriptionDefault
delay_secondsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, and the description adds value by stating that the operation is simulated, time-consuming, and reports progress incrementally. This is consistent with the annotations and gives the agent a clear sense of runtime and output behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single efficient sentence that states what the tool does and its key behavioral trait. No filler or redundant information is present.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema, annotations, and a single self-explanatory parameter, the description is mostly sufficient for a simple simulation tool. However, it omits explicit guidance on how the progress reporting is delivered and when an agent should choose this tool over siblings.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description does not explicitly explain delay_seconds. However, the phrase '耗时盘点' implies the delay parameter controls simulated duration, and the parameter name plus default value make its purpose reasonably inferable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('simulate') and resource ('inventory count'), and adds the distinct behavior of reporting progress step by step. This clearly separates audit_inventory from the book-focused siblings search_books, checkout_book, and return_book.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for simulating an inventory audit, but it does not state when to use it versus alternatives, nor does it mention any exclusions or preconditions. An agent must infer usage context from the word 'simulate'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

checkout_book借阅图书A

借阅一本可用图书;执行前必须由用户确认

ParametersJSON Schema
NameRequiredDescriptionDefault
book_idYes
member_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
book_idYes
loan_idYes
member_idYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a non-read-only, non-destructive mutation. The description adds a meaningful behavioral guardrail—user confirmation is mandatory before execution—which is not available from annotations or schema alone. It does not detail side effects like inventory changes, but the availability wording partially implies them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single compact sentence with the action stated first and the confirmation requirement after. No filler, repetition, or unnecessary detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter checkout tool with an output schema and annotations, the description is nearly complete. It could be improved by stating what happens if the book is unavailable or how confirmation is elicited, but these are not essential for basic invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not explicitly explain the roles of book_id and member_id. However, the parameter names are self-explanatory, and 'available book' implies book_id should refer to a borrowable copy, so there is minimal but useful implicit guidance.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific action, '借阅' (checkout), with a clear resource, '一本可用图书' (an available book), which distinguishes it from sibling tools like return_book, search_books, and audit_inventory. It also adds a condition beyond the title: the book must be available.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear execution context: borrow an available book, and user confirmation is required before execution. It does not explicitly name alternatives or when-not-to-use cases, but the domain and sibling tool names make the intended usage reasonably clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

return_book归还图书A
Idempotent

根据借阅单归还图书;重复调用结果不变

ParametersJSON Schema
NameRequiredDescriptionDefault
loan_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
statusYes
book_idYes
loan_idYes
member_idYes

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, and the description restates idempotency ('重复调用结果不变') without adding new behavioral context such as side effects on book availability, permissions required, or error behavior. The description does not contradict annotations, but it also does not enrich the safety profile beyond what structured data provides.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence with no filler. It front-loads the core action ('根据借阅单归还图书') and appends the idempotency note, which is directly relevant. Every word contributes meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter tool with output schema and annotations covering idempotency and non-destructiveness, the description is mostly sufficient. It lacks explicit mention of error cases or prerequisites (e.g., loan must exist and be active), but the simplicity of the tool and the supporting structured data make it reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides only the bare parameter name loan_id with no description, and schema description coverage is 0%. The description's '借阅单' (loan slip) gives a hint that loan_id references a loan slip, adding a small amount of meaning beyond the schema. However, it does not explain the format, where to obtain it, or how it relates to the returned book, leaving the agent partially in the dark.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb (归还/return) and resource (图书/book), and clarifies the basis (借阅单/loan slip). It clearly distinguishes itself from sibling tools like checkout_book by representing the inverse operation, and from search_books and audit_inventory which do not mutate loans.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied: a book is returned after being checked out, using the loan slip. However, there is no explicit guidance about when to use this tool versus alternatives, nor any mention of prerequisites such as the loan being active or already returned. The route to the right tool is obvious from the name and description but not spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_books搜索图书A
Read-onlyIdempotent

按标题、作者或标签搜索书目

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
booksYes
queryYes
totalYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds meaningful behavioral context by specifying that the search operates on title, author, or tag fields, which goes beyond the schema's simple 'query' string. It does not disclose pagination or result ordering, but this is minor for a simple search tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, compact sentence that delivers the essential information immediately. Every word earns its place and there is no redundant or filler content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter search tool with an output schema and safety-revealing annotations, the description provides sufficient context to call the tool correctly. The search criteria are specified, required parameters are evident from the schema, and the output schema covers return values. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the underspecified 'query' parameter. It does so by clarifying that query can be a title, author, or tag. However, it does not explain the 'limit' parameter at all; although the default value provides some hint, the description leaves that semantic gap open.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('search') with a clear resource ('book catalog/bibliography') and explicitly lists the searchable criteria (title, author, or tag). This makes it easily distinguishable from the sibling tools, which are mutations or inventory audits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies this tool is for finding books by title, author, or tag, which sets context against the mutation siblings (checkout_book, return_book). It does not explicitly state when not to use it or provide alternative selection criteria, but the sibling names make the distinction obvious enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.1/5.0
Disambiguation5/5

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

Naming Consistency5/5

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

Tool Count5/5

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

Completeness3/5

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

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    A
    quality
    D
    maintenance
    A demo server that allows AI models to manage a personal reading list stored in a local SQLite database. It provides tools for searching, adding, and updating books while demonstrating core Model Context Protocol features like resources and tools.
    5
  • F
    license
    Not graded
    quality
    D
    maintenance
    A foundational implementation of a Model Context Protocol (MCP) server designed for educational purposes. It demonstrates the complete interaction between an LLM, an inference engine, and a client during an agentic call.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/debuger00/MCPdemo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server