Skip to main content
Glama

mcp-brain

A Model Context Protocol (MCP) server that provides controlled access to local Brain notes.

Features

This MCP server implements the following tools:

  • search_notes(query) - Search note filenames and note content (case-insensitive)

  • list_notes(path?) - List folders and files under the configured Brain path

  • read_note(path) - Read one note file by relative path

Built-in safeguards:

  • Path traversal protection (cannot read outside the configured Brain root)

  • Configurable file size limit for reads/search

  • Configurable maximum number of search results

Related MCP server: Yaps MCP

Prerequisites

  • Python 3.11 or higher

  • A local notes folder (default is ./brain)

Installation

Local Installation (.venv)

  1. Create and activate a virtual environment:

python3 -m venv .venv
source .venv/bin/activate
  1. Install the project:

python -m pip install --upgrade pip
python -m pip install -e .
  1. Optional: copy environment template:

cp .env.example .env
  1. Run the server (stdio transport):

BRAIN_PATH=./brain brain-mcp

Docker

Build image

docker build -t mcp-brain .

Run container

docker run -i \
	-e BRAIN_PATH=/brain \
	-e BRAIN_MAX_RESULTS=10 \
	-e BRAIN_MAX_FILE_SIZE=1048576 \
	-v "$(pwd)/brain:/brain:ro" \
	mcp-brain

Docker Compose

The included compose file follows the same structure as the reference project and starts a stdio-oriented container.

  1. Optional: copy the environment template:

cp .env.example .env
  1. Start the service:

docker compose -f compose.yml up --build
  1. Run it as a one-off interactive test:

docker compose -f compose.yml run --rm brain-mcp

Configuration

Environment Variables

Variable

Required

Description

BRAIN_PATH

No

Root path of notes directory (default: ./brain locally, /brain in container)

BRAIN_MAX_RESULTS

No

Maximum returned search hits (default: 10)

BRAIN_MAX_FILE_SIZE

No

Max readable file size in bytes (default: 1048576)

MCP Client Integration

Claude Desktop

Add a server entry to your configuration:

{
	"mcpServers": {
		"brain": {
			"command": "/absolute/path/to/mcp-brain/.venv/bin/brain-mcp",
			"env": {
				"BRAIN_PATH": "/absolute/path/to/mcp-brain/brain",
				"BRAIN_MAX_RESULTS": "10",
				"BRAIN_MAX_FILE_SIZE": "1048576"
			}
		}
	}
}

VS Code MCP Settings

{
	"mcp": {
		"servers": {
			"brain": {
				"command": "/absolute/path/to/mcp-brain/.venv/bin/brain-mcp",
				"env": {
					"BRAIN_PATH": "/absolute/path/to/mcp-brain/brain",
					"BRAIN_MAX_RESULTS": "10",
					"BRAIN_MAX_FILE_SIZE": "1048576"
				}
			}
		}
	}
}

Testing

Unit Tests

./.venv/bin/python -m pytest -q

End-to-End MCP Smoke Test (Tool Calls)

This starts your server over stdio and calls all tools via the MCP Python client.

BRAIN_PATH=./brain ./.venv/bin/python - <<'PY'
import anyio
from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client

async def main():
		params = StdioServerParameters(
				command="brain-mcp",
				env={
						"BRAIN_PATH": "./brain",
						"BRAIN_MAX_RESULTS": "10",
						"BRAIN_MAX_FILE_SIZE": "1048576",
				},
		)
		async with stdio_client(params) as (read_stream, write_stream):
				async with ClientSession(read_stream, write_stream) as session:
						await session.initialize()

						tools = await session.list_tools()
						print("TOOLS:", [tool.name for tool in tools.tools])

						print("LIST:", (await session.call_tool("list_notes", {"path": "People"})).model_dump())
						print("READ:", (await session.call_tool("read_note", {"path": "People/John Smith.md"})).model_dump())
						print("SEARCH:", (await session.call_tool("search_notes", {"query": "john"})).model_dump())

anyio.run(main)
PY

One-Command Quick Test Script

Use the helper script if you only want to pass a query string and get a quick response.

Local server mode:

./.venv/bin/python scripts/quick_mcp_test.py "john"

With custom list path:

./.venv/bin/python scripts/quick_mcp_test.py "festival" --list-path Projects

Against a running Docker container:

./.venv/bin/python scripts/quick_mcp_test.py "john" --container brain-mcp

Tools Reference

search_notes

Search filenames and file contents for a query.

Input:

{
	"query": "john"
}

Output (example):

{
	"query": "john",
	"files_scanned": 12,
	"count": 2,
	"max_results": 10,
	"matches": [
		{
			"path": "People/John Smith.md",
			"size": 321,
			"line": 1,
			"snippet": "John is a designer..."
		}
	]
}

list_notes

List files and folders under the root or a subpath.

Input:

{
	"path": "People"
}

Output (example):

{
	"path": "People",
	"count": 1,
	"entries": [
		{
			"name": "John Smith.md",
			"path": "People/John Smith.md",
			"type": "file",
			"size": 321
		}
	]
}

read_note

Read one note file by relative path.

Input:

{
	"path": "People/John Smith.md"
}

Output (example):

{
	"path": "People/John Smith.md",
	"size": 321,
	"content": "...full note text..."
}

Troubleshooting

AttributeError: 'Server' object has no attribute 'list_tools'

Cause: old MCP v1 server style with MCP v2 runtime.

Fix: this project already uses MCP v2 MCPServer APIs and depends on mcp>=2.0.0 in pyproject.toml. Reinstall:

./.venv/bin/python -m pip install -e .

Brain path does not exist

Set BRAIN_PATH correctly and ensure the folder exists:

BRAIN_PATH=./brain brain-mcp

Path is outside of the configured brain directory

This is expected protection against path traversal. Use a path relative to BRAIN_PATH.

Project Structure

mcp-brain/
├── src/brain_mcp/
│   ├── __init__.py
│   ├── brain.py
│   ├── config.py
│   ├── security.py
│   └── server.py
├── tests/
│   └── test_brain.py
├── brain/
├── Dockerfile
├── compose.yml
├── pyproject.toml
├── .env.example
└── README.md

License

MIT License - see LICENSE.

Available Tools

3 tools
list_notesA

List files and folders in the brain directory, optionally under a subpath.

Inputs: path. Returns: object

read_noteA

Read a single note file from the brain directory.

Inputs: path (required). Returns: object

search_notesA

Search notes by filename and content using a case-insensitive query.

Inputs: query (required). Returns: object

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 3 tools

    Disambiguation5/5

    Each tool maps to a distinct action on the notes collection: searching across content, listing the directory structure, and reading a specific file. There is no functional overlap between the tools.

    Naming Consistency5/5

    All three tools follow a clear verb_noun pattern with snake_case: search_notes, list_notes, and read_note. The singular 'note' is semantically accurate for reading one file)Skip

    Tool Count5/5

    The server is intentionally scoped to three essential read operations for a personal-knowledge directory. Each tool serves a unique purpose, and the small count is appropriate for a lightweight, focused MCP server.

    Completeness4/5

    The read-side surface is well covered: you can discover, search, and view notes. The only notable gap is the absence of any create, update, or delete operations, so if the brain is meant to be fully managed through MCP, the surface is incomplete.

    Maintenance

    ActivitySlowing
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      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
    • A
      license
      Not graded
      quality
      C
      maintenance
      Provides controlled, read-only or write-enabled access to a private local Yaps Markdown vault, enabling AI clients to search, read, and manage notes securely.
      MIT
    • F
      license
      A
      quality
      C
      maintenance
      Enables listing, reading, and searching local Markdown notes through MCP tools and exposing them as context resources, with protection against path traversal attacks.
      3
      -