mcp-notas
mcp-server-example — MCP-сервер для базы заметок в Markdown
Пример MCP (Model Context Protocol) сервера — рабочий и протестированный, — который даёт ассистенту доступ к second brain: локальному каталогу заметок в Markdown, которые он может создавать, читать, обновлять, перечислять, искать и измерять.
Здесь важен не объём возможностей, а показ честного MCP-сервера: схемы, генерируемые из type hints, настоящая санитизация против path traversal и набор тестов, которые вызывают инструменты по-настоящему, а не имитируют вызов.
Что такое MCP
Model Context Protocol — это открытый протокол, стандартизирующий то, как ассистент общается с внешними системами. Вместо того чтобы каждое приложение изобретало собственный формат плагинов, MCP-сервер объявляет три вещи — tools (действия, которые модель может выполнять), resources (данные, которые она может читать, адресуемые по URI) и prompts (шаблоны разговора, которые может вызывать пользователь) — и любой совместимый клиент сам обнаруживает и использует всё это. Связь идёт по JSON-RPC, обычно через stdio: клиент запускает сервер как подпроцесс и обменивается сообщениями через стандартный ввод и вывод.
Related MCP server: Notes MCP Server
Что здесь есть
Файл | Что делает |
| Определяет сервер |
| Весь ввод-вывод на диск и санитизация идентификаторов. Единственная точка сборки путей. |
| Текстовый поиск с ранжированием по полям (заголовок > теги > тело), без учёта акцентов. |
| Точка входа для |
| 45 тестов, которые по-настоящему упражняют сервер, включая полную MCP-сессию. |
| Зависимости для рантайма и для тестов. |
| Конфигурация |
Каждая заметка — это файл .md с минимальным front matter:
---
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, иClientSessionиз самого SDK завершил handshake по stdio, перечислил tools и выполнил вызовы (см. «Статус проверки»). Перевод этого handshake в формат конфигурации конкретного клиента не отрабатывался.
Пример использования
Реальные выводы, снятые при запуске сервера in-process (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.И реальный handshake по stdio, с сервером, работающим как подпроцесс, и ClientSession
из SDK на другой стороне (дословный вывод, без 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-сервера, работающего с файлами, — принять идентификатор от модели и
склеить его прямо с путём: 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(), и код проверяет, что его родитель — это в точности
каталог базы. Эта проверка избыточна по построению — и в этом суть: если когда-нибудь в
первом слое появится дыра, утечка всё равно не произойдёт.
Каноническая атака, реально выполненная против tool:
>>> 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), а
percent-encoded форма notas://..%2F..%2Fetc%2Fpasswd соответствует, доходит до санитизации
и блокируется там — именно этот второй, опасный случай покрыт тестом.
Тест также доказывает в файловой системе, что цель атаки не создаётся: после попытки
criar_nota со slug="../vazamento" каталог базы остаётся пустым, а файл вне его
не существует.
Кроме того: никаких ключей API, никакого сетевого доступа, и сервер никогда не читает и не пишет за пределами настроенного каталога.
Тесты
$ python3 -m pytest tests/ -q
............................................. [100%]
45 passed in 1.48sТолько тесты path traversal:
$ 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, и схемы (required,type,default,outputSchema) — это сгенерированные из type hints и docstrings.Реальный вызов каждой tool — создание с проверкой сохранения на диске, дубликат, чтение, чтение несуществующей, обновление, обновление с
anexar, список с фильтром по тегу и без, поиск с ранжированием и с лимитом, статистика и удаление.Resources —
list_resources,list_resource_templates, чтение JSON-индекса, чтение отдельной заметки и обе формы traversal.Prompts —
list_prompts,get_promptдля обоих промптов, с проверкой, что содержимое заметки действительно встроено и что исходная заметка не появляется в каталоге остальных.Сквозная сессия —
create_connected_server_and_client_sessionподнимает MCP-клиента и сервер, соединённых в памяти; тест перечисляет tools, создаёт заметку, перечисляет, читает resource, получает prompt и подтверждаетisError: Trueпри попытке traversal.Изолированное хранилище — round-trip 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-сессия клиент↔сервер в памяти через
mcp.shared.memory.create_connected_server_and_client_session.Реальный stdio-handshake: сервер поднят как подпроцесс (
python3 -m mcp_notas), иClientSessionиз SDK выполнил через негоinitialize,list_toolsиcall_tool.Path traversal отклонён в
sanitizar_slug, в tool, в resource и в файловой системе.MCP_NOTAS_DIRсоблюдается: созданная заметка появилась в каталоге, указанном переменной.Все выводы, показанные в этом README, скопированы из реальных запусков.
⚠️ Не проверено
Блок
mcpServersне проверялся против реального MCP-клиента (Claude Desktop, редакторы и т.д.). В этом окружении нет ни одного установленного клиента; эту проверку заменяет программный stdio-handshake, описанный выше.Транспорты
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