Skip to main content
Glama
utils.py3.54 kB
"""Utility functions for the Zettelkasten MCP server.""" import logging import sys from datetime import datetime from typing import Optional def setup_logging(level: str = "INFO", log_file: Optional[str] = None): """Set up logging configuration. Args: level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL) log_file: Optional path to a log file """ # Convert string level to logging level numeric_level = getattr(logging, level.upper(), None) if not isinstance(numeric_level, int): numeric_level = logging.INFO # Base configuration log_config = { "level": numeric_level, "format": "%(asctime)s [%(levelname)s] %(name)s: %(message)s", "datefmt": "%Y-%m-%d %H:%M:%S", } # Add file handler if log file is specified if log_file: log_config["filename"] = log_file log_config["filemode"] = "a" else: # Otherwise, log to stderr log_config["stream"] = sys.stderr # Apply configuration logging.basicConfig(**log_config) def generate_timestamp_id() -> str: """Generate a timestamp-based ID in ISO 8601 Zettelkasten format with nanosecond precision. Returns: A string in format "YYYYMMDDTHHMMSSsssssssss" where: - YYYYMMDD is the date - T is the ISO 8601 date/time separator - HHMMSS is the time (hours, minutes, seconds) - sssssssss is the 9-digit nanosecond component """ # Get nanoseconds since epoch ns_timestamp = time.time_ns() # Convert to seconds and nanosecond fraction seconds = ns_timestamp // 1_000_000_000 nanoseconds = ns_timestamp % 1_000_000_000 # Convert seconds to datetime timestamp = datetime.fromtimestamp(seconds) # Format as ISO 8601 basic format (YYYYMMDDThhmmss) with nanoseconds date_time = timestamp.strftime('%Y%m%dT%H%M%S') # Return the ISO 8601 timestamp with nanosecond precision return f"{date_time}{nanoseconds:09d}" def parse_tags(tags_str: str) -> list[str]: """Parse a comma-separated list of tags into a list of tag strings. Args: tags_str: Comma-separated string of tags Returns: List of tag strings """ if not tags_str: return [] return [tag.strip() for tag in tags_str.split(",") if tag.strip()] def format_note_for_display(title: str, id: str, content: str, tags: list[str], created_at: datetime, updated_at: datetime, links: Optional[list] = None) -> str: """Format a note for display in the console. Args: title: Note title id: Note ID content: Note content tags: List of tags created_at: Creation timestamp updated_at: Update timestamp links: Optional list of links Returns: Formatted string representation of the note """ result = f"# {title}\n" result += f"ID: {id}\n" result += f"Created: {created_at.isoformat()}\n" result += f"Updated: {updated_at.isoformat()}\n" if tags: result += f"Tags: {', '.join(tags)}\n" result += f"\n{content}\n" if links: result += "\n## Links\n" for link in links: if hasattr(link, "description") and link.description: result += f"- {link.link_type.value}: {link.target_id} - {link.description}\n" else: result += f"- {link.link_type.value}: {link.target_id}\n" return result

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/Liam-Deacon/zettelkasten-mcp'

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