mcp-notas
mcp-server-example — MCP-Server für eine Markdown-Notizdatenbank
Ein funktionsfähiger, getesteter Beispiel-MCP-Server (Model Context Protocol), der einem Assistenten Zugriff auf ein Second Brain gibt: ein lokales Verzeichnis mit Markdown-Notizen, das er erstellen, lesen, aktualisieren, auflisten, durchsuchen und messen kann.
Der Fokus liegt hier nicht auf der Menge der Funktionen, sondern darauf, einen ehrlichen MCP-Server zu zeigen: Schemas, die aus den Type Hints generiert werden, echte Sanitisierung gegen Path Traversal und eine Testsuite, die die Tools wirklich aufruft, statt den Aufruf zu simulieren.
Was ist MCP
Das Model Context Protocol ist ein offenes Protokoll, das standardisiert, wie ein Assistent mit externen Systemen kommuniziert. Statt dass jede Anwendung ihr eigenes Plugin-Format erfindet, deklariert der MCP-Server drei Dinge — Tools (Aktionen, die das Modell ausführen kann), Resources (Daten, die es lesen kann, adressiert per URI) und Prompts (Gesprächsvorlagen, die der Benutzer aufrufen kann) — und jeder kompatible Client entdeckt und nutzt all das von selbst. Die Kommunikation erfolgt über JSON-RPC, normalerweise über stdio: Der Client startet den Server als Subprozess und tauscht Nachrichten über die Standardeingabe und -ausgabe aus.
Related MCP server: Notes MCP Server
Was es hier gibt
Datei | Funktion |
| Definiert den |
| Das gesamte Datei-I/O und die Sanitisierung von Bezeichnern. Einziger Punkt, der Pfade zusammensetzt. |
| Textsuche mit Ranking nach Feld (Titel > Tags > Textkörper), akzentunabhängig. |
| Einstiegspunkt für |
| 45 Tests, die den Server wirklich ausüben, einschließlich einer vollständigen MCP-Sitzung. |
| Laufzeit- und Testabhängigkeiten. |
| Konfiguration von |
Jede Notiz ist eine .md-Datei mit einem minimalen Front Matter:
---
title: Teste env
tags: []
created: 2026-08-25T00:20:24+00:00
updated: 2026-08-25T00:20:24+00:00
---Was der Server bereitstellt
Tools
Tool | Argumente | Gibt zurück |
|
| Die erstellte Notiz mit ausgefüllten Daten. |
|
| Die vollständige Notiz (Textkörper, Tags, Daten). |
|
| Die bereits aktualisierte Notiz. |
|
| Textbestätigung. |
|
| Gesamtzahl und Zusammenfassung jeder Notiz, ohne den Textkörper. |
|
| Nach Relevanz sortierte Ergebnisse mit Ausschnitt. |
| — | Zählungen, am häufigsten verwendete Tags, längste Notiz. |
Resources
URI | Typ | Inhalt |
|
| Index der gesamten Basis: Slug, Titel, Tags und URI jeder Notiz. |
|
| Vollständiges Markdown einer Notiz, mit Front Matter. |
Prompts
Prompt | Argumente | Was zusammengestellt wird |
|
| Eine Zusammenfassungsanfrage mit dem bereits eingebetteten Inhalt der Notiz. |
|
| Vier Nachrichten: Anweisung, Ausgangsnotiz, Katalog der übrigen Notizen und die Eröffnung des Assistenten. |
Installation
git clone <url-do-repositorio> mcp-server-example
cd mcp-server-example
pip install -r requirements.txtErfordert Python 3.11+ und mcp >= 1.27.0.
So führen Sie es aus
Der Standardtransport ist stdio — so startet ein MCP-Client den Server:
cd mcp-server-example
python3 -m mcp_notasDer Prozess bleibt still und wartet auf JSON-RPC-Nachrichten auf der Standardeingabe; das ist das korrekte Verhalten, kein Absturz.
Das Basisverzeichnis ist über die Umgebungsvariable MCP_NOTAS_DIR konfigurierbar
(Standard: ./notas, wird automatisch erstellt):
MCP_NOTAS_DIR=~/meu-second-brain python3 -m mcp_notasKonfiguration im Client
Fertiger Block zum Einfügen in die Konfiguration eines MCP-Clients:
{
"mcpServers": {
"notas": {
"command": "python3",
"args": ["-m", "mcp_notas"],
"cwd": "/caminho/absoluto/para/mcp-server-example",
"env": {
"MCP_NOTAS_DIR": "/caminho/absoluto/para/suas-notas"
}
}
}
}⚠️ Dieser Block wurde in dieser Umgebung nicht gegen einen echten MCP-Client getestet. Was hier tatsächlich verifiziert wurde, ist das programmatische Äquivalent: Der Server wurde als Subprozess mit
python3 -m mcp_notasgestartet, und eineClientSessionaus dem SDK selbst hat den Handshake über stdio abgeschlossen, die Tools aufgelistet und Aufrufe ausgeführt (siehe „Verifizierungsstatus"). Die Übersetzung dieses Handshakes in das Konfigurationsformat eines bestimmten Clients wurde nicht erprobt.
Nutzungsbeispiel
Echte Ausgaben, aufgezeichnet beim Ausführen des Servers in-process (criar_servidor() +
call_tool). Das Feld diretorio wurde durch einen generischen Pfad ersetzt; der Rest ist
wörtlich.
>>> 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."
}
]
}Beachten Sie das Ranking: Das Wort „protocolo" steht im Titel und in den Tags der ersten Notiz (Punktzahl 8.0) und nur im Textkörper der zweiten (Punktzahl 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.Und der echte Handshake über stdio, mit dem Server als Subprozess und einer ClientSession
aus dem SDK auf der anderen Seite (wörtliche Ausgabe, ohne die INFO-Logs des Servers):
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. UseSicherheit
Der klassische Fehler eines MCP-Servers, der mit Dateien arbeitet, besteht darin, einen vom
Modell stammenden Bezeichner zu akzeptieren und ihn direkt in den Pfad zu verketten:
Path(base) / slug. Mit slug = "../../etc/passwd" wird so die gesamte Festplatte an
diejenigen ausgeliefert, die den Prompt kontrollieren.
Hier liegt die Verteidigung in mcp_notas/storage.py und hat zwei Schichten.
1. sanitizar_slug() — Validierung über eine Positivliste. Ein Bezeichner wird nur
durchgelassen, wenn er mit ^[a-z0-9][a-z0-9._-]{0,79}$ übereinstimmt, nachdem
Pfadtrennzeichen (/, \), Nullbyte, Windows-Laufwerksbuchstaben (C:) und jedes Vorkommen
von .. explizit abgelehnt wurden. Die Anforderung, mit einem Buchstaben oder einer Ziffer zu
beginnen, weist auch versteckte Namen wie .ssh ab.
2. BaseDeNotas.caminho() — Prüfung des aufgelösten Pfads. Nach der Sanitisierung wird der
Pfad mit Path.resolve() aufgelöst, und der Code prüft, dass sein Elternverzeichnis exakt das
Basisverzeichnis ist. Diese Prüfung ist konstruktionsbedingt redundant — und genau das ist der
Punkt: Sollte die erste Schicht jemals ein Loch haben, kommt es trotzdem nicht zum Leck.
Der kanonische Angriff, tatsächlich gegen das Tool ausgeführt:
>>> 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.Die Ressource notas://{slug} hat denselben Schutz, und zwar auf zwei verschiedenen Wegen: Die
rohe URI notas://../../etc/passwd passt nicht einmal auf die Vorlage (Unknown resource),
während die percent-encodierte Form notas://..%2F..%2Fetc%2Fpasswd passt, zur Sanitisierung
gelangt und dort abgewiesen wird — genau dieser zweite, gefährliche Fall wird vom Test abgedeckt.
Ein Test beweist außerdem im Dateisystem, dass das Angriffsziel gar nicht erst erstellt wird:
Nach einem Versuch von criar_nota mit slug="../vazamento" bleibt das Basisverzeichnis leer,
und die Datei außerhalb davon existiert nicht.
Darüber hinaus: keine API-Schlüssel, kein Netzwerkzugriff, und der Server liest oder schreibt niemals außerhalb des konfigurierten Verzeichnisses.
Tests
$ python3 -m pytest tests/ -q
............................................. [100%]
45 passed in 1.48sNur die Path-Traversal-Tests:
$ python3 -m pytest tests/ -q -k traversal
................. [100%]
17 passed, 28 deselected in 0.67sDie Suite deckt in dieser Reihenfolge ab:
Sanitisierung — 13 parametrisierte bösartige Eingaben (
../../etc/passwd,/etc/passwd,..\\..\\windows\\system32\\config\\sam,C:\Windows\win.ini,nota\x00.md, leere Zeichenkette…), plus der Beweis im Dateisystem, dass außerhalb der Basis nichts erstellt wird.MCP-Oberfläche —
list_toolsgibt exakt die sieben Tools zurück, und die Schemas (required,type,default,outputSchema) sind die aus den Type Hints und Docstrings generierten.Echter Aufruf jedes Tools — Erstellung mit im Dateisystem verifizierter Persistenz, Duplikat, Lesen, Lesen einer nicht existierenden Notiz, Aktualisierung, Aktualisierung mit
anexar, Auflistung mit und ohne Tag-Filter, Suche mit Ranking und mit Limit, Statistiken und Entfernung.Resources —
list_resources,list_resource_templates, Lesen des JSON-Index, Lesen einer einzelnen Notiz und die beiden Traversal-Formen.Prompts —
list_prompts,get_promptder beiden Prompts, wobei geprüft wird, dass der Inhalt der Notiz tatsächlich eingebettet ist und dass die Ausgangsnotiz nicht im Katalog der übrigen Notizen erscheint.Ende-zu-Ende-Sitzung —
create_connected_server_and_client_sessionstartet einen verbundenen MCP-Client und -Server im Speicher; der Test listet Tools, erstellt eine Notiz, listet, liest eine Ressource, holt einen Prompt und bestätigtisError: Truebeim Traversal-Versuch.Isolierter Speicher — Round-Trip des Front Matter, und Dateien, die keine Notizen sind, werden bei der Auflistung ignoriert.
Verifizierungsstatus
Alles unten wurde in dieser Umgebung ausgeführt, mit mcp 1.27.0, pytest 9.1.1 und
pytest-asyncio 1.4.0 unter Python 3.11.
✅ Verifiziert
python3 -m pytest tests/ -q→ 45 passed.Die sieben Tools tatsächlich über
FastMCP.call_toolaufgerufen, mit geprüften Ergebnissen.Die beiden Resources über
FastMCP.read_resourcegelesen; die beiden Prompts überFastMCP.get_prompt.Vollständige MCP-Sitzung Client↔Server im Speicher mit
mcp.shared.memory.create_connected_server_and_client_session.Echter stdio-Handshake: Server als Subprozess gestartet (
python3 -m mcp_notas) und eineClientSessionaus dem SDK, dieinitialize,list_toolsundcall_tooldarüber ausführt.Path Traversal in
sanitizar_slug, im Tool, in der Ressource und im Dateisystem abgewiesen.MCP_NOTAS_DIRwird respektiert: Die erstellte Notiz erschien im von der Variablen angegebenen Verzeichnis.Alle in diesem README gezeigten Ausgaben wurden aus echten Ausführungen kopiert.
⚠️ Nicht getestet
Der
mcpServers-Block wurde nicht gegen einen echten MCP-Client getestet (Claude Desktop, Editoren usw.). In dieser Umgebung ist kein Client installiert; was diese Verifizierung ersetzt, ist der oben beschriebene programmatische stdio-Handshake.Die Transporte
sseundstreamable-httpexistieren inFastMCP.run, aber dieses Projekt übt nurstdioaus.Keine Konkurrenztests: Gleichzeitige Schreibvorgänge auf dieselbe Notiz werden nicht durch einen Lock koordiniert.
Keine Tests unter Windows oder macOS — nur Linux.
Lizenz
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