Skip to main content
Glama

mcp-server-example — Markdownノートベース用MCPサーバー

動作確認済みの実用的なMCP(Model Context Protocol)サーバーのサンプルです。アシスタントに セカンドブレインへのアクセスを提供します。ローカルのMarkdownノートディレクトリに対して、 作成・読み取り・更新・一覧表示・検索・統計を実行できます。

ここでの焦点は機能の多さではなく、誠実なMCPサーバーを示すことです。型ヒントから生成される スキーマ、パストラバーサルに対する本物のサニタイズ、そして呼び出しをモックするのではなく 実際にツールを呼び出すテストスイートを備えています。


MCPとは

Model Context Protocolは、アシスタントが外部システムと対話する方法を標準化するオープンプロトコルです。 各アプリケーションが独自のプラグインフォーマットを考案する代わりに、MCPサーバーは3つのものを宣言します — tools(モデルが実行できるアクション)、resources(URIでアドレス指定され、読み取り可能なデータ)、 prompts(ユーザーが呼び出せる会話テンプレート)— そして互換性のあるクライアントはこれらすべてを 自動的に発見して使用します。通信はJSON-RPCで、通常はstdio上で行われます。クライアントはサーバーを サブプロセスとして起動し、標準入出力を介してメッセージを交換します。


Related MCP server: Notes MCP Server

含まれるもの

ファイル

機能

mcp_notas/server.py

FastMCPサーバーを定義: tools、resources、prompts、およびPydantic出力モデル。

mcp_notas/storage.py

ディスクI/Oと識別子のサニタイズをすべて担当。パスを構築する唯一の場所。

mcp_notas/search.py

フィールド別ランキング(タイトル > タグ > 本文)、アクセント非依存のテキスト検索。

mcp_notas/__main__.py

python3 -m mcp_notasのエントリポイント。

tests/test_server.py

実際のサーバーを実行する45のテスト。完全なMCPセッションを含む。

requirements.txt

ランタイムおよびテストの依存関係。

pytest.ini

pytest-asyncioの設定。

各ノートは最小限のフロントマターを持つ.mdファイルです:

---
title: Teste env
tags: []
created: 2026-08-25T00:20:24+00:00
updated: 2026-08-25T00:20:24+00:00
---

サーバーが公開するもの

Tools

Tool

引数

戻り値

criar_nota

titulo(必須)、corpotagsslug

日付が入力された作成済みノート。

ler_nota

slug

完全なノート(本文、タグ、日付)。

atualizar_nota

slugcorpotitulotagsanexar

更新済みのノート。

apagar_nota

slug

テキストでの確認メッセージ。

listar_notas

tag(オプション)

各ノートの合計と概要(本文なし)。

buscar_notas

consultalimite

関連性順に並べられた結果(抜粋付き)。

estatisticas_base

件数、最も使用されているタグ、最長ノート。

Resources

URI

タイプ

内容

notas://index

application/json

ベース全体のインデックス: 各ノートのslug、タイトル、タグ、URI。

notas://{slug}

text/markdown

フロントマターを含むノートの完全なMarkdown。

Prompts

Prompt

引数

組み立てる内容

resumir_nota

slugtamanhocurto/longo

ノートの内容がすでに埋め込まれた要約リクエスト。

sugerir_conexoes

slugquantidade

4つのメッセージ: 指示、開始ノート、他のノートのカタログ、アシスタントの冒頭。


インストール

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)、2番目のノートの本文にのみあります(スコア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.

そして、サーバーをサブプロセスとして実行し、SDKのClientSessionを反対側に置いた、stdio経由の 実際のハンドシェイク(サーバーの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) / slugslug = "../../etc/passwd"の場合、プロンプトを 制御する者にディスク全体を渡すことになります。

ここでの防御はmcp_notas/storage.pyにあり、2つの層があります。

1. sanitizar_slug() — 許可リストによる検証。 識別子は、パス区切り文字(/\)、 ヌルバイト、Windowsドライブ文字(C:)、および..の出現を明示的に拒否した後、 ^[a-z0-9][a-z0-9._-]{0,79}$に一致する場合のみ通過します。文字または数字で始まることを 要求することで、.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.

notas://{slug}リソースも同じ保護があり、しかも2つの異なる経路で保護されています: 生のURI notas://../../etc/passwdはテンプレートに一致しません(Unknown resource)が、パーセントエンコードされた 形式notas://..%2F..%2Fetc%2Fpasswdは一致し、サニタイズに到達してそこでブロックされます — 危険なのはこの2番目のケースであり、テストがカバーしているのはこれです。

また、テストはファイルシステム上で、攻撃対象が作成されないことを証明します: 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

スイートは順に以下をカバーします:

  1. サニタイズ — パラメータ化された13の悪意のある入力(../../etc/passwd/etc/passwd..\\..\\windows\\system32\\config\\samC:\Windows\win.ininota\x00.md、空文字列…)、 さらにベースの外に何も作成されないことのディスク上での証明。

  2. MCPサーフェスlist_toolsは正確に7つのツールを返し、スキーマ(requiredtypedefaultoutputSchema)は型ヒントとdocstringから生成されたものです。

  3. 各ツールの実際の呼び出し — ディスク上で永続化を確認した作成、重複、読み取り、 存在しないものの読み取り、更新、anexarでの更新、タグフィルターありとなしの一覧表示、 ランキングと制限付きの検索、統計、削除。

  4. Resourceslist_resourceslist_resource_templates、JSONインデックスの読み取り、 個別ノートの読み取り、および2つのトラバーサル形式。

  5. Promptslist_prompts、2つのプロンプトのget_prompt。ノートの内容が実際に埋め込まれ、 開始ノートが他のノートのカタログに表示されないことを確認。

  6. エンドツーエンドセッションcreate_connected_server_and_client_sessionは、メモリ内で 接続されたMCPクライアントとサーバーを起動します。テストはtoolsの一覧表示、ノートの作成、 一覧表示、リソースの読み取り、プロンプトの取得を行い、トラバーサル試行でisError: Trueを確認します。

  7. 分離されたストレージ — フロントマターのラウンドトリップと、ノートではないファイルが 一覧表示で無視されること。


検証ステータス

以下はすべてこの環境で、mcp 1.27.0、pytest 9.1.1、pytest-asyncio 1.4.0、Python 3.11で 実行されました。

検証済み

  • python3 -m pytest tests/ -q45 passed

  • 7つのツールがFastMCP.call_tool経由で実際に呼び出され、結果が確認されました。

  • 2つのリソースがFastMCP.read_resource経由で読み取られ、2つのプロンプトがFastMCP.get_prompt経由で取得されました。

  • mcp.shared.memory.create_connected_server_and_client_sessionによるメモリ内の完全なMCPクライアント↔サーバーセッション。

  • 実際のstdioハンドシェイク: サーバーがサブプロセス(python3 -m mcp_notas)として起動され、 SDKのClientSessioninitializelist_toolscall_toolを実行しました。

  • パストラバーサルがsanitizar_slug、ツール、リソース、ファイルシステムで拒否されました。

  • MCP_NOTAS_DIRが尊重されました: 作成されたノートは変数が指すディレクトリに表示されました。

  • このREADMEに示されているすべての出力は、実際の実行からコピーされたものです。

⚠️ 未テスト

  • mcpServersブロックは実際のMCPクライアント(Claude Desktop、エディタなど)に対してテストされていません。 この環境にはクライアントがインストールされていません。この検証の代わりとなるのは、上記の プログラムによるstdioハンドシェイクです。

  • sseおよびstreamable-httpトランスポートはFastMCP.runに存在しますが、このプロジェクトは stdioのみを実行します。

  • 並行性テストなし: 同じノートへの同時書き込みはロックで調整されていません。

  • WindowsまたはmacOSでのテストなし — Linuxのみ。


ライセンス

MIT

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

  • F
    license
    Not graded
    quality
    D
    maintenance
    Manages markdown notes in a specified directory, allowing users to create, read, update, and list notes through the Model Context Protocol.
    1
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI assistants to search, read, create, update, and remove personal markdown notes stored locally, providing persistent memory across sessions.
    13
    2
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to interact with a local folder of Markdown notes, supporting listing, reading, searching, creating, and appending to notes with strict security boundaries.
    5
    MIT

View all related MCP servers

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.

View all MCP Connectors

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/herickbrandao483-jpg/mcp-server-example'

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