mcp-notas
mcp-server-example — 用于 Markdown 笔记库的 MCP 服务器
一个功能完整且经过测试的示例 MCP(Model Context Protocol) 服务器,为助手提供对 第二大脑 的访问:一个本地 Markdown 笔记目录,助手可以对其执行创建、读取、更新、列出、搜索和统计操作。
这里的重点不在于功能数量,而在于展示一个诚实的 MCP 服务器:从类型提示生成的 schema、真正针对路径遍历的消毒处理,以及一套真实调用工具而非模拟调用的测试套件。
什么是 MCP
Model Context Protocol 是一个开放协议,它标准化了助手与外部系统对话的方式。与其让每个应用发明自己的插件格式,MCP 服务器声明三样东西——tools(模型可以执行的操作)、resources(模型可以通过 URI 寻址读取的数据)和 prompts(用户可以调用的对话模板)——任何兼容的客户端都能自动发现并使用所有这些。通信采用 JSON-RPC,通常通过 stdio:客户端将服务器作为子进程启动,并通过标准输入输出交换消息。
Related MCP server: Notes MCP Server
这里有什么
文件 | 作用 |
| 定义 |
| 所有磁盘 I/O 和标识符消毒处理。唯一拼接路径的地方。 |
| 按字段(标题 > 标签 > 正文)排序的文本搜索,不区分重音。 |
|
|
| 45 个测试,真实运行服务器,包括一个完整的 MCP 会话。 |
| 运行时和测试依赖。 |
|
|
每条笔记都是一个带最小 front matter 的 .md 文件:
---
title: Teste env
tags: []
created: 2026-08-25T00:20:24+00:00
updated: 2026-08-25T00:20:24+00:00
---服务器暴露了什么
Tools
Tool | 参数 | 返回 |
|
| 创建的笔记,日期已填充。 |
|
| 完整笔记(正文、标签、日期)。 |
|
| 已更新的笔记。 |
|
| 文本确认信息。 |
|
| 总数和每条笔记的摘要,不含正文。 |
|
| 按相关性排序的结果,带片段。 |
| — | 计数、最常用标签、最长笔记。 |
Resources
URI | 类型 | 内容 |
|
| 整个笔记库的索引:每条笔记的 slug、标题、标签和 URI。 |
|
| 一条笔记的完整 Markdown,含 front matter。 |
Prompts
Prompt | 参数 | 组装内容 |
|
| 一个摘要请求,笔记内容已内嵌其中。 |
|
| 四条消息:指令、起始笔记、其余笔记的目录以及助手的开场白。 |
安装
git clone <url-do-repositorio> mcp-server-example
cd mcp-server-example
pip install -r requirements.txt需要 Python 3.11+ 和 mcp >= 1.27.0。
如何运行
默认传输方式是 stdio——MCP 客户端就是这样启动服务器的:
cd mcp-server-example
python3 -m mcp_notas进程会保持静默,等待标准输入上的 JSON-RPC 消息;这是正确行为,不是卡死。
笔记库目录可通过环境变量 MCP_NOTAS_DIR 配置(默认:./notas,自动创建):
MCP_NOTAS_DIR=~/meu-second-brain python3 -m mcp_notas客户端配置
可直接粘贴到 MCP 客户端配置中的代码块:
{
"mcpServers": {
"notas": {
"command": "python3",
"args": ["-m", "mcp_notas"],
"cwd": "/caminho/absoluto/para/mcp-server-example",
"env": {
"MCP_NOTAS_DIR": "/caminho/absoluto/para/suas-notas"
}
}
}
}⚠️ 此代码块未在此环境中针对真实 MCP 客户端测试过。 这里实际验证的是程序化等价物:服务器以
python3 -m mcp_notas作为子进程启动,SDK 自带的ClientSession通过 stdio 完成了握手、列出了 tools 并执行了调用(见"验证状态")。该握手到特定客户端配置格式的转换未经过实际测试。
使用示例
真实输出,通过进程内运行服务器(criar_servidor() + call_tool)捕获。diretorio 字段已替换为通用路径;其余为字面输出。
>>> criar_nota
{
"slug": "protocolo-mcp",
"titulo": "Protocolo MCP",
"tags": [
"mcp",
"protocolo"
],
"corpo": "O Model Context Protocol padroniza como um assistente acessa ferramentas e dados externos.",
"criada_em": "2026-08-25T00:20:03+00:00",
"atualizada_em": "2026-08-25T00:20:03+00:00"
}
>>> listar_notas(tag='mcp')
{
"total": 1,
"filtro_tag": "mcp",
"notas": [
{
"slug": "protocolo-mcp",
"titulo": "Protocolo MCP",
"tags": [
"mcp",
"protocolo"
],
"atualizada_em": "2026-08-25T00:20:03+00:00",
"resumo": "O Model Context Protocol padroniza como um assistente acessa ferramentas e dados externos.",
"tamanho": 90
}
]
}
>>> buscar_notas(consulta='protocolo')
{
"consulta": "protocolo",
"total": 2,
"resultados": [
{
"slug": "protocolo-mcp",
"titulo": "Protocolo MCP",
"tags": [
"mcp",
"protocolo"
],
"pontuacao": 8.0,
"trecho": "O Model Context Protocol padroniza como um assistente acessa ferramentas e dados externos."
},
{
"slug": "memoria-de-longo-prazo",
"titulo": "Memória de longo prazo",
"tags": [
"produtividade"
],
"pontuacao": 1.0,
"trecho": "Anotações sobre second brain. Cita o protocolo de revisão semanal."
}
]
}注意排序:单词"protocolo"出现在第一条笔记的标题和标签中(得分 8.0),而只出现在第二条的正文中(得分 1.0)。
>>> estatisticas_base()
{
"total_de_notas": 2,
"total_de_caracteres": 156,
"total_de_palavras": 23,
"media_de_caracteres": 78.0,
"total_de_tags": 3,
"tags_mais_usadas": {
"mcp": 1,
"produtividade": 1,
"protocolo": 1
},
"nota_mais_longa": "protocolo-mcp",
"ultima_atualizacao": "2026-08-25T00:20:03+00:00",
"diretorio": "/caminho/para/notas"
}
>>> read_resource('notas://index')
{
"diretorio": "/caminho/para/notas",
"total": 2,
"notas": [
{
"slug": "memoria-de-longo-prazo",
"titulo": "Memória de longo prazo",
"tags": [
"produtividade"
],
"uri": "notas://memoria-de-longo-prazo"
},
{
"slug": "protocolo-mcp",
"titulo": "Protocolo MCP",
"tags": [
"mcp",
"protocolo"
],
"uri": "notas://protocolo-mcp"
}
]
}
>>> get_prompt('resumir_nota', {'slug': 'protocolo-mcp'})
Resuma em no máximo 3 bullets.
Não invente informação que não esteja na nota.
# Protocolo MCP
Tags: mcp, protocolo
O Model Context Protocol padroniza como um assistente acessa ferramentas e dados externos.以及通过 stdio 的真实握手,服务器作为子进程运行,SDK 的 ClientSession 在另一端(字面输出,不含服务器的 INFO 日志):
serverInfo: mcp-notas 1.27.0
instructions[:60]: Servidor de uma base local de notas em Markdown. Use 'listar
tools: ['apagar_nota', 'atualizar_nota', 'buscar_notas', 'criar_nota', 'estatisticas_base', 'ler_nota', 'listar_notas']
criar_nota isError: False slug: handshake-stdio
estatisticas: 1 nota(s)
traversal isError: True
traversal msg: Error executing tool ler_nota: Identificador inválido '../../etc/passwd': separadores de caminho não são permitidos. Use安全性
处理文件的 MCP 服务器的一个经典 bug 是接受来自模型的标识符并直接拼接到路径中:Path(base) / slug。当 slug = "../../etc/passwd" 时,这会把整个磁盘交给控制提示词的人。
这里的防御位于 mcp_notas/storage.py,有两层。
1. sanitizar_slug() — 白名单验证。 标识符只有在匹配 ^[a-z0-9][a-z0-9._-]{0,79}$ 时才能通过,在此之前会明确拒绝路径分隔符(/、\)、空字节、Windows 盘符(C:)以及任何 .. 出现。要求以字母或数字开头也排除了 .ssh 之类的隐藏名称。
2. BaseDeNotas.caminho() — 解析后路径的检查。 消毒之后,路径用 Path.resolve() 解析,代码确认其父目录恰好是笔记库目录。这个检查在构造上就是冗余的——而这正是重点:如果有一天第一层出现漏洞,数据泄露仍然不会发生。
针对该工具实际执行的经典攻击:
>>> call_tool('ler_nota', {'slug': '../../etc/passwd'})
ToolError: Error executing tool ler_nota: Identificador inválido '../../etc/passwd': separadores de caminho não são permitidos. Use apenas o slug da nota, sem diretórios.resource notas://{slug} 有同样的保护,而且通过两条不同的路径:原始 URI notas://../../etc/passwd 根本不匹配模板(Unknown resource),而百分号编码形式 notas://..%2F..%2Fetc%2Fpasswd 能匹配、到达消毒层并在那里被拦截——测试覆盖的正是这第二种危险情况。
还有一个测试在文件系统上证明攻击目标不会被创建:在尝试用 slug="../vazamento" 调用 criar_nota 之后,笔记库目录仍然为空,目录外的文件也不存在。
此外:没有 API 密钥,没有网络访问,服务器从不读取或写入配置目录之外的内容。
测试
$ python3 -m pytest tests/ -q
............................................. [100%]
45 passed in 1.48s仅路径遍历测试:
$ python3 -m pytest tests/ -q -k traversal
................. [100%]
17 passed, 28 deselected in 0.67s测试套件按顺序覆盖:
消毒处理 — 13 个参数化的恶意输入(
../../etc/passwd、/etc/passwd、..\\..\\windows\\system32\\config\\sam、C:\Windows\win.ini、nota\x00.md、空字符串……),外加磁盘上证明不会在笔记库之外创建任何内容的测试。MCP 表面 —
list_tools恰好返回七个 tools,schema(required、type、default、outputSchema)是从类型提示和 docstring 生成的。每个工具的真实调用 — 创建并在磁盘上验证持久化、重复创建、读取、读取不存在的笔记、更新、带
anexar的更新、带和不带标签过滤的列表、带排序和限制的搜索、统计和删除。Resources —
list_resources、list_resource_templates、读取 JSON 索引、读取单条笔记以及两种遍历形式。Prompts —
list_prompts、获取两个 prompt 的get_prompt,确认笔记内容确实被内嵌,且起始笔记不会出现在其他笔记的目录中。端到端会话 —
create_connected_server_and_client_session在内存中启动一个连接的 MCP 客户端和服务器;测试列出 tools、创建笔记、列出、读取 resource、获取 prompt,并确认遍历尝试时isError: True。隔离存储 — front matter 的往返测试,以及非笔记文件在列表中被忽略的测试。
验证状态
以下所有内容均在此环境中执行,使用 mcp 1.27.0、pytest 9.1.1 和 pytest-asyncio 1.4.0,Python 3.11。
✅ 已验证
python3 -m pytest tests/ -q→ 45 passed。七个 tools 通过
FastMCP.call_tool真实调用,结果已核对。两个 resources 通过
FastMCP.read_resource读取;两个 prompts 通过FastMCP.get_prompt获取。通过
mcp.shared.memory.create_connected_server_and_client_session在内存中完成完整的客户端↔服务器 MCP 会话。真实 stdio 握手:服务器作为子进程启动(
python3 -m mcp_notas),SDK 的ClientSession通过它执行initialize、list_tools和call_tool。路径遍历在
sanitizar_slug、工具、resource 和文件系统层面均被拒绝。MCP_NOTAS_DIR被遵守:创建的笔记出现在变量指向的目录中。本 README 中显示的所有输出均来自真实执行。
⚠️ 未测试
mcpServers代码块未针对真实 MCP 客户端测试过(Claude Desktop、编辑器等)。此环境中未安装任何客户端;替代此验证的是上述程序化 stdio 握手。sse和streamable-http传输方式存在于FastMCP.run中,但本项目只使用stdio。无并发测试:对同一笔记的并发写入没有通过锁协调。
未在 Windows 或 macOS 上测试——仅 Linux。
许可证
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceManages markdown notes in a specified directory, allowing users to create, read, update, and list notes through the Model Context Protocol.1
- AlicenseAqualityDmaintenanceEnables creating, managing, and searching Markdown notes with support for tags, timestamps, and full-text search. Includes AI prompts for analyzing and summarizing notes.61MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to search, read, create, update, and remove personal markdown notes stored locally, providing persistent memory across sessions.132MIT
- AlicenseAqualityCmaintenanceEnables AI assistants to interact with a local folder of Markdown notes, supporting listing, reading, searching, creating, and appending to notes with strict security boundaries.5MIT
Related MCP Connectors
AI access to your aNotepad online notes: read, search, write, and organize via 22 tools.
Read and write your Fresh Jots notes from Claude, Cursor, and any MCP client.
Create, validate, edit, export (markdown/svg/png/mermaid), and search JSON Canvas files.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/herickbrandao483-jpg/mcp-server-example'
If you have feedback or need assistance with the MCP directory API, please join our Discord server