Skip to main content
Glama
kzmshx
by kzmshx

frontmatter-mcp

An MCP server for querying Markdown frontmatter with DuckDB SQL.

Configuration

{ "mcpServers": { "frontmatter": { "command": "uvx", "args": ["frontmatter-mcp"], "env": { "FRONTMATTER_BASE_DIR": "/path/to/markdown/directory" } } } }

To enable semantic search, use the [semantic] extras:

{ "mcpServers": { "frontmatter": { "command": "uvx", "args": ["--from", "frontmatter-mcp[semantic]", "frontmatter-mcp"], "env": { "FRONTMATTER_BASE_DIR": "/path/to/markdown/directory", "FRONTMATTER_ENABLE_SEMANTIC": "true" } } } }

Installation (Optional)

If you prefer to install globally:

pip install frontmatter-mcp # or uv tool install frontmatter-mcp

Tools

query_inspect

Get schema information from frontmatter across files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

Example:

// Input { "glob": "**/*.md" } // Output { "file_count": 186, "schema": { "date": { "type": "string", "count": 180, "nullable": true }, "tags": { "type": "array", "count": 150, "nullable": true } } } // Output (with semantic search ready) { "file_count": 186, "schema": { "date": { "type": "string", "count": 180, "nullable": true }, "tags": { "type": "array", "count": 150, "nullable": true }, "embedding": { "type": "FLOAT[256]", "nullable": false } } }

query

Query frontmatter data with DuckDB SQL.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

sql

string

DuckDB SQL query referencing

files

table

Example:

// Input { "glob": "**/*.md", "sql": "SELECT path, date FROM files WHERE date >= '2025-11-01' ORDER BY date DESC" } // Output { "columns": ["path", "date"], "row_count": 24, "results": [ {"path": "daily/2025-11-28.md", "date": "2025-11-28"}, {"path": "daily/2025-11-27.md", "date": "2025-11-27"} ] }

update

Update frontmatter properties in a single file.

Parameter

Type

Description

path

string

File path relative to base directory

set

object

Properties to add or overwrite

unset

string[]

Property names to remove

Example:

// Input { "path": "notes/idea.md", "set": {"status": "published"} } // Output { "path": "notes/idea.md", "frontmatter": {"title": "Idea", "status": "published"} }

batch_update

Update frontmatter properties in multiple files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

set

object

Properties to add or overwrite

unset

string[]

Property names to remove

Example:

// Input { "glob": "drafts/*.md", "set": {"status": "review"} } // Output { "updated_count": 5, "updated_files": ["drafts/a.md", "drafts/b.md", ...] }

batch_array_add

Add a value to an array property in multiple files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

property

string

Name of the array property

value

any

Value to add

allow_duplicates

bool

Allow duplicate values (default: false)

Example:

// Input { "glob": "**/*.md", "property": "tags", "value": "reviewed" } // Output { "updated_count": 42, "updated_files": ["a.md", "b.md", ...] }

batch_array_remove

Remove a value from an array property in multiple files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

property

string

Name of the array property

value

any

Value to remove

Example:

// Input { "glob": "**/*.md", "property": "tags", "value": "draft" } // Output { "updated_count": 15, "updated_files": ["a.md", "b.md", ...] }

batch_array_replace

Replace a value in an array property in multiple files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

property

string

Name of the array property

old_value

any

Value to replace

new_value

any

New value

Example:

// Input { "glob": "**/*.md", "property": "tags", "old_value": "draft", "new_value": "review" } // Output { "updated_count": 10, "updated_files": ["a.md", "b.md", ...] }

batch_array_sort

Sort an array property in multiple files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

property

string

Name of the array property

reverse

bool

Sort in descending order (default: false)

Example:

// Input { "glob": "**/*.md", "property": "tags" } // Output { "updated_count": 20, "updated_files": ["a.md", "b.md", ...] }

batch_array_unique

Remove duplicate values from an array property in multiple files.

Parameter

Type

Description

glob

string

Glob pattern relative to base directory

property

string

Name of the array property

Example:

// Input { "glob": "**/*.md", "property": "tags" } // Output { "updated_count": 5, "updated_files": ["a.md", "b.md", ...] }

index_status

Get the status of the semantic search index.

This tool is only available when FRONTMATTER_ENABLE_SEMANTIC=true.

Example:

// Output (not started) { "state": "idle" } // Output (indexing in progress) { "state": "indexing" } // Output (ready) { "state": "ready" }

index_refresh

Refresh the semantic search index (differential update).

This tool is only available when FRONTMATTER_ENABLE_SEMANTIC=true.

Example:

// Output { "state": "indexing", "message": "Indexing started", "target_count": 665 } // Output (when already indexing) { "state": "indexing", "message": "Indexing already in progress" }

Technical Notes

All Values Are Strings

All frontmatter values are passed to DuckDB as strings. Use TRY_CAST in SQL for type conversion when needed.

SELECT * FROM files WHERE TRY_CAST(date AS DATE) >= '2025-11-01'

Arrays Are JSON Strings

Arrays like tags: [ai, python] are stored as JSON strings '["ai", "python"]'. Use from_json() and UNNEST to expand them.

SELECT path, tag FROM files, UNNEST(from_json(tags, '[""]')) AS t(tag) WHERE tag = 'ai'

Templater Expression Support

Files containing Obsidian Templater expressions (e.g., <% tp.date.now("YYYY-MM-DD") %>) are handled gracefully. These expressions are treated as strings and naturally excluded by date filtering.

When semantic search is enabled, you can use the embed() function and embedding column in SQL queries. After running index_refresh, the markdown body content is indexed as vectors.

-- Find semantically similar documents SELECT path, 1 - array_cosine_distance(embedding, embed('feeling better')) as score FROM files ORDER BY score DESC LIMIT 10 -- Combine with frontmatter filters SELECT path, date, 1 - array_cosine_distance(embedding, embed('motivation')) as score FROM files WHERE date >= '2025-11-01' ORDER BY score DESC LIMIT 10

Environment variables:

Variable

Default

Description

FRONTMATTER_BASE_DIR

(required)

Base directory for files

FRONTMATTER_ENABLE_SEMANTIC

false

Enable semantic search

FRONTMATTER_EMBEDDING_MODEL

cl-nagoya/ruri-v3-30m

Embedding model name

FRONTMATTER_CACHE_DIR

FRONTMATTER_BASE_DIR/.frontmatter-mcp

Cache directory for embeddings

License

MIT

-
security - not tested
A
license - permissive license
-
quality - not tested

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/kzmshx/frontmatter-mcp'

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