We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/suhailnajeeb/obsidian-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
"""Tool for viewing images embedded in notes."""
import re
import base64
from typing import List, Optional
from fastmcp import Context, Image
from ..utils.filesystem import get_vault
from ..utils import validate_note_path, sanitize_path
from ..constants import ERROR_MESSAGES
async def view_note_images(
path: str,
image_index: Optional[int] = None,
max_width: int = 1600,
ctx: Optional[Context] = None
) -> List[Image]:
"""
Extract and display images embedded in a note.
Use this tool to view images that are referenced within a note's content.
This is separate from read_note to ensure proper image display in MCP clients.
Args:
path: Path to the note containing images
image_index: Optional specific image index to display (0-based)
max_width: Maximum width for automatic resizing in pixels (default: 800)
ctx: MCP context for progress reporting
Returns:
List of Image objects from the note (or single image if index specified)
Example:
>>> # View all images in a note
>>> await view_note_images("Projects/Design.md")
[<Image>, <Image>, ...]
>>> # View specific image by index
>>> await view_note_images("Projects/Design.md", image_index=0)
[<Image>]
"""
# Validate path
is_valid, error_msg = validate_note_path(path)
if not is_valid:
raise ValueError(f"Invalid path: {error_msg}")
path = sanitize_path(path)
if ctx:
ctx.info(f"Extracting images from note: {path}")
vault = get_vault()
# Read the note to get its content
try:
note = await vault.read_note(path)
except FileNotFoundError:
raise FileNotFoundError(ERROR_MESSAGES["note_not_found"].format(path=path))
# Extract image references
wiki_pattern = r'!\[\[([^]]+\.(?:png|jpg|jpeg|gif|webp|svg|bmp|ico))\]\]'
markdown_pattern = r'!\[[^\]]*\]\(([^)]+\.(?:png|jpg|jpeg|gif|webp|svg|bmp|ico))\)'
image_paths = []
# Find wiki-style embeds
for match in re.finditer(wiki_pattern, note.content, re.IGNORECASE):
image_paths.append(match.group(1))
# Find markdown-style embeds
for match in re.finditer(markdown_pattern, note.content, re.IGNORECASE):
image_paths.append(match.group(1))
if not image_paths:
if ctx:
ctx.info("No images found in this note")
return []
if ctx:
ctx.info(f"Found {len(image_paths)} image(s) in note")
# If specific index requested, validate it
if image_index is not None:
if image_index < 0 or image_index >= len(image_paths):
raise ValueError(f"Invalid image index {image_index}. Note contains {len(image_paths)} images (0-{len(image_paths)-1})")
image_paths = [image_paths[image_index]]
# Load and convert images to Image objects
images = []
for i, image_ref in enumerate(image_paths):
try:
if ctx:
ctx.info(f"Loading image {i+1}/{len(image_paths)}: {image_ref}")
# Try to read the image directly
try:
image_data = await vault.read_image(image_ref, max_width=max_width)
except FileNotFoundError:
# If not found at direct path, search for it
filename = image_ref.split('/')[-1]
found_path = await vault.find_image(filename)
if found_path:
if ctx:
ctx.info(f"Found image at: {found_path}")
image_data = await vault.read_image(found_path, max_width=max_width)
else:
if ctx:
ctx.info(f"Could not find image: {image_ref}")
continue
# Convert to Image object
image_bytes = base64.b64decode(image_data["content"])
# Extract format from mime type
mime_to_format = {
"image/png": "png",
"image/jpeg": "jpeg",
"image/jpg": "jpeg",
"image/gif": "gif",
"image/webp": "webp",
"image/svg+xml": "svg",
"image/bmp": "bmp",
"image/x-icon": "ico"
}
format_type = mime_to_format.get(image_data["mime_type"], "png")
images.append(Image(data=image_bytes, format=format_type))
except Exception as e:
if ctx:
ctx.info(f"Error loading image {image_ref}: {str(e)}")
continue
return images