metadata_mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@metadata_mcpread metadata from photos/vacation.jpg"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
metadata_mcp
For the tool-routing architecture and constraints, see DESIGN.md.
Author: Jim Lehmer
License: MIT
A Model Context Protocol (MCP) server that gives coding agents compact file context plus embedded and semantic document metadata across a broad range of formats. Connect it to any MCP-compatible client and inspect filesystem, content type, Git facts, document attributes, and format-specific tags without rebuilding the relevant parsers in every agent.
Why the name?
This server started as a thin ExifTool wrapper. It has since grown a compact, cross-file context probe; a Pandoc semantic-document reader; and backends for audio formats ExifTool can't write (mutagen) and text-based formats with no binary metadata section (HTML, Markdown). "exiftool_mcp" no longer described it; "metadata_mcp" does.
Related MCP server: EXIF MCP Server
First call for coding agents: inspect_file
Use inspect_file for one exact path before reading source or embedded tags. It returns independently computed sections, so a missing optional command (such as Git or file) does not hide valid filesystem facts.
# Compact file context: stat attributes, libmagic type, Git status, and last file commit
inspect_file(path="server.py")
# Attribute only the source lines relevant to a change request
inspect_file(path="server.py", blame_start_line=85, blame_end_line=120)Its default response includes:
Filesystem — normalized and resolved paths, kind, symlink status, size/allocation, permissions, owner IDs on POSIX, and UTC timestamps.
Content type — libmagic (
file) description, MIME type, and encoding. Iffileis unavailable, extension-based values are returned only as an explicitly labeled fallback.Git — worktree root, branch and HEAD, tracking/worktree status, and the last commit affecting the file. Files outside a Git worktree receive an explicit
not_repositorystatus.
Git blame is never returned unless both inclusive line bounds are supplied. inspect_file does not return document or embedded tags. Use read_document_attributes for semantic text-document attributes and read_metadata for potentially verbose embedded/container tags.
Semantic text-document attributes: read_document_attributes
Use this exact-path, read-only tool when a document's meaning-bearing attributes matter: title, author, date, language, description, keywords, YAML-frontmatter values, and similar fields. It asks Pandoc to read the document into its JSON AST, then returns a compact normalized view rather than document content.
# Markdown YAML frontmatter, including custom scalar/list fields
read_document_attributes(path="proposal.md")
# HTML title, author, description, language, and standard meta fields
read_document_attributes(path="site/about.html")
# Inspect nested notebook metadata only when it is specifically needed
read_document_attributes(path="analysis.ipynb", include_full_metadata=True)Supported inferred readers include Markdown, HTML/XHTML, RST, Org, RTF, LaTeX, Jupyter notebooks, DocBook/JATS, OPML, and several wiki/text-markup formats. For an unusual extension, pass an explicit Pandoc source_format.
This tool is deliberately not the route for PDF, legacy Word/OLE, OOXML (.docx, .xlsx, .pptx and related files), OpenDocument, or EPUB. Use read_metadata for those formats: ExifTool exposes their core, application, and custom/container properties more completely than Pandoc. Pandoc cannot read PDF, and local verification shows its DOCX reader can omit Word subject and custom properties.
Backend Architecture
The server dispatches automatically to the right backend based on file extension. You never need to specify which backend to use.
Format(s) | Embedded/container metadata | Semantic attributes | Write backend |
JPEG, TIFF, PNG, HEIC, WebP, RAW, GIF… | ExifTool | — | ExifTool |
PDF, Word/OLE, OOXML, ODF, EPUB | ExifTool | Use | ExifTool where supported |
MP4, MOV, MKV, AVI… | ExifTool | — | ExifTool |
MP3 | ExifTool | — | mutagen — ID3v2 frames |
OGG, Opus | ExifTool | — | mutagen — Vorbis comment tags |
HTML, XHTML | ExifTool raw tags | Pandoc normalized fields |
|
Markdown, RST, Org, LaTeX, notebooks, markup | Limited or format-dependent | Pandoc normalized fields | YAML frontmatter for Markdown |
ExifTool
Handles the widest range of formats. Required for reading metadata from any format and for writing to images, video, and PDF. Must be installed separately and on PATH.
mutagen
Used for audio formats ExifTool can write only partially or not at all. Installed as a Python dependency in the server venv. Tag names are mapped to the appropriate ID3v2 frame (MP3) or used verbatim as Vorbis comment keys (OGG/Opus).
Pandoc document reader
read_document_attributes uses pypandoc and a locally installed Pandoc executable to read semantic metadata from text-centric documents. Its default response includes scalar and list attributes only. Nested metadata maps are named in omitted_attributes; set include_full_metadata=True only when their raw Pandoc AST is worth the additional context.
ID3v2 tag name map (MP3):
Tag name (case-insensitive) | ID3v2 frame |
Comment | COMM |
Title | TIT2 |
Artist | TPE1 |
AlbumArtist | TPE2 |
Album | TALB |
TrackNumber / Track | TRCK |
Genre | TCON |
Date / Year | TDRC |
Description | TIT3 |
Encoder | TSSE |
Copyright | TCOP |
In-process text handlers
For formats with no binary metadata section:
HTML: injects or updates a
<meta name="..." content="...">tag before</head>. The ExifTool tag name is mapped to a standard HTML meta name (Comment→description, etc.); unknown tags are lowercased and used verbatim.Markdown: writes or updates a YAML frontmatter block (
--- ... ---) at the top of the file. The tag name is lowercased directly as the YAML key — no fixed mapping, any attribute works.
Bulk Operations
ExifTool-backed tools accept glob patterns and directory paths natively — ExifTool handles the expansion. This covers read_metadata, set_copyright, strip_metadata, set_author, set_description, set_gps, copy_metadata, and write_metadata for images/video/PDF.
For write_metadata on audio (MP3/OGG/Opus) and text (HTML/Markdown) formats, the server expands globs in Python before dispatching to the format-specific backend. All bulk operations happen in a single tool call — no loop needed.
# Read metadata from every photo — one call, no loop
read_metadata(path="photos/*.jpg")
# Set copyright on every photo — one call, no loop
set_copyright(path="photos/*.jpg", copyright="© 2026 Jim Lehmer")
# Strip metadata from every export — one call, no loop
strip_metadata(path="exports/*.jpg")
# Write ID3 tags to every MP3 — one call, no loop
write_metadata(path="music/*.mp3", tags={"Artist": "Jim Lehmer", "Album": "Demo"})
# Write EXIF to every JPEG — one call, no loop
write_metadata(path="photos/*.jpg", tags={"Copyright": "© 2026"})
# Recursive operation via passthrough
exiftool_passthrough(arguments=["-r", "-all=", "exports/"])Tools
inspect_file
Compact, read-only context for one exact file or directory path. This is the preferred first tool for coding agents.
Parameter | Type | Default | Description |
|
| required | One exact path; glob patterns are not expanded |
|
| optional | First line for bounded Git blame; requires |
|
| optional | Last inclusive line for bounded Git blame; requires |
read_document_attributes
Read compact semantic attributes from one Pandoc-readable text document. It does not modify the document or expand globs.
Parameter | Type | Default | Description |
|
| required | One exact path |
|
| inferred | Pandoc reader for an unusual/ambiguous extension |
|
|
| Include the full raw Pandoc metadata AST, including nested maps |
The response contains attributes, omitted_attributes, selected source_format, and the installed Pandoc version. For PDF, Office/OOXML, OpenDocument, and EPUB, it returns a not_applicable response that directs the caller to read_metadata.
read_metadata
Read all metadata tags from any file. Uses ExifTool.
Parameter | Type | Description |
|
| File to read |
write_metadata
Write arbitrary tag=value pairs to a file. Backend is chosen automatically.
Parameter | Type | Description |
|
| File to write |
|
| Tag names and values, e.g. |
set_copyright
Set Copyright tag on a file or directory (ExifTool). Recursive flag available.
Parameter | Type | Default | Description |
|
| required | File or directory path |
|
| required | Copyright text |
|
|
| Apply to all files in directory recursively |
set_author
Set Author tag (ExifTool).
Parameter | Type | Description |
|
| File path |
|
| Author name |
set_description
Set Description tag (ExifTool).
Parameter | Type | Description |
|
| File path |
|
| Description text |
set_gps
Set GPS coordinates (ExifTool).
Parameter | Type | Default | Description |
|
| required | File path |
|
| required | GPS latitude |
|
| required | GPS longitude |
|
|
|
|
|
|
|
|
|
| optional | Altitude in metres |
|
|
|
|
copy_metadata
Copy metadata from source to destination (ExifTool).
Parameter | Type | Default | Description |
|
| required | Source file |
|
| required | Destination file |
|
| optional | Restrict to these tag names |
strip_metadata
Strip all metadata from a file or directory (ExifTool).
Parameter | Type | Default | Description |
|
| required | File or directory path |
|
|
| Apply recursively |
exiftool_passthrough
Run arbitrary ExifTool CLI commands for operations not covered by the tools above.
Parameter | Type | Description |
|
| Raw ExifTool CLI arguments (omit |
Requirements
Python 3.10+
ExifTool installed and on
PATHGit installed and on
PATHfor repository context and blame (optional)A
filecommand backed by libmagic for content sniffing (optional; extension fallback is labeled)Pandoc installed and on
PATHfor semantic document attributes (optional)Python packages:
mcp[cli],mutagen,pypandoc(seerequirements.txt)
Installation
git clone https://github.com/dullroar/metadata_mcp.git
cd metadata_mcp
python -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
pip install -r requirements.txtMCP Client Configuration
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"metadata": {
"command": "/path/to/metadata_mcp/.venv/bin/python",
"args": ["/path/to/metadata_mcp/server.py"]
}
}
}Claude Code
claude mcp add metadata -- /path/to/metadata_mcp/.venv/bin/python /path/to/metadata_mcp/server.pyHTTP/SSE mode
python server.py --transport sse
# Listening on http://127.0.0.1:8000/sseFlag | Default | Description |
|
|
|
|
| Bind address |
|
| Bind port |
Example Prompts
"Inspect this file before editing it; tell me its type, Git state, and last commit."
"Who last changed lines 85 through 120 of this file?"
"What are this Markdown document's frontmatter attributes?"
"Read the title, author, description, and language from this HTML file."
"Show the full notebook metadata only if its compact document attributes omit something relevant."
"Read all the metadata from this photo and tell me what camera was used."
"Read the metadata from every photo in photos/ and summarize what cameras were used."
"Set the Comment field on this MP3 to 'ripped from vinyl'."
"Set the Artist and Album on every MP3 in music/ to 'Jim Lehmer' and 'Demo'."
"Add an Author and Copyright field to this Markdown file."
"Inject a description meta tag into this HTML page."
"Set copyright on every JPEG in photos/ to '© 2026 Jim Lehmer'."
"Copy all metadata from original.jpg to backup.jpg."
"Strip all metadata from this file before uploading."
"Strip all metadata from every JPEG in exports/ before I upload them."
"Set my GPS coordinates on this photo to geotag my travels."
Project-context templates for file-heavy work
This repository includes sample-CLAUDE.md and sample-AGENTS.md. They have identical content and are intentionally prefixed with sample- so they do not govern this MCP project.
For a project that will read or manipulate many files, copy the template appropriate to its agent environment into that project, then remove the prefix: sample-CLAUDE.md → CLAUDE.md or sample-AGENTS.md → AGENTS.md. The template directs future agents to use this server's registered tools before ad-hoc parsing or metadata-writing code, preserving bounded context, reproducible extraction, and a shared cross-agent tool vocabulary.
Testing with the MCP Inspector
mcp dev server.pyLicense
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
- RendobarOAuthcom.rendobar
Transform video, audio and images, and generate media from prompts. FFmpeg, captions, models.
Convert and compress PDFs and images, redact personal data, and run text and data utilities.
Geometry and CAD file metadata extraction for STL, OBJ, PLY, PCD, LAS/LAZ, glTF/GLB.
- MochifyOAuthapp.mochify
Image and PDF toolkit: convert to AVIF/WebP/JXL, resize, crop, remove backgrounds, optimize PDFs.
Related MCP Servers
- -licenseBqualityNot gradedmaintenanceEnables comprehensive video file metadata management including reading, editing, and batch processing of video properties like title, description, tags, and technical specifications. Supports multiple video formats with intelligent caching and search capabilities.89 npm1-
- AlicenseAqualityDmaintenanceInspect and remove EXIF metadata locally through MCP tools. Supports reading EXIF, detecting GPS, summarizing privacy risks, and stripping EXIF from images.113MIT
- AlicenseNot gradedqualityDmaintenanceEnables reading, writing, and removing metadata from over 150 file formats using ExifTool, supporting EXIF, IPTC, XMP, GPS, and manufacturer-specific metadata.27 PyPIMIT
- AlicenseNot gradedqualityDmaintenanceProvides tools for AI clients to scan, match, and scrape TMDB metadata for local media files, with safe sidecar writing or full Jellyfin-style reorganization including file renaming and NFO generation.MIT